{"version":3,"file":"default/js/cart.js","mappings":";uBAAIA,2CCGJ,MAAMC,EAAiBC,EAAQ,MAe/B,MAAMC,UAAkBC,YACpBC,WAAAA,CAAYC,GACRC,QAEAC,KAAKC,SAAU,EACfD,KAAKE,KAAOF,KAAKE,KAAKC,KAAKH,MAC3BA,KAAKI,KAAO,KAEZ,MAAMC,EAAgBP,GAAYQ,SAASC,MACA,QAA1BF,EAAcG,QAAoBH,EAAcA,cAAgBA,GACxEI,YAAYT,MAErBA,KAAKU,OAASC,IAAAA,cAAqB,CAC/BC,UAAWZ,KAAKI,KAAKS,cAAc,YACnCC,SAAU,MACVC,MAAM,EACNC,UAAU,EACVC,cAAexB,GAEvB,CAOAyB,KAAAA,CAAMC,GACF,OAAO,IAAIC,SAASC,IACZrB,KAAKC,SAASoB,IAGK,WAFAC,OAAOC,iBAAiBvB,KAAKK,eAAemB,iBAAiB,cAG7C,SAA/BxB,KAAKK,cAAcG,UACnBR,KAAKK,cAAcoB,MAAMC,SAAW,YAExC1B,KAAKK,cAAcsB,UAAUC,IAAI,WAGjCT,GACAnB,KAAKI,KAAKyB,mBAAmB,YAAa,wBAAwBV,WAGtEnB,KAAKC,SAAU,EACf6B,YAAW,KACH9B,KAAKC,UACLD,KAAKU,QAAQqB,OACb/B,KAAKI,KAAKuB,UAAUC,IAAI,SAE5BP,GAAS,GACV,IAAI,GAEf,CAMAnB,IAAAA,GACI,OAAO,IAAIkB,SAASC,IACXrB,KAAKC,SAASoB,IACfrB,KAAKK,cAAcsB,UAAUK,SAAS,YACtChC,KAAKK,cAAcoB,MAAMC,SAAW,GACpC1B,KAAKK,cAAcsB,UAAUM,OAAO,WAGxC,MAAMC,EAAUlC,KAAKI,KAAKS,cAAc,YACpCqB,GAASA,EAAQD,SACrBjC,KAAKI,KAAKuB,UAAUM,OAAO,QAC3BjC,KAAKC,SAAU,EACfD,KAAKU,QAAQR,OACbmB,GAAS,GAEjB,CAEAc,iBAAAA,GACInC,KAAKoC,UAAY,4JAOjBpC,KAAKI,KAAOJ,KAAKa,cAAc,SAC/Bb,KAAKI,KAAKiC,iBAAiB,SAAUC,GAAQA,EAAIC,mBACrD,EAGJjB,OAAO3B,UAAY2B,OAAOkB,eAAeC,IAAI,eAAiB9C,EAC9D,QAAe2B,OAAgB,UAE1BA,OAAOkB,eAAeC,IAAI,eAC3BnB,OAAOkB,eAAeE,OAAO,aAAc/C,WCjGxC,SAASgD,EAAWC,GACvB,IAAKA,EAAIC,SAAS,KAAM,MAAO,CAAC,EAEhC,IAAIC,EACAC,EAAWH,EAAII,MAAM,KAAKC,GAAG,GAQjC,OALIF,EAASF,SAAS,OAClBC,EAAOC,EAASC,MAAM,KAAKC,GAAG,GAC9BF,EAAWA,EAASC,MAAM,KAAKC,GAAG,IAG/B,CACHC,OAAQN,EAAII,MAAM,KAAKC,GAAG,GAC1BE,OAAQJ,EAASC,MAAM,KACvBF,KAAMA,EAEd,CAmDO,SAASM,EAAiBR,EAAKS,EAAMC,GACxC,IAAIC,EAASX,EAETA,EAAIC,SAAS,GAAGQ,QAChBE,EA3CD,SAA4BX,EAAKS,GACpC,IAAKT,EAAIC,SAAS,OAASD,EAAIC,SAAS,GAAGQ,MAAU,OAAOT,EAE5D,MAAMY,EAAYb,EAAWC,GACvBa,EAAYD,EAAUL,OAAOO,QAAQC,GAAUA,EAAMX,MAAM,KAAKC,GAAG,KAAOI,IAEhF,MAAO,GAAGG,EAAUN,UAAUO,EAAUG,KAAK,OAAOJ,EAAUV,KAAO,IAAIU,EAAUV,OAAS,IAChG,CAoCiBe,CAAmBjB,EAAKS,IAErC,MAAMS,EAAYP,EAAOV,SAAS,KAAO,IAAM,IAC/C,MAAO,GAAGU,IAASO,IAAYT,KAAQU,mBAAmBT,IAC9D,CCjFA,SAASU,EAAUC,EAAYC,EAAahB,EAAQiB,EAAiB,IACjE,MAAMC,EAAO,IAAIC,KACjBD,EAAKE,QAAQF,EAAKG,UAA6B,GAAjBJ,EAAsB,GAAK,GAAK,KAC9D,MAEMK,EAAe,GAAGP,KAAcC,KAFtB,WAAWE,EAAKK,oBACPvB,EAAS,UAAUA,KAAY,IAAlC,kCAGtB5C,SAASoE,OAASF,CACtB,CCNA,SAASG,IACL,ODYJ,SAAmBV,GACf,MACMW,EADQ,KAAKtE,SAASoE,SACR1B,MAAM,KAAKiB,MAC/B,OAAqB,IAAjBW,EAAMC,OAAqBD,EAAME,MAAM9B,MAAM,KAAK+B,QAC/C,IACX,CChBQC,CAAU,YACJhC,MAAM,KACPU,QAAQuB,GAASA,EAAKJ,OAAS,KAAM,EAElD,CCTA,MAAMK,UAAsBtF,YACxBC,WAAAA,GACIE,OACJ,CAEAoC,iBAAAA,GACInC,KAAKqC,iBAAiB,QAASrC,KAAKmF,SACpCnF,KAAKoF,UAAYpF,KAAKa,cAAc,IACxC,CAEAwE,oBAAAA,GACIrF,KAAKsF,oBAAoB,QAAStF,KAAKmF,QAC3C,CAOAI,kBAAAA,GACI,MAAMC,IAAexF,KAAKoF,UAAUK,QAAQ,aAC5CnE,OAAOoE,SAAWF,EAAapC,EAAiB9B,OAAOoE,SAASC,KAAM,eAAgB,QAAUrE,OAAOoE,SAASC,IACpH,CAEAR,OAAAA,CAAQ7C,GACJ,MAAMsD,EAAUtF,SAASO,cAAc,eAAiB,IAAIlB,EAC5DiG,EAAQ1E,QACRoB,EAAIuD,iBAEJ,MAAMC,EAAgC9F,KAAKoF,UAAUW,aAAa,6BAC5DC,EAAmChG,KAAKoF,UAAUW,aAAa,uBAErE,GAAID,GAAiCE,EAAkC,CACnE,IAAIC,EAAUtB,IACd,GAAIsB,EAAQpB,OAAS,IACjBoB,EAAUA,EAAQvC,QAAQuB,GAASA,IAASa,GAAiCb,IAASe,IAClFC,EAAQC,OAAOC,GAAc,YAAPA,KAA0D,YAArCH,GDO3DhC,EAAU,UAAW,KAAM1C,OAAOoE,SAASU,SAAU,GACrDpC,EAAU,mCAAoC,KAAM1C,OAAOoE,SAASU,SAAU,GAC9EpC,EAAU,4BAA6B,KAAM1C,OAAOoE,SAASU,SAAU,IAhB3E,SAAuBH,EAASI,GAE5BrC,EAAU,UAAWiC,EAAQrC,KAAK,KAAMtC,OAAOoE,SAASU,SAAU,OAC9DC,IACArC,EAAU,mCAAoCqC,EAAK,mBAAoB/E,OAAOoE,SAASU,SAAU,OACjGpC,EAAU,4BAA6BqC,EAAKC,SAAUhF,OAAOoE,SAASU,SAAU,OAExF,CCGoBG,CAAcN,GAEdH,GAGA,OAFAF,EAAQ1F,YACRoB,OAAOoE,SAASc,QAI5B,CAEAC,MAAMzG,KAAKoF,UAAUO,KAAM,CACvBe,OAAQ1G,KAAKoF,UAAUW,aAAa,cAAgB,QAEnDY,KAAK3G,KAAKuF,mBAAmBpF,KAAKH,OAClC4G,QAAQhB,EAAQ1F,KACzB,EAGWoB,OAAOkB,eAAeC,IAAI,mBAEpCnB,OAAOkB,eAAeC,IAAI,oBAC3BnB,OAAOkB,eAAeE,OAAO,kBAAmBwC,GChEpD,MAAM2B,EAAiBtF,iBAAiBjB,SAASwG,iBAmOjD,GACIC,WA3Be,CACfC,MAAO,QACPC,gBAAiB,qBACjBC,kBAAmB,0BACnBC,OAAQ,YACRC,SAAU,gBAuBVC,WAzFe,CACfC,OAAQ,SACRC,MAAO,QACPC,QAAS,UACTC,UAAW,kBACXC,SAAU,iBACVC,SAAU,WACVC,QAAS,eACTjC,KAAM,OACNQ,GAAI,KACJ0B,QAAS,UACTC,YAAa,cACbC,SAAU,WACVC,SAAU,WACVC,SAAU,WACVC,OAAQ,iBACRtF,IAAK,MACLU,MAAO,QACP6E,WAAY,CACRC,gBAAiB,wBACjBC,aAAc,qBACdC,SAAU,mBAqEdC,YAtDgB,CAChBC,IAAKC,SAAS5B,EAAerF,iBAAiB,oBAAqB,IACnEkH,GAAID,SAAS5B,EAAerF,iBAAiB,mBAAoB,IACjEmH,GAAIF,SAAS5B,EAAerF,iBAAiB,mBAAoB,IACjEoH,GAAIH,SAAS5B,EAAerF,iBAAiB,mBAAoB,IACjEqH,GAAIJ,SAAS5B,EAAerF,iBAAiB,mBAAoB,IACjEsH,GAAIL,SAAS5B,EAAerF,iBAAiB,mBAAoB,IACjEuH,IAAKN,SAAS5B,EAAerF,iBAAiB,oBAAqB,KAgDnEwH,QAnIY,CACZC,OAAQ,SACRC,QAAS,CACLC,KAAM,iBACNC,SAAU,qBACVC,QAAS,qBAEbC,OAAQ,UACRC,MAAO,SACPC,aAAc,iBACdC,MAAO,SACP9B,SAAU,WACV+B,MAAO,QACPC,SAAU,WACVC,QAAS,UACTC,OAAQ,SACRC,KAAM,OACNC,KAAM,OACNC,MAAO,SAkHPC,OAtNW,CACXC,KAAM,OACNC,OAAQ,SACRC,MAAO,QACPC,MAAO,QACPC,MAAO,QACPC,KAAM,OACNC,UAAW,YACXC,WAAY,aACZC,UAAW,YACXC,MAAO,QACPC,SAAU,WACVC,OAAQ,SACRC,cAAe,gBACfC,OAAQ,SACRC,OAAQ,SACRC,cAAe,gBACfC,OAAQ,SACRtB,QAAS,WAqMTuB,UA/Kc,CACd5K,KAAM,OACN6K,KAAM,CACFC,SAAU,yBACVC,KAAM,qBACNF,KAAM,OACNf,MAAO,QACPkB,gBAAiB,kBACjBC,mBAAoB,uBACpBC,MAAO,QACPC,MAAO,sBACPC,OAAQ,SACRX,OAAQ,kBACRY,SAAU,YAEdC,KAAM,OACNC,SAAU,aACVC,IAAK,MACL1B,MAAO,QACP2B,oBAAqB,4CA6JrBC,aA5CiB,CACjBC,kBAAmB,qBA4CnBC,eAjBmB,CACnB5E,MAAO,oBACP3G,UAAW,wBACXwL,kBAAmB,iCACnBjG,GAAI,iBACJkG,UAAW,yBACXC,gBAAiB,oBCtNrB,SAASC,EAASC,EAAQC,EAAaC,EAAUC,GAC7CH,EAAOnK,iBACHoK,GACA,SAAoBG,GAEZA,EAAM1E,OAAO2E,QAAQ,GAAGH,OAAcA,QACtCC,EAAQG,MAAMF,EAAM1E,OAAOzC,QAAQiH,GAAWK,UAEtD,IACA,EAER,CAMA,SAASC,EAAcC,GACS,YAAxB3M,SAAS4M,WACTD,IAEA3M,SAAS+B,iBAAiB,mBAAoB4K,EAEtD,CCzBA,MAAM9B,EACM,aADNA,EAEU,sBAFVA,EAGY,wBAHZA,EAIa,yBAJbA,EAKc,iCALdA,EAMgB,qBAOtB,SAASgC,EAAWP,GAChB,MACM1E,EADS0E,EAAM1E,OACCnC,aAAaqH,EAAM/F,WAAWa,QAC9CmF,EAAS/M,SAASO,cAAcqH,GAElCmF,GACAA,EAAO1L,UAAUC,IAAIwL,EAAMpE,QAAQC,OAE3C,CAOA,SAASqE,EAAYV,EAAOW,GACnBA,GACDX,EAAM/G,iBAGV,MAAM2H,EAASZ,EAAM1E,OACfmF,EAASG,EAAO/H,QAAQ0F,GAE1BkC,IACAA,EAAO1L,UAAUM,OAAOmL,EAAMpE,QAAQC,QACtCuE,EAAOtD,OAEf,CAEA8C,GAAc,KACVT,EAASjM,SAAU8M,EAAMnD,OAAOG,MAAOe,EAAsBgC,GAC7DZ,EAASjM,SAAU8M,EAAMnD,OAAOG,MAAOe,GAAyByB,IAC5DU,EAAYV,GAAO,EAAM,IAE7BL,EAASjM,SAAU8M,EAAMnD,OAAOG,MAAOe,GAA0ByB,IAC7DU,EAAYV,GAAO,EAAK,IAG5BL,EAASjM,SAAU8M,EAAMnD,OAAOG,MAAOe,GAA2ByB,IAC9D,MAAMY,EAASZ,EAAM1E,OAEhBsF,EAAOzH,aAAaqH,EAAM/F,WAAWa,SACtCsF,EAAOC,aAAaL,EAAM/F,WAAWa,OAAQiD,GAGjDgC,EAAWP,EAAM,GACnB,IClEN,MAAMc,EACM,IADNA,EAEQ,IAFRA,EAGc,IAHdA,EAIO,IAJPA,EAKO,IALPA,EAMO,IANPA,EAOO,IAPPA,EAQO,IARPA,EASQ,IATRA,EAUK,KAGLC,EAAsB,CAAC,EAC7BA,EAAoBD,GAA2B,oCAC/CC,EAAoBD,GAAyBC,EAAoBD,GACjEC,EAAoBD,GAAiC,aACrDC,EAAoBD,GAA0B,8BAC9CC,EAAoBD,GAA0BC,EAAoBD,GAClEC,EAAoBD,GAA0BC,EAAoBD,GAClEC,EAAoBD,GAA0BC,EAAoBD,GAClEC,EAAoBD,GAA0BC,EAAoBD,GAClEC,EAAoBD,GAA0BC,EAAoBD,GAClEC,EAAoBD,GAA2BC,EAAoBD,GAGnEC,EAAoBD,GAAwB,SAK5C,MAAME,EAAU,8CAMhB,SAASC,EAAqBvL,GAC1B,MAAMwL,EAAUxL,EAAI4F,OAAO/B,KAAOyH,EAAUtL,EAAI4F,OAAS5H,SAASyN,eAAeH,GAC7EE,EAAQxK,OACRwK,EAAQrI,QAAQ,QAAQuI,cACpB,IAAIC,YAAY,4BAA6B,CACzCC,OAAQ,CACJC,KAAML,EAAQxK,MACd8K,MAAOT,EAAoBG,EAAQxK,UAKvD,CCzCO,MAAM+K,EACTxO,WAAAA,CAAYiO,GACRA,EAAQzL,iBAAiB,QAASrC,KAAKsO,QAAQnO,KAAK2N,IACpDA,EAAQzL,iBAAiB,SAAUrC,KAAKsO,QAAQnO,KAAK2N,GACzD,CAEAQ,OAAAA,GACI,MAAM5M,EAAW1B,KAAKuO,eACtBvO,KAAKsD,MAAQtD,KAAKsD,MAAMkL,cACxBxO,KAAKyO,kBAAkB/M,EAAUA,EACrC,ECdJ,MAeMgN,EAAY,CAVQ,EAKH,GAK+B,YAAa,UAMnE,MAAMC,UAAqBN,EACvBxO,WAAAA,CAAYiO,GACR/N,MAAM+N,GACN9N,KAAK8N,QAAUA,EACf9N,KAAK4O,QAAU5O,KAAK4O,QAAQzO,KAAKH,MAEjC8N,EAAQzL,iBAAiB,QAASrC,KAAK4O,QAC3C,CAMAA,OAAAA,CAAQtM,GACJ,MAAMuM,EAAMvM,EAAIuM,KAA0B,iBAAZvM,EAAIuM,IAAmBvM,EAAIuM,IAAIC,oBAAsBxM,EAAIuM,KAAO,KAC1FA,GAAOH,EAAUK,MAAMC,GAAMA,IAAMH,IACD,IAA9B7O,KAAK8N,QAAQxK,MAAMuB,SACnB7E,KAAK8N,QAAQxK,MAAQtD,KAAK8N,QAAQxK,MAAM2L,UAAU,EAAG,IAM7DjP,KAAK8N,QAAQxK,MAAQtD,KAAK8N,QAAQxK,MAAM4L,QAAQ,qBAAsB,QAC1E,EC7CJ,MAeMR,EAAY,CAVQ,EAKH,GAK+B,YAAa,UAEnE,MAAMS,UAAiBd,EACnBxO,WAAAA,CAAYiO,GACR/N,MAAM+N,GACN9N,KAAK8N,QAAUA,EACf9N,KAAK4O,QAAU5O,KAAK4O,QAAQzO,KAAKH,MAEjC8N,EAAQzL,iBAAiB,QAASrC,KAAK4O,QAC3C,CAMAA,OAAAA,CAAQtM,GACJ,MAAMuM,EAAMvM,EAAIuM,KAA0B,iBAAZvM,EAAIuM,IAAmBvM,EAAIuM,IAAIC,oBAAsBxM,EAAIuM,KAAO,KAC1FA,GAAOH,EAAUK,MAAMC,GAAMA,IAAMH,IAC/B7O,KAAK8N,QAAQxK,MAAMuB,OAAS,GAAM,IAClC7E,KAAK8N,QAAQxK,MAAQtD,KAAK8N,QAAQxK,MAAM2L,UAAU,EAAGjP,KAAK8N,QAAQxK,MAAMuB,SAMhF7E,KAAK8N,QAAQxK,MAAQtD,KAAK8N,QAAQxK,MAC7B4L,QAAQ,MAAO,IACfA,QAAQ,0DAA2D,kBACnEA,QAAQ,SAAU,IAC3B,EC5CJ,MAAME,EACFvP,WAAAA,CAAYiO,GACR9N,KAAKqP,MAAQvB,EACb9N,KAAKsP,YAAc,EACnBtP,KAAKuP,SAAWzB,EAAQ/H,aAAa,kBACrC/F,KAAKwP,kBAAoB,GAEzBxP,KAAKsO,QAAUtO,KAAKsO,QAAQnO,KAAKH,MACjCA,KAAKyP,QAAUzP,KAAKyP,QAAQtP,KAAKH,MACjCA,KAAK0P,8BAAgC1P,KAAK0P,8BAA8BvP,KAAKH,MAC7EA,KAAK2P,aAAe3P,KAAK2P,aAAaxP,KAAKH,MAC3CA,KAAK4P,YAAc5P,KAAK4P,YAAYzP,KAAKH,MACzCA,KAAK6P,mBAAqB7P,KAAK6P,mBAAmB1P,KAAKH,MACvDA,KAAK8P,sBAAwB9P,KAAK8P,sBAAsB3P,KAAKH,MAC7DA,KAAK+P,iBAAmB/P,KAAK+P,iBAAiB5P,KAAKH,MAEnD8N,EAAQzL,iBAAiB,UAAWrC,KAAKgQ,UAAU7P,KAAKH,OACxD8N,EAAQzL,iBAAiB,QAASrC,KAAKsO,SACvCR,EAAQzL,iBAAiB,QAASrC,KAAKyP,QAC3C,CAUA,sBAAOQ,CAAgB3M,GACnB,OAAOA,EACFkL,cACAU,QAAQ,aAAc,QACtBA,QAAQ,aAAc,SAEtBA,QAAQ,OAAQ,KAChBA,QAAQ,aAAc,IACtBA,QAAQ,YAAa,MACrBA,QAAQ,KAAM,IACdlM,MAAM,GACf,CAWA,gCAAOkN,CAA0BC,GAE7B,IAAIC,EADmBD,EAAOvM,KAAK,IAAIsL,QAAQ,SAAU,IACxBrK,OAQjC,OAPIuL,EAAc,IACdA,GAAe,GAEfA,EAAc,IACdA,GAAe,GAGZA,CACX,CAUAV,6BAAAA,CAA8BS,GAG1B,IAAIE,EAAe,EACnB,MAAMf,EAActP,KAAKsP,YAEL,IAAhBA,GAAqC,IAAhBA,EACrBe,GAAgB,EACTf,EAAc,IACrBe,GAAgB,GAIpB,MAAMC,EAAmBtQ,KAAKuP,SAASN,UAAUK,EAAaA,EAAc,GAM5E,MAJyB,MAArBgB,GACAH,EAAOI,OAAOjB,EAAce,EAAc,EAAGC,GAG1CH,CACX,CAUA,gBAAOK,CAAUL,GAWb,OATIA,EAAOtL,QAAU,GACjBsL,EAAOI,OAAO,EAAG,EAAG,KAIpBJ,EAAOtL,QAAU,GACjBsL,EAAOI,OAAO,EAAG,EAAG,KAGjBJ,CACX,CASAR,YAAAA,CAAaQ,GACLnQ,KAAK8P,sBAAsBK,KAASnQ,KAAKsP,aAAe,GAC5DtP,KAAKqP,MAAMZ,kBAAkBzO,KAAKsP,YAAatP,KAAKsP,YACxD,CASAM,WAAAA,CAAYO,GACJnQ,KAAK8P,sBAAsBK,EAAQ,UAASnQ,KAAKsP,aAAe,GACpEtP,KAAKqP,MAAMZ,kBAAkBzO,KAAKsP,YAAatP,KAAKsP,YACxD,CASAO,kBAAAA,CAAmBM,GAEXnQ,KAAK8P,sBAAsBK,EAAQ,UAASnQ,KAAKsP,aAAe,GAGhEtP,KAAKsP,YAAc,IAAGtP,KAAKsP,YAAc,GAE7CtP,KAAKqP,MAAMZ,kBAAkBzO,KAAKsP,YAAatP,KAAKsP,YACxD,CASAQ,qBAAAA,CAAsBxM,EAAOmN,EAAWC,EAAS,GAC7C,MAAMpB,EAActP,KAAKsP,YAAcoB,EAEvC,MAAkB,SAAdD,EACyD,MAAlDnN,EAAM2L,UAAUK,EAAc,EAAGA,GAGa,MAAlDhM,EAAM2L,UAAUK,EAAaA,EAAc,EACtD,CASA,gBAAOqB,CAAUrN,EAAOsN,EAAOC,GAC3B,OAAOvN,EAAM2L,UAAU,EAAG2B,GAASC,EAAcvN,EAAM2L,UAAU2B,EAAQ,EAC7E,CASAb,gBAAAA,CAAiBlB,GACb,IAAIvL,EAAQtD,KAAKqP,MAAM/L,MACvB,MAAMwN,GAAWxP,OAAOyP,MAAMlC,GACxBmC,EAAsB,MAARnC,GAAe7O,KAAK8P,sBAAsBxM,EAAO,QAAS,GAe9E,OAVItD,KAAKsP,YAAchM,EAAMuB,SAAW7E,KAAKiR,eAAiBH,GAAWE,KAEjEhR,KAAK8P,sBAAsBxM,IAC3BtD,KAAKsP,cAGThM,EAAQtD,KAAKH,YAAY8Q,UAAUrN,EAAOtD,KAAKsP,YAAaT,GAC5D7O,KAAKsP,eAGFhM,CACX,CAMA0M,SAAAA,CAAU1N,GAEN,GAAIA,EAAI4O,QAAsB,cAAZ5O,EAAIuM,KAAmC,WAAZvM,EAAIuM,IAE7C,YADAvM,EAAIuD,iBAIR7F,KAAKiR,aAAe3O,EAAI4F,OAAOiJ,aAAe7O,EAAI4F,OAAOqG,iBACxCjN,OAAOyP,MAAMzO,EAAIuM,MAEP,MAAZvM,EAAIuM,OACfvM,EAAIuD,iBACJ7F,KAAKwP,kBAAkB4B,KAAK9O,EAAIuM,KAChC7O,KAAKsO,QAAQhM,GAErB,CAMAgM,OAAAA,CAAQhM,GACJ,GACiB,UAAbA,EAAI6L,OACS,WAAZ7L,EAAIuM,KACW,UAAZvM,EAAIuM,KACQ,QAAZvM,EAAIuM,KACQ,YAAZvM,EAAIuM,KACQ,UAAZvM,EAAIuM,KACQ,QAAZvM,EAAIuM,KACQ,SAAZvM,EAAIuM,KACQ,YAAZvM,EAAIuM,KACQ,cAAZvM,EAAIuM,KAER,OAGJ,MAAMQ,EAAQrP,KAAKqP,MACbgC,EAAMhC,EAAM/L,MAClB,IAAIgO,EAA2B,UAAbhP,EAAI6L,OAAiC,cAAZ7L,EAAIuM,KAAmC,WAAZvM,EAAIuM,KAC1E7O,KAAKsP,YAAcD,EAAMd,eAMzB,MAAMgD,EAAwBvR,KAAKwP,kBAAkB,GAGrD,GAAkC,IAA9BlN,EAAI4F,OAAOqG,gBAAoD,KAA5BjM,EAAI4F,OAAOiJ,aAAqB,CACnE,IAAII,EAMA,OAJAlC,EAAM/L,MAAQiO,EACdvR,KAAKsP,aAKb,CAImB,IAAf+B,EAAIxM,QAAgB0M,GACpBlC,EAAM/L,MAAQiO,EACdlC,EAAM1N,UAAUM,OAAO,UACD,IAAfoP,EAAIxM,QACXwK,EAAM1N,UAAUC,IAAI,SAIxB,IAAIuO,EAASnQ,KAAK+P,iBAAiBwB,EAAuBF,GAC1DhC,EAAM/L,MAAQ6M,EAEdnQ,KAAKwP,kBAAkBzK,QAGvBoL,EAASnQ,KAAKH,YAAYoQ,gBAAgBE,GAI1C,MAAMC,EAAcpQ,KAAKH,YAAYqQ,0BAA0BC,GAG3DmB,IACAnB,EAASnQ,KAAK0P,8BAA8BS,IAK5CmB,GAAetR,KAAKsP,YAAcc,IAClCkB,GAAc,GAIlBnB,EAASnQ,KAAKH,YAAY2Q,UAAUL,GAIhCC,EAAc,GACdD,EAASA,EAAOvM,KAAK,IAAIqL,UAAU,EAAG,IACtCkB,GAAUnQ,KAAKuP,SAASN,UAAUkB,EAAOtL,OAAQ,IACjD7E,KAAKqP,MAAM/L,MAAQ6M,EAOP,cAAZ7N,EAAIuM,IAMQ,eAAZvM,EAAIuM,IAMJyC,EACAtR,KAAK6P,mBAAmBM,IAKxBnQ,KAAK8P,sBAAsBK,KAC3BnQ,KAAKsP,aAAe,GAIxBtP,KAAKqP,MAAMZ,kBAAkBzO,KAAKsP,YAAatP,KAAKsP,cAhBhDtP,KAAK2P,aAAaQ,GANlBnQ,KAAK4P,YAAYO,IANjBnQ,KAAKqP,MAAM/L,MAAQ,EA6B3B,CAMAmM,OAAAA,CAAQnN,GACJtC,KAAKsO,QAAQhM,GAEbR,YAAW,KACP,MAAMuP,EAAMrR,KAAKqP,MAAM/L,MACvBtD,KAAKqP,MAAMZ,kBAAkB4C,EAAIxM,OAAQwM,EAAIxM,OAAO,GACrD,IACP,ECjVJ,QArBA,MACIhF,WAAAA,CAAYiO,GACR9N,KAAK8N,QAAUA,EACf9N,KAAKwR,SAAWxR,KAAK8N,QAAQ/H,aAAa,aHPlB,aGUpB/F,KAAKwR,WACLxR,KAAKyR,KAAO,IAAI9C,EAAa3O,KAAK8N,UFXlB,SEahB9N,KAAKwR,WACLxR,KAAKyR,KAAO,IAAItC,EAASnP,KAAK8N,UDhBd,SCkBhB9N,KAAKwR,WACLxR,KAAKyR,KAAO,IAAIrC,EAASpP,KAAK8N,UJnBP,SIqBvB9N,KAAKwR,WACLxR,KAAKyR,KAAO,IAAIpD,EAASrO,KAAK8N,SAEtC,GCvBJ,SAAS4D,EAAkB9E,GACvB,MAAM,OAAE1E,GAAW0E,EACb+E,EAAmBzJ,EAAOnC,aAAa,gBAE7C,GAAI6G,EAAMiC,KAAO8C,EAAiB9O,SAAS+J,EAAMiC,KAC7CjC,EAAM/G,sBACH,GAAI+G,EAAMgF,cAAe,CAC5BhF,EAAM/G,iBAEN,MACMgM,EADgBjF,EAAMgF,cAAcE,QAAQ,cAE7C9O,MAAM,IACNU,QAAQqO,IAAeJ,EAAiB9O,SAASkP,KACjDnO,KAAK,IACJoO,EAAY9J,EAAO5E,MAEzB,GAAqC,iBAA1B4E,EAAOqG,eAA6B,CAC3C,MAAMrN,EAAQgH,EAAOqG,eACf0D,EAAM/J,EAAOiJ,aACbhB,EAAS,GAED,IAAVjP,GAAuB,IAAR+Q,GACf9B,EAAOiB,KAAKS,GACZ1B,EAAOiB,KAAKY,KAEZ7B,EAAOiB,KAAKY,EAAUE,OAAO,EAAGhR,IAChCiP,EAAOiB,KAAKS,GACZ1B,EAAOiB,KAAKY,EAAUE,OAAOD,EAAKD,EAAUnN,OAAS,KAGzDqD,EAAO5E,MAAQ6M,EAAOvM,KAAK,GAC/B,MAEIsE,EAAO5E,MAAQ0O,EAAYH,CAEnC,CACJ,CCxCA,MAAM5H,EAAS,CAAC,UAAW,QAAS,QAAS,aAM7C,SAASkI,EAAa7P,GAEE,IAAhBA,EAAI8P,SAAe9P,EAAIuD,gBAC/B,CCAA,SACIwM,eCDW,SAAwBvE,GACnC,GAPoB,wDAOhBA,EAAQzK,KAA0B,OAEtCyK,EAAQrI,QAAQ,QAAQpD,iBAAiB,6BAA8BC,IAGnEwL,EAAQjG,QAAUvF,EAAI4L,OAAOE,MAAMkE,WAAWpD,QAAQ,KAAM,KAAKA,QAAQ,OAAQ,KACjFpB,EAAQM,MAAMmE,UAAY,EAC1BzE,EAAQM,MAAQ,IAAIoE,OAAO1E,EAAQjG,SAC/BiG,EAAQxK,MAAMuB,OAAS,IACvBiJ,EAAQE,cAAc,IAAIC,YAAY,UACtCH,EAAQE,cAAc,IAAIC,YAAY,SAC1C,IAGJ,MAAMwE,EAAmB3E,EAAQ4E,QAAQC,aACzC7E,EAAQzL,iBAAiB,SAAS,KAE9ByL,EAAQ4E,QAAQC,aAAeF,EAC3B3E,EAAQ4E,QAAQE,YAAc9E,EAAQ4E,QAAQE,WAAW/P,SAAS,uBAC9DiL,EAAQxK,MAAMuP,cAAcC,WAAW,SAAQhF,EAAQ4E,QAAQC,aAAe7E,EAAQ4E,QAAQK,iBAC9FjF,EAAQxK,MAAMuP,cAAcC,WAAW,OAAMhF,EAAQ4E,QAAQC,aAAe7E,EAAQ4E,QAAQM,eACpG,GAER,EDtBIC,OR6CW,SAAgBnF,GACvBA,EAAQ3H,KAAOyH,IAEnBE,EAAQzL,iBAAiB,SAAUwL,GACnCvM,OAAOe,iBAAiB,OAAQwL,GACpC,EQjDI4D,KENW,SAAc3D,GACzBoF,OAAOC,eAAerF,EAAS,OAAQ,CACnCsF,YAAY,EACZC,cAAc,EACd/P,MAAO,IAAIgQ,EAAKxF,IAExB,EFCIyF,SGJW,SAAsBzF,GACjC,MAAM0F,EAAkB1F,EAAQzN,cAAcQ,cAPrB,uBAQpB2S,IAELA,EAAgBnR,iBAAiB,SAAS,KACtCyL,EAAQ2F,aAAgC,aAAjB3F,EAAQK,IAAmB,IAEtD+E,OAAOC,eAAerF,EAAS,eAAgB,CAC3CsF,YAAY,EACZC,cAAc,EACdK,IAAMpQ,IAEEwK,EAAQK,KADR7K,EACe,OAEA,UACnB,IAGZ,EHbIoO,kBFgCW,SAAkC5D,GACxCA,EAAQ/H,aAAa,kBAE1B+H,EAAQzL,iBAAiB,UAAWqP,GACpC5D,EAAQzL,iBAAiB,QAASqP,GACtC,EEpCI1J,SDwBW,SAAgB8F,GACtBA,EAAQ6F,aAAa,eAC1BT,OAAOC,eAAerF,EAAS,YAAa,CACxCsF,YAAY,EACZC,cAAc,EACdK,IAAME,IAEE5T,KAAKsD,MADLsQ,EA7BhB,SAAgB9F,GAIZ,OAHA7D,EAAO4J,SAASjH,IACZkB,EAAQzL,iBAAiBuK,EAAOuF,EAAa,KAE1C,CACX,CAyB6B2B,CAAOhG,GAlBpC,SAAiBA,GAIb,OAHA7D,EAAO4J,SAASjH,IACZkB,EAAQxI,oBAAoBsH,EAAOuF,EAAa,KAE7C,CACX,CAgByB4B,CAAQjG,EAAQ,IAGrCA,EAAQ,aAAeA,EAAQ/H,aAAa,aAChD,ECrCIqI,MIZW,SAAeN,GAC1BoF,OAAOC,eAAerF,EAAS,QAAS,CACpCsF,YAAY,EACZC,cAAc,EACdW,UAAU,EACV1Q,MAAOwK,EAAQ/F,SAAW,IAAIyK,OAAO1E,EAAQjG,SAAW,IAAI2K,QAEpE,EJMIxI,MKbW,SAAkB8D,GAC7BoF,OAAOC,eAAerF,EAAS,QAAS,CACpCsF,YAAY,EACZC,cAAc,EACdK,IAAMpQ,IACEA,GACAwK,EAAQnM,UAAUC,IAAI,SACtBkM,EAAQnM,UAAUM,OAAO,aAEzB6L,EAAQnM,UAAUC,IAAI,WACtBkM,EAAQnM,UAAUM,OAAO,SAC7B,GAGZ,GCfA,MAAMgS,EAAuB,CAAC,eAAgB,kBAAmB,YAOjE,SAASC,EAAoBC,EAASjM,GAC9BiM,GACAjM,EAAOvG,UAAUM,OAAO,WACxBiG,EAAOvG,UAAUC,IAAI,WAErBsG,EAAOvG,UAAUC,IAAI,WACrBsG,EAAOvG,UAAUM,OAAO,SAEhC,CAMA,SAASmS,EAA+BlM,GACpC,MAAM4F,EAAU5F,EAAO7H,cAAcQ,cAAc,cAC/CiN,GAASA,EAAQ7L,QACzB,CAOA,SAASoS,EAA+BC,EAASpM,GAC7C,MAAM4F,EACF5F,EAAO7H,cAAcQ,cAAc,eAClC,WACG,MAAM0T,EAAKjU,SAASkU,cAAc,SAElC,OADAD,EAAG5S,UAAUC,IAAI,YAAa,gBACvB2S,CACX,CAJC,GAKLzG,EAAQ2G,UAAYH,EAChBpM,EAAOwK,QAAQE,YAAc1K,EAAOwK,QAAQE,WAAW/P,SAAS,sBAAsBiL,EAAQnM,UAAUC,IAAI,iBAChHsG,EAAO7H,cAAcqU,sBAAsB,YAAa5G,EAC5D,CAgCA,SAAS6G,EAAavJ,GAClB,IAAIwJ,GAAY,EAChB,MAAMC,EAAa,IAAIzJ,EAAK0J,iBAAiB1H,EAAMjC,UAAUC,KAAKf,UAAWe,EAAK0J,iBAAiB1H,EAAMjC,UAAUC,KAAKQ,WAClHmJ,EAAY,IAAI3J,EAAK0J,iBAAiB,iCAsB5C,OApBAD,EAAWhB,SAASxE,IAChB,GAAmB,WAAfA,EAAMlB,KACN,OAGJ,MAAM6G,EAnCd,SAAuB3F,GACnB,IAAI2F,GAAa,EAgBjB,OAdAf,EAAqBJ,SAASoB,IAC1B,GAAI5F,EAAM6F,UAAY7F,EAAM6F,SAASD,GAAY,CAC7C,MAAME,EAAe9F,EAAMtJ,aAAaqH,EAAM/F,WAAWc,WAAW8M,IACpED,GAAa,EACbX,EAA+Bc,EAAc9F,GAC7C6E,GAAoB,EAAO7E,EAC/B,KAGA2F,IACAZ,EAA+B/E,GAC/B6E,GAAoB,EAAM7E,IAGvB2F,CACX,CAiB2BI,CAAc/F,GAE5B2F,IACDJ,GAAY,EAChB,IAGJG,EAAUlB,SAASwB,IACIA,EAASC,kBAGxBV,GAAY,EAChB,IAGGA,CACX,CAOA,SAASW,GAASjT,EAAKnB,GACnB,MAAMmT,EAAUnT,KCnFsBkO,EDmFW/M,EAAI4F,QCjF3CgN,SAASlL,QAGfqF,EAAMtH,UAAmC,IAAvBsH,EAAM/L,MAAMuB,OAAqBwK,EAAMtJ,aAAa,sBAGrEsJ,EAAM7H,UAAY6H,EAAMxC,QAAQ,uBAAwBwC,EAAMxC,QAAQ,kBAGvEwC,EAAMxH,UAAY,IAAI2K,OAAOnD,EAAMxH,SAAS2N,KAAKnG,EAAM/L,OAAe+L,EAAMtJ,aAAa,sBAGlE,SAAvBsJ,EAAMqD,QAAQjB,MAA6C,SAA1BpC,EAAMqD,QAAQ9I,QAA2ByF,EAAMtJ,aAAa,sBACtE,SAAvBsJ,EAAMqD,QAAQjB,MAAgD,SAA7BpC,EAAMqD,QAAQ+C,WAA8BpG,EAAMtJ,aAAa,sBACzE,SAAvBsJ,EAAMqD,QAAQjB,MAAgD,SAA7BpC,EAAMqD,QAAQgD,WAA8BrG,EAAMtJ,aAAa,sBACzE,aAAvBsJ,EAAMqD,QAAQjB,MAA2D,SAApCpC,EAAMqD,QAAQiD,mBAAqCtG,EAAMtJ,aAAa,sBATTsJ,EAAMtJ,aAAa,uBARtH,IAAmCsJ,EDoFlCiF,GACAD,EAA+BC,EAAShS,EAAI4F,QAC5CgM,GAAoB,EAAO5R,EAAI4F,UAE/BkM,EAA+B9R,EAAI4F,QACnCgM,GAAoB,EAAM5R,EAAI4F,QAEtC,CEhHA,MAAM0N,WAAqBC,iBACvBhW,WAAAA,GACIE,QACAC,KAAK8V,gBAAkB9V,KAAK8V,gBAAgB3V,KAAKH,MACjDA,KAAK+V,eAAiB/V,KAAK+V,eAAe5V,KAAKH,MAC/CA,KAAKyP,QAAUzP,KAAKyP,QAAQtP,KAAKH,MAEjCA,KAAKqC,iBAAiB,QAASrC,KAAK8V,iBACpC9V,KAAKqC,iBAAiB,QAASrC,KAAK+V,gBACpC/V,KAAKqC,iBAAiB,aAAcrC,KAAK+V,gBACzC/V,KAAKqC,iBAAiB,aAAckT,IACpCvV,KAAKqC,iBAAiB,QAASrC,KAAKyP,SACpCzP,KAAKuV,SAAWA,GAEhBS,EAAWhO,SAAShI,MACpBgW,EAAW5H,MAAMpO,MACjBgW,EAAWhM,MAAMhK,MACjBgW,EAAW3D,eAAerS,MAEtBA,KAAK2T,aAAa,cAClBqC,EAAWvE,KAAKzR,MAGhBA,KAAK2T,aAAa,iBAClBqC,EAAWtE,kBAAkB1R,MAGf,aAAdA,KAAKmO,MACL6H,EAAWzC,SAASvT,MAIxBA,KAAK+V,iBAEa,UAAd/V,KAAKmO,MAAkC,aAAdnO,KAAKmO,KAC9BnO,KAAKqC,iBAAiB,SAAUkT,IAEhCvV,KAAKqC,iBAAiB,OAAQkT,IAGlCvV,KAAKyF,QAAQ,QAAQpD,iBAAiB,SAAUrC,KAAKiW,sBACzD,CAEAxG,OAAAA,CAAQnN,GAEJR,YAAW,KACP9B,KAAK+V,iBACLR,GAASjT,EAAI,GACd,EACP,CAEA2T,qBAAAA,GACQjW,KAAK2T,aAAa,iBAClB3T,KAAKyN,aAAa,WAAY,WAEtC,CAOAsI,cAAAA,GACI,MAAMG,EAAWlW,KAAKsD,MAAMuB,OAAS,EAC/BsR,EAAqBnW,KAAKH,YAAYuW,kBAAkBpW,MAC1DkW,EACAlW,KAAK2B,UAAUM,OAAO,SACfkU,GAEPnW,KAAK2B,UAAUC,IAAI,QAE3B,CAOAkU,eAAAA,GACI9V,KAAKgK,MAAQhK,KAAKoO,MAAMoH,KAAKxV,KAAKsD,MACtC,CAQA,wBAAO8S,CAAkBtI,GACrB,MAAMpB,EAAW,GAAGoB,EAAQuI,SAASxD,uBAAuB/E,EAAQzK,2BACpE,QAAS/C,SAASO,cAAc6L,EACpC,EAGWpL,OAAOkB,eAAeC,IAAI,YACpCnB,OAAOkB,eAAeC,IAAI,aAC3BnB,OAAOkB,eAAeE,OAAO,WAAYkT,GAAc,CAAEU,QAAS,UCnG/D,MAAMC,GACT1W,WAAAA,GACIG,KAAKwW,aAAelW,SAASyN,eAAe,kCAC5C/N,KAAKyW,cAAgBzW,KAAKwW,aAAa/Q,QAAQ,QAG/CzF,KAAK0W,YAAcpW,SAASO,cAAc,8BAE1Cb,KAAK2W,SAAW3W,KAAK2W,SAASxW,KAAKH,MACnCA,KAAK4W,aAAe5W,KAAK4W,aAAazW,KAAKH,MAC3CA,KAAK6W,UAAY7W,KAAK6W,UAAU1W,KAAKH,MACrCA,KAAKyW,cAAcpU,iBAAiB,SAAUrC,KAAK2W,SACvD,CAEA,2BAAOG,CAAqB1L,EAAM2L,EAASrQ,GACV,SAAzBA,EAAOmM,gBACPkE,EAAQxW,KAAO,IAAIyW,SAAS5L,GAEpC,CAEAuL,QAAAA,CAASrU,GACLA,EAAIuD,iBAEJ,MAAMD,EAAUtF,SAASO,cAAc,eAAiB,IAAIlB,EAG5D,GAFAiG,EAAQ1E,QAEJyT,EAAa3U,KAAKyW,eAAgB,CAClCzW,KAAK4W,eAGL,MAAMG,EAAU,CACZrQ,OAAQ1G,KAAK0W,YAAYhQ,QAI7B1G,KAAKH,YAAYiX,qBAAqB9W,KAAK0W,YAAaK,EAASA,EAAQrQ,QAEzED,MAAMzG,KAAK0W,YAAYpP,OAAQyP,GAASpQ,MAAK,KACzC3G,KAAKiX,aAAejX,KAAKwW,aAAalT,MACtCtD,KAAK6W,YACLjR,EAAQ1F,MAAM,GAEtB,MACI0F,EAAQ1F,MAEhB,CAEA2W,SAAAA,GACI,MAAME,EAAU,CACZrQ,OAAQ1G,KAAKyW,cAAc/P,QAI/B1G,KAAKH,YAAYiX,qBAAqB9W,KAAKyW,cAAeM,EAASA,EAAQrQ,QAG3E,MAAMwQ,EAAalX,KAAKyW,cAAc5V,cAAc,wBAC9CsW,EAAYnX,KAAKyW,cAAc5V,cAAc,uBAC7CuW,EAAcpX,KAAKyW,cAAc5V,cAAc,yBAC/CwW,EAAmBrX,KAAKyW,cAAc5V,cAAc,wBACpDyW,EAAwBJ,EAAWxE,QAAQ6E,kBAC3CC,EAA0BL,EAAUzE,QAAQ+E,oBAClD,IAAIC,EAAuBP,EAAUzE,QAAQiF,iBAC7C,MAAM,uBAAEC,GAA2BR,EAAY1E,QAE3C1S,KAAKiX,cAAgBS,EAAqBG,QAAQ,QAAU,IAC5DH,EAAuBA,EAAqBxI,QAAQ,MAAOlP,KAAKiX,eAGpE,MAAMa,EAAmB,0CACMN,0BACtBE,kBAGHK,EAAsB,sLAE2GH,sCAIvInR,MAAMzG,KAAKyW,cAAcnP,OAAQyP,GAC5BpQ,MAAMqR,GAASA,EAAKC,SACpBtR,MAAMqR,IACHhY,KAAK4W,aAAaoB,EAAKE,YAEvBb,EAAiBpV,SACjBmV,EAAYzV,UAAUM,OAAO,yBAC7BmV,EAAYzV,UAAUC,IAAI,2BAC1BsV,EAAWiB,YAAcb,EACzBH,EAAU/U,UAAY0V,EACtBV,EAAYhV,UAAY2V,CAAmB,GAEvD,CAEAnB,YAAAA,CAAanP,GACLnG,OAAO8W,MACPpY,KAAKyW,cAAc5U,mBACf,YACA,gDAC6B4F,GAAanG,OAAO8W,KAAKC,qBAAqB5Q,GAAanG,OAAO8W,KAAKE,0BAIhH,EC1FJtL,GAPA,WACI,MAAMuL,EAAiBjY,SAASyN,eAAe,qBAAqBzK,MAC7C,SAAnBiV,GACA,IAAIhC,EAEZ,IAGAvJ,GCZe,SAA8BwL,IAChBA,EAAU,IAAIA,EAAQ1D,iBAAiB,kCAAoC,IAAIxU,SAASwU,iBAAiB,mCAEjHjB,SAAS4E,IACtB,MAAMC,EAAcA,KAEhB,MAAMC,EAAuD,SAA1CF,EAAQ1S,aAAa,iBAMxC,GALA0S,EAAQhL,aAAa,kBAAmBkL,GAAYrG,YAEpDmG,EAAQ9W,UAAUiX,OAAO,oCAGrBH,EAAQ9W,UAAUK,SAAS,oCAC3ByW,EAAQhT,QAAQ,0BAA0B9D,UAAUiX,OAAO,mCACxD,CACW,IAAKH,EAAQhT,QAAQ,UAAUqP,iBAAiB,0BAA4B,IACpFjB,SAAS5O,IACXA,EAAKtD,UAAUiX,OAAO,8BAA8B,GAE5D,GAEEC,EAAUJ,EAAQhT,QAAQ,0BAA0B5E,cAAc,kCACpEgY,EACAA,EAAQxW,iBAAiB,QAASqW,GAElCD,EAAQpW,iBAAiB,QAASqW,GrByJnC,iEAAiElD,KAAKsD,UAAUC,YqBtJjEN,EAAQ9W,UAAUK,SAAS,yCAAqF,SAA1CyW,EAAQ1S,aAAa,kBACzG2S,GACJ,GAER,MCvCIM,EAA2B,CAAC,EAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBE,IAAjBD,EACH,OAAOA,EAAaE,QAGrB,IAAIC,EAASN,EAAyBE,GAAY,CAGjDG,QAAS,CAAC,GAOX,OAHAE,EAAoBL,GAAUM,KAAKF,EAAOD,QAASC,EAAQA,EAAOD,QAASJ,GAGpEK,EAAOD,OACf,CAGAJ,EAAoBQ,EAAIF,ECzBxBN,EAAoBS,KAAO,CAAC,E9BAxBla,EAAW,GACfyZ,EAAoBU,EAAI,CAACC,EAAQC,EAAU5M,EAAI6M,KAC9C,IAAGD,EAAH,CAMA,IAAIE,EAAeC,IACnB,IAASC,EAAI,EAAGA,EAAIza,EAASqF,OAAQoV,IAAK,CAGzC,IAFA,IAAKJ,EAAU5M,EAAI6M,GAAYta,EAASya,GACpCC,GAAY,EACPC,EAAI,EAAGA,EAAIN,EAAShV,OAAQsV,MACpB,EAAXL,GAAsBC,GAAgBD,IAAa5G,OAAOkH,KAAKnB,EAAoBU,GAAGzT,OAAO2I,GAASoK,EAAoBU,EAAE9K,GAAKgL,EAASM,MAC9IN,EAAStJ,OAAO4J,IAAK,IAErBD,GAAY,EACTJ,EAAWC,IAAcA,EAAeD,IAG7C,GAAGI,EAAW,CACb1a,EAAS+Q,OAAO0J,IAAK,GACrB,IAAII,EAAIpN,SACEmM,IAANiB,IAAiBT,EAASS,EAC/B,CACD,CACA,OAAOT,CAnBP,CAJCE,EAAWA,GAAY,EACvB,IAAI,IAAIG,EAAIza,EAASqF,OAAQoV,EAAI,GAAKza,EAASya,EAAI,GAAG,GAAKH,EAAUG,IAAKza,EAASya,GAAKza,EAASya,EAAI,GACrGza,EAASya,GAAK,CAACJ,EAAU5M,EAAI6M,EAqBjB,E+BzBdb,EAAoBqB,EAAKhB,IACxB,IAAIiB,EAASjB,GAAUA,EAAOkB,WAC7B,IAAOlB,EAAiB,QACxB,IAAM,EAEP,OADAL,EAAoBwB,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdtB,EAAoBwB,EAAI,CAACpB,EAASsB,KACjC,IAAI,IAAI9L,KAAO8L,EACX1B,EAAoB2B,EAAED,EAAY9L,KAASoK,EAAoB2B,EAAEvB,EAASxK,IAC5EqE,OAAOC,eAAekG,EAASxK,EAAK,CAAEuE,YAAY,EAAM3Q,IAAKkY,EAAW9L,IAE1E,ECNDoK,EAAoB4B,EAAI,WACvB,GAA0B,iBAAfC,WAAyB,OAAOA,WAC3C,IACC,OAAO9a,MAAQ,IAAI+a,SAAS,cAAb,EAChB,CAAE,MAAOC,GACR,GAAsB,iBAAX1Z,OAAqB,OAAOA,MACxC,CACA,CAPuB,GCAxB2X,EAAoB2B,EAAI,CAACK,EAAKC,IAAUhI,OAAOiI,UAAUC,eAAe5B,KAAKyB,EAAKC,GCAlFjC,EAAoBkB,EAAI,UCKxB,IAAIkB,EAAkB,CACrB,IAAK,GAaNpC,EAAoBU,EAAEQ,EAAKmB,GAA0C,IAA7BD,EAAgBC,GAGxD,IAAIC,EAAuB,CAACC,EAA4BC,KACvD,IAGIvC,EAAUoC,GAHTzB,EAAU6B,EAAaC,GAAWF,EAGhBxB,EAAI,EAC3B,GAAGJ,EAAS9K,MAAM5I,GAAgC,IAAxBkV,EAAgBlV,KAAa,CACtD,IAAI+S,KAAYwC,EACZzC,EAAoB2B,EAAEc,EAAaxC,KACrCD,EAAoBQ,EAAEP,GAAYwC,EAAYxC,IAGhD,GAAGyC,EAAS,IAAI/B,EAAS+B,EAAQ1C,EAClC,CAEA,IADGuC,GAA4BA,EAA2BC,GACrDxB,EAAIJ,EAAShV,OAAQoV,IACzBqB,EAAUzB,EAASI,GAChBhB,EAAoB2B,EAAES,EAAiBC,IAAYD,EAAgBC,IACrED,EAAgBC,GAAS,KAE1BD,EAAgBC,GAAW,EAE5B,OAAOrC,EAAoBU,EAAEC,EAAO,EAGjCgC,EAAqBd,WAAsC,0BAAIA,WAAsC,2BAAK,GAC9Gc,EAAmB/H,QAAQ0H,EAAqBpb,KAAK,KAAM,IAC3Dyb,EAAmBxK,KAAOmK,EAAqBpb,KAAK,KAAMyb,EAAmBxK,KAAKjR,KAAKyb,QC7CvF,IAAIC,EAAsB5C,EAAoBU,OAAEP,EAAW,CAAC,IAAI,IAAI,MAAM,IAAOH,EAAoB,QACrG4C,EAAsB5C,EAAoBU,EAAEkC","sources":["webpack://vodafoneziggo/webpack/runtime/chunk loaded","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/VZSpinner.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/util/urlUtils.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/util/cookies.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/journey/journeyHelper.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/product/components/VZDeleteGroup.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/util/constants.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/util/util.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/prompt.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/decorators/idType.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/form/masks/caps.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/form/masks/postcode.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/form/masks/iban.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/form/masks/date.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/form/mask.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/decorators/preventCharacters.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/decorators/readonly.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/decorators/index.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/decorators/documentNumber.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/decorators/mask.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/decorators/password.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/decorators/regex.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/decorators/valid.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/util/validation.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/form/form.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/form/VZInputField.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/product/components/VZProductMailModal.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/cart.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/collapsibleSpecs.js","webpack://vodafoneziggo/webpack/bootstrap","webpack://vodafoneziggo/webpack/runtime/amd options","webpack://vodafoneziggo/webpack/runtime/compat get default export","webpack://vodafoneziggo/webpack/runtime/define property getters","webpack://vodafoneziggo/webpack/runtime/global","webpack://vodafoneziggo/webpack/runtime/hasOwnProperty shorthand","webpack://vodafoneziggo/webpack/runtime/runtimeId","webpack://vodafoneziggo/webpack/runtime/jsonp chunk loading","webpack://vodafoneziggo/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","'use strict';\n\nimport Lottie from 'lottie-web/build/player/lottie_light.min';\nconst redSpinnerData = require('./spinners/spinner_animation_min.json');\n\n/**\n * @class VZSpinner\n * @param {HTMLElement} [parent] - Parent element for the spinner to be added in.\n * @description\n * Creates a VZ-Spinner component\n *\n * @example\n * \n *
\n *
\n *
\n *
\n */\nclass VZSpinner extends HTMLElement {\n constructor(parentEl) {\n super();\n\n this.showing = false;\n this.stop = this.stop.bind(this);\n this.veil = null;\n\n const parentElement = parentEl || document.body;\n const location = parentElement.tagName === 'IMG' ? parentElement.parentElement : parentElement;\n location.appendChild(this);\n\n this.lottie = Lottie.loadAnimation({\n container: this.veil.querySelector('.spinner'),\n renderer: 'svg',\n loop: true,\n autoplay: false,\n animationData: redSpinnerData\n });\n }\n\n /**\n * @public\n * @param {string} [msg] - A message to be shown below the spinner.\n * @returns {Promise} promise\n */\n start(msg) {\n return new Promise((resolve) => {\n if (this.showing) resolve();\n const parentPosition = window.getComputedStyle(this.parentElement).getPropertyValue('position');\n\n if (parentPosition === 'static') {\n if (this.parentElement.tagName !== 'BODY') {\n this.parentElement.style.position = 'relative';\n }\n this.parentElement.classList.add('veiled');\n }\n\n if (msg) {\n this.veil.insertAdjacentHTML('beforeend', `
${msg}
`);\n }\n\n this.showing = true;\n setTimeout(() => {\n if (this.showing) {\n this.lottie?.play();\n this.veil.classList.add('show');\n }\n resolve();\n }, 500);\n });\n }\n\n /**\n * @public\n * @returns {Promise} promise\n */\n stop() {\n return new Promise((resolve) => {\n if (!this.showing) resolve();\n if (this.parentElement.classList.contains('veiled')) {\n this.parentElement.style.position = '';\n this.parentElement.classList.remove('veiled');\n }\n\n const content = this.veil.querySelector('.content');\n if (content) content.remove();\n this.veil.classList.remove('show');\n this.showing = false;\n this.lottie?.stop();\n resolve();\n });\n }\n\n connectedCallback() {\n this.innerHTML = `\n
\n
\n
\n
\n `;\n\n this.veil = this.querySelector('.veil');\n this.veil.addEventListener('click', (evt) => evt.stopPropagation());\n }\n}\n\nwindow.VZSpinner = window.customElements.get('vz-spinner') || VZSpinner;\nexport default window.VZSpinner;\n\nif (!window.customElements.get('vz-spinner')) {\n window.customElements.define('vz-spinner', VZSpinner);\n}\n","'use stict';\n\nimport 'core-js/features/array/at';\n\n/**\n * @private splitUpUrl\n * @param {string} url - The url to split up\n * @returns {Object} values\n *\n * @description\n * Will return an object with different parts of the url\n */\nexport function splitUpUrl(url) {\n if (!url.includes('?')) return {};\n\n let hash;\n let paramUrl = url.split('?').at(1);\n\n // if there is a hash at the end, store the hash\n if (paramUrl.includes('#')) {\n hash = paramUrl.split('#').at(1);\n paramUrl = paramUrl.split('#').at(0);\n }\n\n return {\n domain: url.split('?').at(0),\n params: paramUrl.split('&'),\n hash: hash\n };\n}\n\n/**\n * @public removeParamFromURL\n * @param {string} url - The url from which the parameter will be removed\n * @param {string} name - The name of the parameter that will be removed from url\n * @returns {string} url\n *\n * @description\n * remove the parameter and its value from the given url and returns the\n * changed url\n */\nexport function removeParamFromURL(url, name) {\n if (!url.includes('?') || !url.includes(`${name}=`)) return url;\n\n const urlValues = splitUpUrl(url);\n const newParams = urlValues.params.filter((param) => param.split('=').at(0) !== name);\n\n return `${urlValues.domain}?${newParams.join('&')}${urlValues.hash ? `#${urlValues.hash}` : ''}`;\n}\n\n/**\n * @public getParamFromURL\n * @param {string} url - The url from which the parameter will be retrieved\n * @param {string} name - The name of the parameter that will be retrieved from url\n * @returns {string} The value of the parameter\n *\n * @description\n * remove the parameter and its value from the given url and returns the\n * changed url\n */\nexport function getParamFromURL(url, name) {\n if (!url.includes('?') || !url.includes(`${name}=`)) return url;\n\n const urlValues = splitUpUrl(url);\n const nameMatch = urlValues.params.find((item) => item.includes(`${name}=`));\n\n return nameMatch && nameMatch.split('=').at(1);\n}\n\n/**\n * @public appendParamToURL\n * @param {string} url - The url to which the parameter will be added\n * @param {string} name - The name of the parameter\n * @param {string} value the value of the parameter\n * @returns {string} url\n *\n * @description\n * appends the parameter with the given name and value to the given url\n * and returns the changed url\n */\nexport function appendParamToURL(url, name, value) {\n let newURL = url;\n // remove if the param already exists\n if (url.includes(`${name}=`)) {\n newURL = removeParamFromURL(url, name);\n }\n const separator = newURL.includes('?') ? '&' : '?';\n return `${newURL}${separator}${name}=${encodeURIComponent(value)}`;\n}\n\n/**\n * @public appendCsrfToUrl\n * @description Takes a URL and adds a CSRF token to it\n * @param {string} url - The URL to append the CSRF token on\n * @returns {string} The URL with the CSRF token appended\n */\nexport function appendCsrfToUrl(url) {\n const separator = url.includes('?') ? '&' : '?';\n return `${url}${separator}${window.csrf.tokenName}=${window.csrf.token}`;\n}\n\n/**\n * @public removeHash\n * @description Will remove the hash from the url\n */\nexport function removeHash() {\n window.history.replaceState({}, document.title, window.location.pathname + window.location.search);\n}\n\nexport const getUrlFromAttributes = (url, component, excludedAttributes) => {\n const newUrl = new URL(url);\n const urlParams = newUrl.searchParams;\n\n // Get all attributeNames except for the irrelevant ones.\n const attributeNames = component.getAttributeNames().filter((attributeName) => !excludedAttributes.includes(attributeName));\n\n // Filter the attributeNames which will be replaced by the new URL.\n attributeNames\n .filter((param) => !urlParams.has(param.replaceAll('-', '')))\n .forEach((attr) => {\n const attrValue = component.getAttribute(attr);\n if (attrValue) {\n const attrName = attr.replaceAll('-', '');\n // Append all other attributes to the new URL\n urlParams.append(attrName, attrValue);\n }\n });\n\n return `${newUrl.origin}${newUrl.pathname}?${urlParams}`;\n};\n\n/**\n * This function checks if the provided element is a part of BM Hardware card. In case of true it appends\n * the 'editIndex' parameter to the URL with the index of the current BM Hardware card, in order to keep the\n * card open after Product-Variation ajax.\n *\n * @public appendBmHardwareCardIndex\n * @param {HTMLElement} element - The HTML element triggering the ajax.\n * @param {string} url - The URL to which the parameter will be appended.\n * @returns {string} The modified URL with the appended parameter.\n */\nexport function appendBmHardwareCardIndex(element, url) {\n let newURL = url;\n if (!element.closest('.js-hardware-device-card')?.classList.contains('is-collapsed') && element.closest('.js-hardware-phones')) {\n newURL = appendParamToURL(url, 'editIndex', element.closest('.js-hardware-phones').dataset.index);\n }\n return newURL;\n}\n","/**\n * @public setCookie\n * @param {string} cookieName - The cookie name\n * @param {string} cookieValue - The cookie value\n * @param {string} domain - The domain\n * @param {string} expirationDays - The expiration in days\n */\nfunction setCookie(cookieName, cookieValue, domain, expirationDays = 30) {\n const date = new Date();\n date.setTime(date.getTime() + expirationDays * 24 * 60 * 60 * 1000);\n const expires = `expires=${date.toUTCString()}`;\n const domainAndPath = `${domain ? `domain=${domain};` : ''}path=/; secure; sameSite=None`;\n const cookieString = `${cookieName}=${cookieValue};${expires};${domainAndPath}`;\n\n document.cookie = cookieString;\n}\n\n/**\n * @public getCookie\n * @param {string} cookieName - The cookie name\n * @return {string|null} The value of the cookie || null\n */\nfunction getCookie(cookieName) {\n const value = `; ${document.cookie}`;\n const parts = value.split(`; ${cookieName}=`);\n if (parts.length === 2) return parts.pop().split(';').shift();\n return null;\n}\n\nexport { setCookie, getCookie };\n","'use strict';\n\nimport { setCookie, getCookie } from 'Util/cookies';\n\n/**\n * @function getJourney\n * @description Retrieves the current journey a customer is in.\n * @returns {Array} An Array of products to be configured in the current journey.\n */\nfunction getJourney() {\n return (\n getCookie('journey')\n ?.split('|')\n .filter((item) => item.length > 0) || []\n );\n}\n\n/**\n * @function notifyJourneyModal\n * @param {Array} journey - A stringified version of the journey Object\n * @description Notifies the journey modal on the new journey state\n */\nfunction notifyJourneyModal(journey) {\n const journeyModal = document.getElementById('journey-modal');\n if (journeyModal) {\n journeyModal.setAttribute('products', journey.join('|'));\n }\n}\n\n/**\n * @function updateJourney\n * @param {Array} journey - The updated journey\n * @param {Object} urls - The urls for adding journey products to basket\n * @description Updates the journey with newly added or removed products.\n */\nfunction updateJourney(journey, urls) {\n // cookie lifetime is similar to basket lifetime (4h)\n setCookie('journey', journey.join('|'), window.location.hostname, 0.1667);\n if (urls) {\n setCookie('journeyUpdateUrl-business-mobile', urls['business-mobile'], window.location.hostname, 0.1667);\n setCookie('journeyUpdateUrl-internet', urls.internet, window.location.hostname, 0.1667);\n }\n}\n\n/**\n * @function clearJourney\n * @description Clears the journey\n */\nfunction clearJourney() {\n setCookie('journey', null, window.location.hostname, 0);\n setCookie('journeyUpdateUrl-business-mobile', null, window.location.hostname, 0);\n setCookie('journeyUpdateUrl-internet', null, window.location.hostname, 0);\n}\n\nexport { clearJourney, getJourney, notifyJourneyModal, updateJourney };\n","'use strict';\n\nimport VZSpinner from 'Components/VZSpinner';\nimport { appendParamToURL } from 'Root/util/urlUtils';\nimport { getJourney, updateJourney, clearJourney } from '../../journey/journeyHelper';\n\nclass VZDeleteGroup extends HTMLElement {\n constructor() {\n super();\n }\n\n connectedCallback() {\n this.addEventListener('click', this.onClick);\n this.deleteBtn = this.querySelector('a');\n }\n\n disconnectedCallback() {\n this.removeEventListener('click', this.onClick);\n }\n\n /**\n * @function removeDeletedGroup\n * @description removes the deleted group from the DOM after it has been removed from the basket and dispatches an\n * event to update the monthly total\n */\n removeDeletedGroup() {\n const isMiniCart = !!this.deleteBtn.closest('vz-drawer');\n window.location = isMiniCart ? appendParamToURL(window.location.href, 'showMinicart', 'true') : window.location.href;\n }\n\n onClick(evt) {\n const spinner = document.querySelector('vz-spinner') || new VZSpinner();\n spinner.start();\n evt.preventDefault();\n\n const removeFromJourneyEmptyProduct = this.deleteBtn.getAttribute('data-empty-journey-remove');\n const removeFromJourneyExistingProduct = this.deleteBtn.getAttribute('data-journey-remove');\n\n if (removeFromJourneyEmptyProduct || removeFromJourneyExistingProduct) {\n let journey = getJourney();\n if (journey.length > 0) {\n journey = journey.filter((item) => item !== removeFromJourneyEmptyProduct && item !== removeFromJourneyExistingProduct);\n if (journey.every((id) => id === 'one-net') || removeFromJourneyExistingProduct === 'one-net') {\n clearJourney();\n } else {\n updateJourney(journey);\n }\n if (removeFromJourneyEmptyProduct) {\n spinner.stop();\n window.location.reload();\n return;\n }\n }\n }\n\n fetch(this.deleteBtn.href, {\n method: this.deleteBtn.getAttribute('data-type') || 'GET'\n })\n .then(this.removeDeletedGroup.bind(this))\n .finally(spinner.stop);\n }\n}\n\nexport default window.customElements.get('vz-delete-group') || VZDeleteGroup;\n\nif (!window.customElements.get('vz-delete-group')) {\n window.customElements.define('vz-delete-group', VZDeleteGroup);\n}\n","'use strict';\n\nconst computedStyles = getComputedStyle(document.documentElement);\n\n/**\n * @constant {Object} events - All common events\n * @property {string} blur - Blur event\n * @property {string} change - Change event\n * @property {string} click - Click event\n * @property {string} keyUp - Keyup event\n * @property {string} load - Load event\n * @property {string} mousedown - Mouse down event\n * @property {string} mouseleave - Mouse leave event\n * @property {string} mouseover - Mouse over event\n * @property {string} popstate - Popstate event\n * @property {string} resize - Resize event\n * @property {string} scroll - Scroll event\n * @property {string} submit - Submit event\n * @property {string} update - Custom update event\n */\nconst events = {\n blur: 'blur',\n change: 'change',\n click: 'click',\n input: 'input',\n keyUp: 'keyup',\n load: 'load',\n mousedown: 'mousedown',\n mouseleave: 'mouseleave',\n mouseover: 'mouseover',\n paste: 'paste',\n popstate: 'popstate',\n resize: 'resize',\n responseError: 'responseError',\n scroll: 'scroll',\n submit: 'submit',\n transitionEnd: 'transitionend',\n update: 'update',\n invalid: 'invalid'\n};\n\n/**\n * @constant {Object} selectors - Common selectors\n * @property {string} body - body\n * @property {Object} form - form related selectors\n * @property {string} checkbox - checkbox\n * @property {string} form - form\n * @property {string} input - input\n * @property {string} inputFieldClear - .js-input-clear\n * @property {string} inputFieldFeedback - .js-invalid-feedback\n * @property {string} label - label\n * @property {string} radio - radio\n * @property {string} select - select\n * @property {string} submit - [type=\"submit\"]\n * @property {string} textarea - textarea\n * @property {string} html - html\n * @property {string} htmlBody - html, body\n * @property {string} img - img\n * @property {string} input - input\n */\nconst selectors = {\n body: 'body',\n form: {\n checkbox: 'input[type=\"checkbox\"]',\n file: 'input[type=\"file\"]',\n form: 'form',\n input: 'input',\n inputFieldClear: '.js-input-clear',\n inputFieldFeedback: '.js-invalid-feedback',\n label: 'label',\n radio: 'input[type=\"radio\"]',\n select: 'select',\n submit: '[type=\"submit\"]',\n textarea: 'textarea'\n },\n html: 'html',\n htmlBody: 'html, body',\n img: 'img',\n input: 'input',\n interactiveElements: 'input, button, select, textarea, a[href]'\n};\n\n/**\n * @constant {Object} classes - Common classes\n * @property {string} active - active\n * @property {Object} buttons - buttons\n * @property {string} next - next\n * @property {string} previous - previous\n * @property {string} warning - warning\n * @property {string} dBlock - d-block\n * @property {string} dFlex - d-flex\n * @property {string} dInlineBlock - d-inline-block\n * @property {string} dNone - d-none\n * @property {string} disabled - disabled\n * @property {string} empty - empty\n * @property {string} inactive - inactive\n * @property {string} invalid - invalid\n * @property {string} hidden - hidden\n * @property {string} last - last\n * @property {string} show - show\n * @property {string} valid - valid\n */\nconst classes = {\n active: 'active',\n buttons: {\n next: 'js-button-next',\n previous: 'js-button-previous',\n warning: 'js-button-warning'\n },\n dBlock: 'd-block',\n dFlex: 'd-flex',\n dInlineBlock: 'd-inline-block',\n dNone: 'd-none',\n disabled: 'disabled',\n empty: 'empty',\n inactive: 'inactive',\n invalid: 'invalid',\n hidden: 'hidden',\n last: 'last',\n show: 'show',\n valid: 'valid'\n};\n\n/**\n * @constant {Object} attributes - Common attributes\n * @property {string} action - action\n * @property {string} class - class\n * @property {string} csrfToken - data-csrf-token\n * @property {string} csrfName - data-csrf-name\n * @property {string} disabled - disabled\n * @property {string} exclude - data-exclude\n * @property {string} href - href\n * @property {string} id - id\n * @property {string} pattern - pattern\n * @property {string} url - url\n * @property {string} readonly - readonly\n * @property {string} target - data-bs-target\n * @property {string} value - value\n * @property {Object} validation - Validation related attributes\n * @property {string} patternMismatch - data-pattern-mismatch\n * @property {string} valueMissing - data-missing-error\n */\nconst attributes = {\n action: 'action',\n class: 'class',\n checked: 'checked',\n csrfToken: 'data-csrf-token',\n csrfName: 'data-csrf-name',\n disabled: 'disabled',\n exclude: 'data-exclude',\n href: 'href',\n id: 'id',\n pattern: 'pattern',\n placeholder: 'placeholder',\n required: 'required',\n readonly: 'readonly',\n selected: 'selected',\n target: 'data-bs-target',\n url: 'url',\n value: 'value',\n validation: {\n patternMismatch: 'data-pattern-mismatch',\n valueMissing: 'data-missing-error',\n tooShort: 'data-too-short'\n }\n};\n\n/**\n * @constant {Object} breakpoints - Common reusable breakpoints\n * @property {string} xxs - 0\n * @property {string} xs - 368\n * @property {string} sm - 576\n * @property {string} md - 768\n * @property {string} lg - 992\n * @property {string} xl - 1200\n * @property {string} xxl - 1400\n */\n\nconst breakpoints = {\n xxs: parseInt(computedStyles.getPropertyValue('--breakpoint-xxs'), 10),\n xs: parseInt(computedStyles.getPropertyValue('--breakpoint-xs'), 10),\n sm: parseInt(computedStyles.getPropertyValue('--breakpoint-sm'), 10),\n md: parseInt(computedStyles.getPropertyValue('--breakpoint-md'), 10),\n lg: parseInt(computedStyles.getPropertyValue('--breakpoint-lg'), 10),\n xl: parseInt(computedStyles.getPropertyValue('--breakpoint-xl'), 10),\n xxl: parseInt(computedStyles.getPropertyValue('--breakpoint-xxl'), 10)\n};\n\n/**\n * @constant {Object} localStorage - constants for local storage items\n * @property {string} preferredLayoutId - preferredLayoutId\n */\nconst localStorage = {\n preferredLayoutId: 'preferredLayoutId'\n};\n\n/**\n * @constant {Object} bscanSteps - constants for Business Scan Steps\n * @property {string} ADVICE - The advice Step\n * @property {string} INTRO - The intro Step\n * @property {string} GROUPED_QUESTIONS - The grouped questions Step\n * @property {string} THANKYOU - The thank you Step\n */\nconst bscanSteps = {\n INTRO: 'intro',\n STATEMENTS_DONE: 'bs-statements-done',\n GROUPED_QUESTIONS: 'js-bscan-question-group',\n ADVICE: 'bs-advice',\n THANKYOU: 'bs-thank-you'\n};\n\n/**\n * @constant {Object} vzLayoutToggle - Attributes used for VZLayoutToggle\n * @property {string} class - data-layout-class\n * @property {string} container - data-layout-container\n * @property {string} enabledBreakpoint - data-layout-enabled-breakpoint\n * @property {string} id - data-layout-id\n * @property {string} idDefault - data-layout-id-default\n * @property {string} localStorageKey - data-layout-key\n */\nconst vzLayoutToggle = {\n class: 'data-layout-class',\n container: 'data-layout-container',\n enabledBreakpoint: 'data-layout-enabled-breakpoint',\n id: 'data-layout-id',\n idDefault: 'data-layout-id-default',\n localStorageKey: 'data-layout-key'\n};\n\nexport default {\n bscanSteps,\n attributes,\n breakpoints,\n classes,\n events,\n selectors,\n localStorage,\n vzLayoutToggle\n};\n","'use strict';\n\nimport CONST from './constants';\n\n/**\n * addEvent - Will add an event listener to an element inside a parent\n *\n * @param {string} parent - The parent element\n * @param {string} passedEvent - The event\n * @param {string} selector - The targeted element\n * @param {function} handler - The handler\n */\nfunction addEvent(parent, passedEvent, selector, handler) {\n parent.addEventListener(\n passedEvent,\n function fnAddEvent(event) {\n // If the clicked element matches the selector, or is a child of the selector\n if (event.target.matches(`${selector} , ${selector} *`)) {\n handler.apply(event.target.closest(selector), arguments);\n }\n },\n false\n );\n}\n\n/**\n * @public documentReady\n * @param {Function} fn - function to be called after document is done loading.\n */\nfunction documentReady(fn) {\n if (document.readyState !== 'loading') {\n fn();\n } else {\n document.addEventListener('DOMContentLoaded', fn);\n }\n}\n\n/**\n * @public exists\n * @param {*} selection - The element or nodelist to verify for existence\n * @returns {boolean} - Boolean value stating the existance of the selection\n * @description\n * Verifies existance of a certain element by checking for type, null and length\n * Usage: use with either querySelector() or querySelectorAll()\n * querySelector will not have a 'length', e.g. this would return true if other conditions are true\n * querySelectorAll will have a 'length', e.g. this would return true if all conditions are true\n */\nfunction exists(selection) {\n return typeof selection !== 'undefined' && selection !== null && ('length' in selection ? selection.length > 0 : true);\n}\n\n/**\n * @public getPosition\n * @param {*} element - The element to get the position for\n * @returns {Object} - An object containing the left and top position of the element\n *\n * @description\n * Will get the position of an element relative to the document\n */\nfunction getPosition(element) {\n let top = element.offsetTop;\n let left = element.offsetLeft;\n\n let currentElement = element;\n while (currentElement.offsetParent && currentElement.offsetParent !== window) {\n currentElement = currentElement.offsetParent;\n top += currentElement.offsetTop;\n left += currentElement.offsetLeft;\n }\n\n return { left, top };\n}\n\n/**\n * isKeyInObject\n * @param {Object} object - The object\n * @param {string} key - The key\n * @returns {boolean} - True or false\n */\nfunction isKeyInObject(object, key) {\n return Object.prototype.hasOwnProperty.call(object, key);\n}\n\n/**\n * @private isAemMobileView\n * @returns {boolean} - Whether the user is on a \"mobile\" viewport or not based on AEM rules\n *\n * @description\n * Checks to see whether the user is on a \"mobile\" viewport or not based on AEM rules\n * Please note that www.vodafone.nl/zakelijk will show the mobile menu from viewports 1023 and smaller\n */\nfunction isAemMobileView() {\n return window.innerWidth < 1024;\n}\n\n/**\n * @memberof util\n * @param {string} breakpointKey from constants that should match css breakpoint\n * @param {boolean} [isUp] by default is true since mobile first, reverses condition\n * @return {boolean} whether window is larger than specified breakpoint\n */\nfunction isMediaBreakpoint(breakpointKey, isUp = true) {\n if (!isKeyInObject(CONST.breakpoints, breakpointKey)) {\n console.error(`fn isMediaBreakpoint: ${breakpointKey} -- does not exist in constants breakpoints object`); // eslint-disable-line\n }\n\n const outerWidth = window.innerWidth;\n const breakpointValue = parseInt(CONST.breakpoints[breakpointKey], 10);\n\n return isUp ? outerWidth > breakpointValue : outerWidth < breakpointValue - 1;\n}\n\n/**\n * @memberof util\n * @return {Object} An object containing the name and value of the current breakpoint\n */\nfunction getCurrentBreakpoint() {\n const breakpoints = CONST.breakpoints;\n const screenSize = document.documentElement.clientWidth;\n const currentBreakpoint = [...Object.keys(breakpoints)].reverse().find((key) => screenSize > breakpoints[key]);\n\n return {\n name: currentBreakpoint,\n value: breakpoints[currentBreakpoint]\n };\n}\n\n/**\n * @memberof util\n * @return {number} a unique number\n */\nfunction generateUniqueNumber() {\n return performance.now().toString().replace('.', 0);\n}\n\n/**\n * @public empty\n * @param {*} element - The element to remove child nodes from\n * @description\n * Empties a given element completely while the given element has child nodes.\n * Plain strings are also considered child nodes and are thus also removed.\n */\nfunction removeChildNodes(element) {\n while (element.hasChildNodes()) {\n element.removeChild(element.lastChild);\n }\n}\n\n/**\n * @public tryParseJSON\n * @param {string} string - The possible JON string\n * @returns {Object} - Either the JSON object or an empty object for consistent return\n * @description\n * Copied from https://stackoverflow.com/a/20392392\n */\nfunction tryParseJSON(string) {\n try {\n const o = JSON.parse(string);\n\n // Handle non-exception-throwing cases:\n // Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,\n // but... JSON.parse(null) returns null, and typeof null === \"object\",\n // so we must check for that, too. Thankfully, null is falsey, so this suffices:\n if (o && typeof o === 'object') {\n return o;\n }\n } catch (e) {} // eslint-disable-line no-empty\n\n return {};\n}\n\n/**\n * @function isIOS\n * @public\n * @description returns a boolean to determine whether a device's OS is IOS or not\n * @returns {boolean} whether the device OS is IOS or not\n */\nfunction isIOS() {\n return (/iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) && !window.MSStream;\n}\n\n/**\n * @function isMobile\n * @returns {boolean} whether the device is an mobile device or not\n */\nfunction isMobile() {\n return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n}\n\n/**\n * @public scrollTo\n * @param {Object} data - The optional object containing the top & left positions to scroll to\n */\nfunction scrollTo(data) {\n const position = data || {\n top: 0,\n left: 0\n };\n\n const stickyHeader = document.querySelector('.page-header');\n const headerHeight = stickyHeader ? stickyHeader.offsetHeight : 0;\n const supportsNativeSmoothScroll = 'scrollBehavior' in document.documentElement.style;\n let positionTop = position.top;\n\n if (headerHeight > 0) {\n positionTop = position.top - headerHeight - 15; // Removing an additional 15px to put some space between the sticky site header and the element\n }\n\n if (supportsNativeSmoothScroll) {\n document.documentElement.scrollTo({\n top: positionTop,\n left: position.left,\n behavior: 'smooth'\n });\n } else {\n document.documentElement.scrollTop = positionTop;\n }\n}\n\n/**\n * @function toggleButtonState\n * @description Enables or disabled the button passed in based on the value of the second parameter.\n * @param {HTMLElement} button - A button element to be enabled or disabled.\n * @param {boolean} enable - True for enable and false for disable.\n */\nfunction toggleButtonState(button, enable) {\n if (enable) {\n button.classList.remove('disabled');\n button.removeAttribute('disabled');\n } else {\n button.classList.add('disabled');\n button.setAttribute('disabled', 'disabled');\n }\n}\n\n/**\n * @function removeAccentCharacters\n * @description Removes a accents from a string.\n * @param {string} string - The string from which we want to remove accents.\n * @returns {string} The string without accents.\n */\nfunction removeAccentCharacters(string) {\n return string.normalize('NFD').replace(/\\p{Diacritic}/gu, '');\n}\n\n/**\n * @function chunkArrayInGroups\n * @param {Array} arr - Array to be splitted\n * @param {number} size - Max size of the array chunk\n * @return {Array} - Array of grouped chunks\n * @description Splitting an array up into chunks of a given size\n */\nfunction chunkArrayInGroups(arr, size) {\n var groupedChunks = [];\n for (let i = 0; i < arr.length; i += size) {\n groupedChunks.push(arr.slice(i, i + size));\n }\n return groupedChunks;\n}\n\n/**\n * @function chunkGroupArrayInGroups\n * @param {Array} groupArr - Array to be splitted\n * @return {Array} - Array of grouped chunks\n * @description Splitting an array up into chunks of a given size\n */\nfunction chunkGroupArrayInGroups(groupArr) {\n // This one sorts and groups the alike product groups together\n // We need to send the requests to backend in a specific order, so we make it grouped\n const chunkGroups = [];\n Object.keys(groupArr).forEach((groupKey) => {\n const arr = groupArr[groupKey];\n const groupedChunks = [];\n // Sorts the product objects based on pids\n arr.sort((a, b) => {\n return a.pid >= b.pid ? 1 : -1;\n });\n for (let i = 0; i < arr.length; i += Math.round(arr.length / 3)) {\n groupedChunks.push(arr.slice(i, i + Math.round(arr.length / 3)));\n }\n // This makes sure that we have a separate business mobile group to send to backend\n groupedChunks.forEach((chunk, chunkIndex) => {\n Object.keys(chunk).forEach((key, index) => {\n const item = chunk[key];\n if (item?.pdpConfiguratorType === 'business-mobile') {\n chunk.splice(index, 1);\n if (chunk.length < 1) groupedChunks.splice(chunkIndex, 1);\n groupedChunks.push(item);\n }\n });\n });\n chunkGroups.push(groupedChunks);\n });\n return chunkGroups;\n}\n\n/**\n * @function trackPdpEccomerceEvent\n * @param {string} productType - Configurator type\n * @param {Object} step - Step to track\n * @description Builds and submits ecommerce event to track btn clicks on PDP\n */\nfunction trackPdpEccomerceEvent(productType, step) {\n const products = {\n brand: 'vodafone',\n category: `business-sme/acquisition/postpaid/${productType.replace(/\\s|business-/gi, '')}`,\n market: 'b2b'\n };\n\n const ecommerceObject = {\n event: 'checkout',\n events: {\n category: 'ecommerce',\n action: 'checkout'\n },\n ecommerce: {\n checkout: {\n action: 'checkout',\n has_vodafone: true,\n has_ziggo: true,\n products: products,\n step_name: step.name,\n step_nr: step.number\n }\n }\n };\n\n /* eslint-disable no-underscore-dangle */\n if (ecommerceObject && window._ddm) {\n window.dataLayer = window.dataLayer || [];\n window.dataLayer.push(ecommerceObject);\n window._ddm.trigger('ecommerce.checkout', {\n data: ecommerceObject.ecommerce.checkout\n });\n }\n /* eslint-enable no-underscore-dangle */\n}\n\n/**\n * @function assignStyling\n * @private\n * @param {Element} el - Element\n * @param {Object} styles - Styles\n * @description Assign a style object to an element\n */\nfunction assignStyling(el, styles) {\n Object.assign(el.style, styles);\n}\n\n/**\n * Calculate the total width of a collection of elements.\n *\n * @param {NodeListOf} elements - A collection of HTML elements.\n * @param {number} spacing - flex gap value in px.\n * @returns {number} The total width of all elements.\n */\nfunction getTotalWidth(elements, spacing = 0) {\n return Array.from(elements).reduce((totalWidth, element) => {\n const elementStyles = window.getComputedStyle(element);\n const elementWidth = element.offsetWidth + parseFloat(elementStyles.marginLeft) + parseFloat(elementStyles.marginRight);\n return totalWidth + elementWidth;\n }, spacing);\n}\n\n/**\n * Checks if a flex container is wrapped by comparing the total width of its flex items\n * with the container's width.\n *\n * @param {HTMLElement} flexContainer - The HTML element representing the flex container.\n * @param {NodeListOf} flexItems - A collection of HTML elements representing the flex items.\n * @param {number} spacing - flex gap value in px.\n * @returns {boolean} True if the flex container is wrapped, false if all items fit in a single row.\n */\nfunction isFlexContainerWrapped(flexContainer, flexItems, spacing) {\n const containerWidth = flexContainer.clientWidth;\n const itemsTotalWidth = getTotalWidth(flexItems, spacing);\n // Check if the items are wrapped by comparing their total width with the container width.\n const isWrapped = itemsTotalWidth > containerWidth;\n return isWrapped;\n}\n\n/**\n * @function loadCSS\n * @param {string} url - The URL of the CSS file to load.\n * @description Creates a link element and appends it to the document head to load a CSS file.\n */\nfunction loadCSS(url) {\n if (!url || document.querySelector(`link[href=\"${url}\"]`)) {\n return;\n }\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n document.head.appendChild(link);\n}\n\n/**\n * The function formats input to money string\n *\n * @param {number} num Source number\n * @returns {string} Formatted string € 1.111,11\n */\nfunction formatToPriceString(num) {\n const parts = Number.parseFloat(num, 10).toFixed(2).toString().split('.');\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.');\n if (parts[1] === '00') {\n return `€ ${parts[0]},00`;\n }\n return `€ ${parts.join(',')}`;\n}\n\n/**\n * Checks if two arrays of objects are equal by comparing their elements.\n *\n * @param {Array} arr1 - The first array to compare.\n * @param {Array} arr2 - The second array to compare.\n * @returns {boolean} True if the arrays are equal, false otherwise.\n */\nfunction arraysAreEqual(arr1, arr2) {\n if (arr1.length !== arr2.length) {\n return false;\n }\n\n return (\n !arr1.some((obj1) => !arr2.some((obj2) => JSON.stringify(obj1) === JSON.stringify(obj2))) &&\n !arr2.some((obj2) => !arr1.some((obj1) => JSON.stringify(obj1) === JSON.stringify(obj2)))\n );\n}\n\nexport {\n CONST,\n addEvent,\n documentReady,\n exists,\n generateUniqueNumber,\n getCurrentBreakpoint,\n getPosition,\n isIOS,\n isMobile,\n isKeyInObject,\n isAemMobileView,\n isMediaBreakpoint,\n removeChildNodes,\n scrollTo,\n tryParseJSON,\n toggleButtonState,\n removeAccentCharacters,\n chunkArrayInGroups,\n chunkGroupArrayInGroups,\n trackPdpEccomerceEvent,\n assignStyling,\n isFlexContainerWrapped,\n getTotalWidth,\n loadCSS,\n formatToPriceString,\n arraysAreEqual\n};\n","'use strict';\n\nimport { CONST, documentReady, addEvent } from 'app_vodafone_ziggo/util/util';\n\n/**\n * @constant {Object} selectors - Selectors used for the Prompt\n * @property {string} promptOpen - .js-btn-prompt-open\n * @property {string} promptCancel - .js-btn-prompt-cancel\n * @property {string} promptConfirm - .js-btn-prompt-confirm\n */\nconst selectors = {\n prompt: '.js-prompt',\n promptOpen: '.js-btn-prompt-open',\n promptCancel: '.js-btn-prompt-cancel',\n promptConfirm: '.js-btn-prompt-confirm',\n chatPromptOpen: '.dimelo_chat_show_when_offline',\n chatClosedPrompt: '#bscan-chat-closed'\n};\n\n/**\n * @private promptOpen\n * @param {event} event - The click event\n */\nfunction promptOpen(event) {\n const button = event.target;\n const target = button.getAttribute(CONST.attributes.target);\n const prompt = document.querySelector(target);\n\n if (prompt) {\n prompt.classList.add(CONST.classes.active);\n }\n}\n\n/**\n * @private promptClose\n * @param {event} event - The click event\n * @param {boolean} confirm - If the \"confirm\" button has been clicked\n */\nfunction promptClose(event, confirm) {\n if (!confirm) {\n event.preventDefault();\n }\n\n const button = event.target;\n const prompt = button.closest(selectors.prompt);\n\n if (prompt) {\n prompt.classList.remove(CONST.classes.active);\n button.blur(); // Remove the focus on the button, necessary for BScan keyboard navigation\n }\n}\n\ndocumentReady(() => {\n addEvent(document, CONST.events.click, selectors.promptOpen, promptOpen);\n addEvent(document, CONST.events.click, selectors.promptCancel, (event) => {\n promptClose(event, false);\n });\n addEvent(document, CONST.events.click, selectors.promptConfirm, (event) => {\n promptClose(event, true);\n });\n\n addEvent(document, CONST.events.click, selectors.chatPromptOpen, (event) => {\n const button = event.target;\n\n if (!button.getAttribute(CONST.attributes.target)) {\n button.setAttribute(CONST.attributes.target, selectors.chatClosedPrompt);\n }\n\n promptOpen(event);\n });\n});\n","'use strict';\n\n// Can't import cartridges/app_vodafone_ziggo/cartridge/scripts/forms/validator.js\nconst ID_TYPES_CODES = {\n idCard: '1',\n passport: '2',\n driversLicense: '3',\n permit1: '4',\n permit2: '5',\n permit3: '6',\n permit4: '7',\n permit5: '8',\n permitEU: '9',\n other: '10'\n};\n\nconst ID_VALIDATION_RULES = {};\nID_VALIDATION_RULES[ID_TYPES_CODES.passport] = /^[A-NP-Z]{2}[\\dA-NP-Z]{6}\\d{1}$/gi;\nID_VALIDATION_RULES[ID_TYPES_CODES.idCard] = ID_VALIDATION_RULES[ID_TYPES_CODES.passport];\nID_VALIDATION_RULES[ID_TYPES_CODES.driversLicense] = /^\\d{10}$/gi;\nID_VALIDATION_RULES[ID_TYPES_CODES.permit1] = /^(?!(X00|V))[\\dA-Z]{8,9}$/gi;\nID_VALIDATION_RULES[ID_TYPES_CODES.permit2] = ID_VALIDATION_RULES[ID_TYPES_CODES.permit1];\nID_VALIDATION_RULES[ID_TYPES_CODES.permit2] = ID_VALIDATION_RULES[ID_TYPES_CODES.permit1];\nID_VALIDATION_RULES[ID_TYPES_CODES.permit3] = ID_VALIDATION_RULES[ID_TYPES_CODES.permit1];\nID_VALIDATION_RULES[ID_TYPES_CODES.permit4] = ID_VALIDATION_RULES[ID_TYPES_CODES.permit1];\nID_VALIDATION_RULES[ID_TYPES_CODES.permit5] = ID_VALIDATION_RULES[ID_TYPES_CODES.permit1];\nID_VALIDATION_RULES[ID_TYPES_CODES.permitEU] = ID_VALIDATION_RULES[ID_TYPES_CODES.permit1];\n\n// this regexp is always invalid\nID_VALIDATION_RULES[ID_TYPES_CODES.other] = /(?=a)b/;\n\n/**\n * @constant {string} ID_TYPE - Selector for identification type\n */\nconst ID_TYPE = 'dwfrm_checkoutDetails_identification_idtype';\n\n/**\n * @private setValidationPattern\n * @param {Event} evt - Change or load event\n */\nfunction setValidationPattern(evt) {\n const element = evt.target.id === ID_TYPE ? evt.target : document.getElementById(ID_TYPE);\n if (element.value) {\n element.closest('form').dispatchEvent(\n new CustomEvent('identificationTypeChanged', {\n detail: {\n type: element.value,\n regex: ID_VALIDATION_RULES[element.value]\n }\n })\n );\n }\n}\n\n/**\n * @public idType\n * @param {HTMLSelectElement} element - Identification type selector\n */\nexport default function idType(element) {\n if (element.id !== ID_TYPE) return;\n\n element.addEventListener('change', setValidationPattern);\n window.addEventListener('load', setValidationPattern);\n}\n","'use strict';\n\n/**\n * @constant {string} CAPS_MASK_ATTRIBUTE - Attribute value for caps mask\n */\nexport const CAPS_MASK_ATTRIBUTE = 'caps';\n\n/**\n * @class CapsMask\n * @param {HTMLInputElement} element - An input field\n */\nexport class CapsMask {\n constructor(element) {\n element.addEventListener('input', this.onInput.bind(element));\n element.addEventListener('change', this.onInput.bind(element));\n }\n\n onInput() {\n const position = this.selectionStart;\n this.value = this.value.toUpperCase();\n this.setSelectionRange(position, position);\n }\n}\n","'use strict';\n\nimport { CapsMask } from './caps';\n\n/**\n * @constant {string} POSTCODE_MASK_ATTRIBUTE - Attribute value for postcode mask\n */\nconst POSTCODE_MASK_ATTRIBUTE = 'postcode';\n\n/**\n * @constant {integer} BACKSPACE_KEYCODE\n */\nconst BACKSPACE_KEYCODE = 8;\n\n/**\n * @constant {integer} DELETE_KEYCODE\n */\nconst DELETE_KEYCODE = 46;\n\n/**\n * @constant {Array} UNDO_KEYS\n */\nconst UNDO_KEYS = [BACKSPACE_KEYCODE, DELETE_KEYCODE, 'backspace', 'delete'];\n\n/**\n * @class PostCodeMask\n * @param {HTMLInputElement} element - The input field to put the postcode mask on.\n */\nclass PostCodeMask extends CapsMask {\n constructor(element) {\n super(element);\n this.element = element;\n this.onKeyUp = this.onKeyUp.bind(this);\n\n element.addEventListener('keyup', this.onKeyUp);\n }\n\n /**\n * @private onKeyUp\n * @param {KeyboardEvent} evt - On key up event\n */\n onKeyUp(evt) {\n const key = evt.key && typeof evt.key !== 'number' ? evt.key.toLocaleLowerCase() : evt.key || null;\n if (key && UNDO_KEYS.some((k) => k === key)) {\n if (this.element.value.length === 5) {\n this.element.value = this.element.value.substring(0, 4);\n }\n return;\n }\n\n // Mask the input value for postcodes using a regular expression.\n this.element.value = this.element.value.replace(/(^\\d{4})(\\w{0,2}$)/, '$1 $2');\n }\n}\n\nexport { PostCodeMask, POSTCODE_MASK_ATTRIBUTE };\n","'use strict';\n\nimport { CapsMask } from './caps';\n\n/**\n * @constant {string} POSTCODE_MASK_ATTRIBUTE - Attribute value for postcode mask\n */\nconst IBAN_MASK_ATTRIBUTE = 'iban';\n\n/**\n * @constant {integer} BACKSPACE_KEYCODE\n */\nconst BACKSPACE_KEYCODE = 8;\n\n/**\n * @constant {integer} DELETE_KEYCODE\n */\nconst DELETE_KEYCODE = 46;\n\n/**\n * @constant {Array} UNDO_KEYS\n */\nconst UNDO_KEYS = [BACKSPACE_KEYCODE, DELETE_KEYCODE, 'backspace', 'delete'];\n\nclass IBANMask extends CapsMask {\n constructor(element) {\n super(element);\n this.element = element;\n this.onKeyUp = this.onKeyUp.bind(this);\n\n element.addEventListener('keyup', this.onKeyUp);\n }\n\n /**\n * @private onKeyUp\n * @param {KeyboardEvent} evt - On key up event\n */\n onKeyUp(evt) {\n const key = evt.key && typeof evt.key !== 'number' ? evt.key.toLocaleLowerCase() : evt.key || null;\n if (key && UNDO_KEYS.some((k) => k === key)) {\n if (this.element.value.length % 4 === 1) {\n this.element.value = this.element.value.substring(0, this.element.value.length);\n }\n return;\n }\n\n // Mask the input value for iban using a regular expression.\n this.element.value = this.element.value\n .replace(/\\s/g, '')\n .replace(/^([a-zA-Z]{2}\\d{2})(\\w{0,4})(\\d{0,4})(\\d{0,4})(\\d{0,2})/, '$1 $2 $3 $4 $5')\n .replace(/\\s\\s+/g, ' ');\n }\n}\n\nexport { IBANMask, IBAN_MASK_ATTRIBUTE };\n","'use strict';\n\n/**\n * @constant {string} DATE_MASK_ATTRIBUTE - Attribute value for date mask\n */\nconst DATE_MASK_ATTRIBUTE = 'date';\n\nclass DateMask {\n constructor(element) {\n this.field = element;\n this.cursorIndex = 0;\n this.maskText = element.getAttribute('data-mask-text');\n this.pressedCharacters = [];\n\n this.onInput = this.onInput.bind(this);\n this.onPaste = this.onPaste.bind(this);\n this.replaceRemovedDigitWithLetter = this.replaceRemovedDigitWithLetter.bind(this);\n this.onArrowRight = this.onArrowRight.bind(this);\n this.onArrowLeft = this.onArrowLeft.bind(this);\n this.onCharacterRemoval = this.onCharacterRemoval.bind(this);\n this.checkIfDashIsSelected = this.checkIfDashIsSelected.bind(this);\n this.replaceAsYouType = this.replaceAsYouType.bind(this);\n\n element.addEventListener('keydown', this.onKeyDown.bind(this));\n element.addEventListener('keyup', this.onInput);\n element.addEventListener('paste', this.onPaste);\n }\n\n /**\n * @private runRegexOnValue\n * @param {string} value - The value\n * @returns {array} - The final manipulated value as an array with each character\n *\n * @description\n * Mask the input value for date using regular expressions and enforcing dashes at specific locations\n */\n static runRegexOnValue(value) {\n return value\n .toUpperCase() // In case lowercase d/m/j letters are entered\n .replace(/^(\\d{1}-)-/, '0$1-') // If we already have the mask and one digit plus a dash has been entered, prepend a 0\n .replace(/-(\\d{1}-)-/, '-0$1-') // For the 2nd group, do the same and prepend a 0\n\n .replace(/-+-/g, '-') // Convert multiple dashes to a single dash\n .replace(/[^\\dDMJ-]/g, '') // Remove any character that is not [numeric, letters D/M/J, a dash]\n .replace(/^-(\\d{1})/, '$1') // If the string starts with a dash, remove the dash\n .replace(/-/g, '') // After all manipulations and cleaning up, remove all dashes (which could also have been added in the 3rd group) and..\n .split(''); // split up our current string so we can enforce dashes on specific locations only\n }\n\n /**\n * @private totalLengthUntilLastDigit\n * @param {string} newVal - The value\n * @returns {number} - The total length\n *\n * @description\n * Calculate what the total length of newVal would be once the dashes are added through `splice`, only until the last entered digit\n * We need this to do calculations for cursorOffset\n */\n static totalLengthUntilLastDigit(newVal) {\n const untilLastDigit = newVal.join('').replace(/[\\D]*$/, '');\n let totalLength = untilLastDigit.length;\n if (totalLength > 4) {\n totalLength += 1;\n }\n if (totalLength > 2) {\n totalLength += 1;\n }\n\n return totalLength;\n }\n\n /**\n * @private replaceRemovedDigitWithLetter\n * @param {string} newVal - The value\n * @returns {array} - The updated newVal\n *\n * @description\n * Will replace the removed digit with a corresponding letter from the maskText\n */\n replaceRemovedDigitWithLetter(newVal) {\n // Calculate the offset which is necessary to determine where the replacing character should be placed\n // The offset is based on the cursorIndex and the amount of dashes that are present\n let cursorOffset = 0;\n const cursorIndex = this.cursorIndex;\n\n if (cursorIndex === 3 || cursorIndex === 4) {\n cursorOffset -= 1;\n } else if (cursorIndex > 4) {\n cursorOffset -= 2;\n }\n\n // Decide which character should take it's place and add it to the array\n const removedCharacter = this.maskText.substring(cursorIndex, cursorIndex + 1);\n\n if (removedCharacter !== '-') {\n newVal.splice(cursorIndex + cursorOffset, 0, removedCharacter);\n }\n\n return newVal;\n }\n\n /**\n * @private addDashes\n * @param {string} newVal - The value\n * @returns {array} - The updated newVal\n *\n * @description\n * Will add dashes at specific spots\n */\n static addDashes(newVal) {\n // If we have 4 or more digits, add a dash\n if (newVal.length >= 4) {\n newVal.splice(4, 0, '-');\n }\n\n // If we have 2 or more digits, add a dash\n if (newVal.length >= 2) {\n newVal.splice(2, 0, '-');\n }\n\n return newVal;\n }\n\n /**\n * @private onArrowRight\n * @param {string} newVal - The value\n *\n * @description\n * Will move the cursor to the right based on some checks\n */\n onArrowRight(newVal) {\n if (this.checkIfDashIsSelected(newVal)) this.cursorIndex += 1;\n this.field.setSelectionRange(this.cursorIndex, this.cursorIndex);\n }\n\n /**\n * @private onArrowLeft\n * @param {string} newVal - The value\n *\n * @description\n * Will move the cursor to the left based on some checks\n */\n onArrowLeft(newVal) {\n if (this.checkIfDashIsSelected(newVal, 'left')) this.cursorIndex -= 1;\n this.field.setSelectionRange(this.cursorIndex, this.cursorIndex);\n }\n\n /**\n * @private onCharacterRemoval\n * @param {string} newVal - The value\n *\n * @description\n * Will move the cursor to the left based on some checks\n */\n onCharacterRemoval(newVal) {\n // If the character on the left is a dash, move an extra spot to the left\n if (this.checkIfDashIsSelected(newVal, 'left')) this.cursorIndex -= 1;\n\n // If we end up before the beginning, reset the index\n if (this.cursorIndex < 0) this.cursorIndex = 0;\n\n this.field.setSelectionRange(this.cursorIndex, this.cursorIndex);\n }\n\n /**\n * @private checkIfDashIsSelected\n * @param {string} value - The string to check\n * @param {string} direction - Either 'left' or 'right'\n * @param {number} offset - An optional offset\n * @returns {boolean} - True of false\n */\n checkIfDashIsSelected(value, direction, offset = 0) {\n const cursorIndex = this.cursorIndex + offset;\n\n if (direction === 'left') {\n return value.substring(cursorIndex - 1, cursorIndex) === '-';\n }\n\n return value.substring(cursorIndex, cursorIndex + 1) === '-';\n }\n\n /**\n * @private replaceAt\n * @param {string} value - The original value\n * @param {number} index - The position of the old character to replace\n * @param {string} replacement - The replacement character\n * @returns {string} - An updated value\n */\n static replaceAt(value, index, replacement) {\n return value.substring(0, index) + replacement + value.substring(index + 1);\n }\n\n /**\n * @private replaceAsYouType\n * @param {string} key - The pressed key as a string\n * @returns {string} - A possibly updated value\n * @description\n * Will replace the next character as you type. This is necessary since we have a max-length on the field.\n */\n replaceAsYouType(key) {\n let value = this.field.value;\n const isDigit = !window.isNaN(key);\n const allowedDash = key === '-' && this.checkIfDashIsSelected(value, 'right', 1);\n\n // If we're not at the end\n // and there's no selection at the moment\n // and the inputted character is either a digit or a dash\n if (this.cursorIndex < value.length && !this.hasSelection && (isDigit || allowedDash)) {\n // If we're before a dash, replace the character after the dash\n if (this.checkIfDashIsSelected(value)) {\n this.cursorIndex++;\n }\n\n value = this.constructor.replaceAt(value, this.cursorIndex, key);\n this.cursorIndex++;\n }\n\n return value;\n }\n\n /**\n * @private onKeyDown\n * @param {KeyboardEvent} evt - On key down event\n */\n onKeyDown(evt) {\n // If the user is holding the key down, and it's not the backspace/delete button, preventDefault\n if (evt.repeat && evt.key !== 'Backspace' && evt.key !== 'Delete') {\n evt.preventDefault();\n return;\n }\n\n this.hasSelection = evt.target.selectionEnd > evt.target.selectionStart;\n const isDigit = !window.isNaN(evt.key);\n\n if (isDigit || evt.key === '-') {\n evt.preventDefault();\n this.pressedCharacters.push(evt.key);\n this.onInput(evt);\n }\n }\n\n /**\n * @private onInput\n * @param {KeyboardEvent} evt - On key up event\n */\n onInput(evt) {\n if (\n evt.type === 'keyup' &&\n (evt.key === 'Escape' ||\n evt.key === 'Enter' ||\n evt.key === 'Tab' ||\n evt.key === 'Control' ||\n evt.key === 'Shift' ||\n evt.key === 'Alt' ||\n evt.key === 'Meta' ||\n evt.key === 'ArrowUp' ||\n evt.key === 'ArrowDown')\n ) {\n return;\n }\n\n const field = this.field;\n const val = field.value;\n let charRemoved = evt.type === 'keyup' && (evt.key === 'Backspace' || evt.key === 'Delete');\n this.cursorIndex = field.selectionStart;\n\n // Getting the pressed character from the array is to cater for the edge case where the user held down for example '1' and then pressed '2'.\n // This should force '1' to be shown first and then '2', instead of the other way around if we would just get evt.key.\n // This is a \"complex\" workaround for a simple problem which would much easier be fixed by using `onKeyDown` instead of `onKeyUp`, but it's\n // too late to refactor half of this file now...\n const firstPressedCharacter = this.pressedCharacters[0];\n\n // If the entire value/date has been selected\n if (evt.target.selectionStart === 0 && evt.target.selectionEnd === 10) {\n if (firstPressedCharacter) {\n // If a character has been entered, reset the value to the pressed character\n field.value = firstPressedCharacter;\n this.cursorIndex++;\n } else {\n // Stop executing the rest of this method so the user can \"select all\" and then hit backspace/delete\n return;\n }\n }\n\n // Init the mask if there is no value yet (seeing as we preventDefault in `onKeyDown`)\n // Also adjust the `empty` class accordingly\n if (val.length === 0 && firstPressedCharacter) {\n field.value = firstPressedCharacter;\n field.classList.remove('empty');\n } else if (val.length === 0) {\n field.classList.add('empty');\n }\n\n // Replace characters as you type\n let newVal = this.replaceAsYouType(firstPressedCharacter, val);\n field.value = newVal;\n\n this.pressedCharacters.shift();\n\n // Mask the input value for date using regular expressions and enforcing dashes at specific locations\n newVal = this.constructor.runRegexOnValue(newVal);\n\n // Calculate what the total length of newVal would be once the dashes are added through `splice`, only until the last entered digit\n // We need this to do calculations for cursorOffset\n const totalLength = this.constructor.totalLengthUntilLastDigit(newVal);\n\n // Will replace the removed digit with a corresponding letter from the maskText\n if (charRemoved) {\n newVal = this.replaceRemovedDigitWithLetter(newVal);\n }\n\n // If we removed any digit \"in the middle\",\n // Reset `charRemoved` to false, in order to keep the cursor in the current position\n if (charRemoved && this.cursorIndex < totalLength) {\n charRemoved = false;\n }\n\n // Add dashes at specific spots\n newVal = this.constructor.addDashes(newVal);\n\n // Set final value with a format of xx-xx-xxxx\n // If the value is incomplete, finish the rest with the mask\n if (totalLength > 0) {\n newVal = newVal.join('').substring(0, 10);\n newVal += this.maskText.substring(newVal.length, 10);\n this.field.value = newVal;\n } else {\n this.field.value = '';\n return;\n }\n\n // If arrow left was pressed\n if (evt.key === 'ArrowLeft') {\n this.onArrowLeft(newVal);\n return;\n }\n\n // If arrow right was pressed\n if (evt.key === 'ArrowRight') {\n this.onArrowRight(newVal);\n return;\n }\n\n // If a character was removed\n if (charRemoved) {\n this.onCharacterRemoval(newVal);\n return;\n }\n\n // When a character has been entered, increment the cursorIndex\n if (this.checkIfDashIsSelected(newVal)) {\n this.cursorIndex += 1;\n }\n\n // Set the new selection based on calculations done in above methods\n this.field.setSelectionRange(this.cursorIndex, this.cursorIndex);\n }\n\n /**\n * @private onPaste\n * @param {KeyboardEvent} evt - On key up event\n */\n onPaste(evt) {\n this.onInput(evt);\n\n setTimeout(() => {\n const val = this.field.value;\n this.field.setSelectionRange(val.length, val.length);\n }, 100); // small delay is necessary because the dashes are added after paste\n }\n}\n\nexport { DateMask, DATE_MASK_ATTRIBUTE };\n","'use strict';\n\nimport { POSTCODE_MASK_ATTRIBUTE, PostCodeMask } from './masks/postcode';\nimport { IBAN_MASK_ATTRIBUTE, IBANMask } from './masks/iban';\nimport { DATE_MASK_ATTRIBUTE, DateMask } from './masks/date';\nimport { CAPS_MASK_ATTRIBUTE, CapsMask } from './masks/caps';\n\n/**\n * @class Mask\n * @param {HTMLInputElement} element - The input field to put a mask on\n */\nclass Mask {\n constructor(element) {\n this.element = element;\n this.maskType = this.element.getAttribute('data-mask');\n\n // PostCode mask\n if (this.maskType === POSTCODE_MASK_ATTRIBUTE) {\n this.mask = new PostCodeMask(this.element);\n }\n if (this.maskType === IBAN_MASK_ATTRIBUTE) {\n this.mask = new IBANMask(this.element);\n }\n if (this.maskType === DATE_MASK_ATTRIBUTE) {\n this.mask = new DateMask(this.element);\n }\n if (this.maskType === CAPS_MASK_ATTRIBUTE) {\n this.mask = new CapsMask(this.element);\n }\n }\n}\n\nexport default Mask;\n","'use strict';\n\n/**\n * @private preventCharacters\n * @param {Event} event - Keydown or paste event\n */\nfunction preventCharacters(event) {\n const { target } = event;\n const bannedCharacters = target.getAttribute('data-prevent');\n\n if (event.key && bannedCharacters.includes(event.key)) {\n event.preventDefault();\n } else if (event.clipboardData) {\n event.preventDefault();\n\n const clipboardData = event.clipboardData.getData('text/plain');\n const dataWithoutBannedCharacters = clipboardData\n .split('')\n .filter((character) => !bannedCharacters.includes(character))\n .join('');\n const currValue = target.value;\n\n if (typeof target.selectionStart === 'number') {\n const start = target.selectionStart;\n const end = target.selectionEnd;\n const newVal = [];\n\n if (start === 0 && end === 0) {\n newVal.push(dataWithoutBannedCharacters);\n newVal.push(currValue);\n } else {\n newVal.push(currValue.substr(0, start));\n newVal.push(dataWithoutBannedCharacters);\n newVal.push(currValue.substr(end, currValue.length - 1));\n }\n\n target.value = newVal.join('');\n } else {\n // Some input types don't support `selectionStart`. In this edge case, just append it to the end\n target.value = currValue + dataWithoutBannedCharacters;\n }\n }\n}\n\n/**\n * @public preventCharactersOnInput\n * @param {HTMLInputElement} element - The input element\n */\nexport default function preventCharactersOnInput(element) {\n if (!element.getAttribute('data-prevent')) return;\n\n element.addEventListener('keydown', preventCharacters);\n element.addEventListener('paste', preventCharacters);\n}\n","'use strict';\n\nconst events = ['keydown', 'paste', 'focus', 'mousedown'];\n\n/**\n * Prevent entry in the field\n * @param {Event} evt - An event\n */\nfunction preventEntry(evt) {\n // ignore tab\n if (evt.keyCode !== 9) evt.preventDefault();\n}\n\n/**\n * Enable the read-only feature\n * @param {HTMLElement} element - The element to make read-only\n * @returns {bool} enabled\n */\nfunction enable(element) {\n events.forEach((event) => {\n element.addEventListener(event, preventEntry);\n });\n return true;\n}\n\n/**\n * Disable the read-only feature\n * @param {HTMLElement} element - The element to make read-only\n * @returns {bool} enabled\n */\nfunction disable(element) {\n events.forEach((event) => {\n element.removeEventListener(event, preventEntry);\n });\n return false;\n}\n\n/**\n * @public idType\n * @param {HTMLSelectElement} element - Identification type selector\n */\nexport default function idType(element) {\n if (!element.hasAttribute('read-only')) return;\n Object.defineProperty(element, 'read-only', {\n enumerable: false,\n configurable: false,\n set: (bool) => {\n if (bool) {\n this.value = enable(element);\n return;\n }\n this.value = disable(element);\n }\n });\n element['read-only'] = element.getAttribute('read-only');\n}\n","'use strict';\n\nimport documentNumber from './documentNumber';\nimport idType from './idType';\nimport mask from './mask';\nimport password from './password';\nimport preventCharacters from './preventCharacters';\nimport readonly from './readonly';\nimport regex from './regex';\nimport valid from './valid';\n\nexport default {\n documentNumber,\n idType,\n mask,\n password,\n preventCharacters,\n readonly,\n regex,\n valid\n};\n","'use strict';\n\n/**\n * @constant {string} DOCUMENT_NUMBER - Input field for document number\n */\nconst DOCUMENT_NUMBER = 'dwfrm_checkoutDetails_identification_documentNumber';\n\n/**\n * @public documentNumber\n * @param {HTMLInputElement} element - Document Number input field\n */\nexport default function documentNumber(element) {\n if (element.name !== DOCUMENT_NUMBER) return;\n\n element.closest('form').addEventListener('identificationTypeChanged', (evt) => {\n // First reset regex state due to /g entries\n // https://stackoverflow.com/questions/2630418/javascript-regex-returning-true-then-false-then-true-etc/2630538#2630538\n element.pattern = evt.detail.regex.toString().replace('/^', '^').replace('$/gi', '$');\n element.regex.lastIndex = 0;\n element.regex = new RegExp(element.pattern);\n if (element.value.length > 0) {\n element.dispatchEvent(new CustomEvent('input'));\n element.dispatchEvent(new CustomEvent('blur'));\n }\n });\n\n const originalErrorMsg = element.dataset.patternError;\n element.addEventListener('input', () => {\n // Reset to original error message\n element.dataset.patternError = originalErrorMsg;\n if (element.dataset.selectedId && element.dataset.selectedId.includes('verblijfsdocument')) {\n if (element.value.toLowerCase().startsWith('x00')) element.dataset.patternError = element.dataset.patternX00Error;\n if (element.value.toLowerCase().startsWith('v')) element.dataset.patternError = element.dataset.patternVError;\n }\n });\n}\n","'use strict';\n\nimport Mask from 'Components/form/mask';\n\n/**\n * @public regex\n * @param {HTMLInputElement} element - The element to put the mask on\n */\nexport default function mask(element) {\n Object.defineProperty(element, 'mask', {\n enumerable: false,\n configurable: false,\n value: new Mask(element)\n });\n}\n","'use strict';\n\n/**\n * @constant {string} PASSWORD_VIEW_TOGGLE - Selector for toggling the view state of a password field.\n */\nconst PASSWORD_VIEW_TOGGLE = '.js-password-toggle';\n\n/**\n * @public showPassword\n * @param {HTMLInputElement} element - The element used to set the password toggle.\n */\nexport default function showPassword(element) {\n const feedbackElement = element.parentElement.querySelector(PASSWORD_VIEW_TOGGLE);\n if (!feedbackElement) return;\n\n feedbackElement.addEventListener('click', () => {\n element.showPassword = element.type === 'password';\n });\n Object.defineProperty(element, 'showPassword', {\n enumerable: false,\n configurable: false,\n set: (value) => {\n if (value) {\n element.type = 'text';\n } else {\n element.type = 'password';\n }\n }\n });\n}\n","'use strict';\n\n/**\n * @public regex\n * @param {HTMLInputElement} element - The element used to set the regex.\n */\nexport default function regex(element) {\n Object.defineProperty(element, 'regex', {\n enumerable: false,\n configurable: true,\n writable: true,\n value: element.required ? new RegExp(element.pattern) : new RegExp() // Pattern or empty when not mandatory\n });\n}\n","'use strict';\n\n/**\n * @public validate\n * @param {HTMLInputElement} element - The element used to validate.\n */\nexport default function validate(element) {\n Object.defineProperty(element, 'valid', {\n enumerable: true,\n configurable: false,\n set: (value) => {\n if (value) {\n element.classList.add('valid');\n element.classList.remove('invalid');\n } else {\n element.classList.add('invalid');\n element.classList.remove('valid');\n }\n }\n });\n}\n","'use strict';\n\nimport { CONST } from 'Util/util';\nimport { getFieldValidationMessage } from 'Components/form/form';\n\nconst validationAttributes = ['valueMissing', 'patternMismatch', 'tooShort'];\n\n/**\n * toggleValidityClass\n * @param {boolean} [isValid] - valid or not - true or false\n * @param {HTMLElement} [target] - target element\n */\nfunction toggleValidityClass(isValid, target) {\n if (isValid) {\n target.classList.remove('invalid');\n target.classList.add('valid');\n } else {\n target.classList.add('invalid');\n target.classList.remove('valid');\n }\n}\n\n/**\n * removeValidationMessageElement\n * @param {HTMLElement} [target] - target element\n */\nfunction removeValidationMessageElement(target) {\n const element = target.parentElement.querySelector('.error-msg');\n if (element) element.remove();\n}\n\n/**\n * createValidationMessageElement\n * @param {string} [message] - validation message\n * @param {HTMLElement} [target] - target element\n */\nfunction createValidationMessageElement(message, target) {\n const element =\n target.parentElement.querySelector('.error-msg') ||\n (function createErrorElement() {\n const el = document.createElement('small');\n el.classList.add('error-msg', 'text-primary');\n return el;\n })();\n element.innerText = message;\n if (target.dataset.selectedId && target.dataset.selectedId.includes('verblijfsdocument')) element.classList.add('d-inline-flex');\n target.parentElement.insertAdjacentElement('beforeend', element);\n}\n\n/**\n * @public validateField\n * @param {HTMLFormElement} field - The form field\n * @return {boolean} valid - Whether the field is valid or not\n */\nfunction validateField(field) {\n let validField = true;\n\n validationAttributes.forEach((attribute) => {\n if (field.validity && field.validity[attribute]) {\n const errorMessage = field.getAttribute(CONST.attributes.validation[attribute]);\n validField = false;\n createValidationMessageElement(errorMessage, field);\n toggleValidityClass(false, field);\n }\n });\n\n if (validField) {\n removeValidationMessageElement(field);\n toggleValidityClass(true, field);\n }\n\n return validField;\n}\n\n/**\n * @public validateForm\n * @param {HTMLForm} form - The form\n * @return {boolean} valid - Whether the form is valid or not\n */\nfunction validateForm(form) {\n let validForm = true;\n const formFields = [...form.querySelectorAll(CONST.selectors.form.input), ...form.querySelectorAll(CONST.selectors.form.textarea)];\n const dropdowns = [...form.querySelectorAll('.js-custom-select-validation')];\n\n formFields.forEach((field) => {\n if (field.type === 'hidden') {\n return;\n }\n\n const validField = validateField(field);\n\n if (!validField) {\n validForm = false;\n }\n });\n\n dropdowns.forEach((dropdown) => {\n const validField = dropdown.checkValidity();\n\n if (!validField) {\n validForm = false;\n }\n });\n\n return validForm;\n}\n\n/**\n * @private validate\n * @param {Event} evt - blur or invalid event\n * @param {string} [msg] - validation message\n */\nfunction validate(evt, msg) {\n const message = msg || getFieldValidationMessage(evt.target);\n if (message) {\n createValidationMessageElement(message, evt.target);\n toggleValidityClass(false, evt.target);\n } else {\n removeValidationMessageElement(evt.target);\n toggleValidityClass(true, evt.target);\n }\n}\n\nexport { validateForm, validateField, validate, removeValidationMessageElement, toggleValidityClass };\n","'use strict';\n\n/**\n * @public prepareFormValues\n * @param {HTMLElement} app - The app component\n *\n * @description\n * Sets the value of an input field as a property. By doing this, a previous\n * selection can be preselected when navigating back in the product configurator.\n */\nexport function prepareFormValues(app) {\n const valueTypes = ['text', 'hidden', 'range', 'email', 'number', 'tel', 'password'];\n [...app.querySelectorAll('input')].forEach((field) => {\n if (valueTypes.indexOf(field.type) !== -1) {\n field.setAttribute('value', field.value);\n } else if (field.type === 'radio' || field.type === 'checkbox') {\n if (field.checked) {\n field.setAttribute('checked', true);\n } else {\n field.removeAttribute('checked');\n }\n }\n });\n}\n\n/**\n * @public getFieldValidationMessage\n * @param {HTMLInputElement | HTMLSelectElement} field - Invalid field element\n * @returns {string | false} - Error message for invalid field\n */\nexport function getFieldValidationMessage(field) {\n // Valid\n if (field.validity.valid) return false;\n\n // Required\n if (field.required && field.value.length === 0) return field.getAttribute('data-missing-error');\n\n // Checked\n if (!field.checked && (field.matches('[type=\"checkbox\"]') || field.matches('[type=\"radio\"]'))) return field.getAttribute('data-missing-error');\n\n // Regex\n if (field.pattern && !new RegExp(field.pattern).test(field.value)) return field.getAttribute('data-pattern-error');\n\n // Dates\n if (field.dataset.mask === 'date' && field.dataset.invalid === 'true') return field.getAttribute('data-invalid-error');\n if (field.dataset.mask === 'date' && field.dataset.invalidMin === 'true') return field.getAttribute('data-mindate-error');\n if (field.dataset.mask === 'date' && field.dataset.invalidMax === 'true') return field.getAttribute('data-maxdate-error');\n if (field.dataset.mask === 'addition' && field.dataset.multipleAdditions === 'true') return field.getAttribute('data-missing-error');\n\n // No valid error messages\n return false;\n}\n","'use strict';\n\nimport decorators from 'Decorators/index';\nimport { validate } from 'app_vodafone_ziggo/util/validation';\n\n/**\n * @class InputField\n * @param {HTMLInputElement} element - The element to create an instance on\n */\nclass VZInputField extends HTMLInputElement {\n constructor() {\n super();\n this.validatePattern = this.validatePattern.bind(this);\n this.setFieldStatus = this.setFieldStatus.bind(this);\n this.onPaste = this.onPaste.bind(this);\n\n this.addEventListener('input', this.validatePattern);\n this.addEventListener('input', this.setFieldStatus);\n this.addEventListener('changeDate', this.setFieldStatus);\n this.addEventListener('changeDate', validate);\n this.addEventListener('paste', this.onPaste);\n this.validate = validate;\n\n decorators.readonly(this);\n decorators.regex(this);\n decorators.valid(this);\n decorators.documentNumber(this);\n\n if (this.hasAttribute('data-mask')) {\n decorators.mask(this);\n }\n\n if (this.hasAttribute('data-prevent')) {\n decorators.preventCharacters(this);\n }\n\n if (this.type === 'password') {\n decorators.password(this);\n }\n\n // Set initial state\n this.setFieldStatus();\n\n if (this.type === 'radio' || this.type === 'checkbox') {\n this.addEventListener('change', validate);\n } else {\n this.addEventListener('blur', validate);\n }\n\n this.closest('form').addEventListener('submit', this.disableExcludedFields);\n }\n\n onPaste(evt) {\n // Execute these methods at the end of the callstack, otherwise `field.value` will be the value before the paste.\n setTimeout(() => {\n this.setFieldStatus();\n validate(evt);\n }, 1);\n }\n\n disableExcludedFields() {\n if (this.hasAttribute('data-exclude')) {\n this.setAttribute('disabled', 'disabled');\n }\n }\n\n /**\n * @private setFieldStatus\n * @description\n * Sets an empty class when the element is empty for styling purposes.\n */\n setFieldStatus() {\n const hasValue = this.value.length > 0;\n const placeholderIsShown = this.constructor.placeholderActive(this);\n if (hasValue) {\n this.classList.remove('empty');\n } else if (placeholderIsShown) {\n // input[type=\"number\"] accepts dash and dots but returns no value for that.\n this.classList.add('empty');\n }\n }\n\n /**\n * @private validatePattern\n * @description\n * Checks whether the value is valid based on pattern\n */\n validatePattern() {\n this.valid = this.regex.test(this.value);\n }\n\n /**\n * @function placeholderActive\n *\n * @param {HTMLInputElement} element - Input element\n * @return {boolean} whether the placeholder is shown or not\n */\n static placeholderActive(element) {\n const selector = `${element.nodeName.toLowerCase()}[name=\"${element.name}\"]:placeholder-shown`;\n return !!document.querySelector(selector);\n }\n}\n\nexport default window.customElements.get('vz-input') || VZInputField;\nif (!window.customElements.get('vz-input')) {\n window.customElements.define('vz-input', VZInputField, { extends: 'input' });\n}\n","'use strict';\n\nimport 'Components/form/VZInputField';\nimport VZSpinner from 'Components/VZSpinner';\nimport { validateForm } from 'app_vodafone_ziggo/util/validation';\n\nexport class VZProductMailModal {\n constructor() {\n this.emailElement = document.getElementById('dwfrm_shareConfiguration_email');\n this.sendEmailForm = this.emailElement.closest('form');\n\n // Grabbing the form using this attribute so its dynamic\n this.productForm = document.querySelector('[data-share-configuration]');\n\n this.onSubmit = this.onSubmit.bind(this);\n this.setCSRFToken = this.setCSRFToken.bind(this);\n this.sendEmail = this.sendEmail.bind(this);\n this.sendEmailForm.addEventListener('submit', this.onSubmit);\n }\n\n static addBodyToPostRequest(form, options, method) {\n if (method.toLowerCase() === 'post') {\n options.body = new FormData(form);\n }\n }\n\n onSubmit(evt) {\n evt.preventDefault();\n\n const spinner = document.querySelector('vz-spinner') || new VZSpinner();\n spinner.start();\n\n if (validateForm(this.sendEmailForm)) {\n this.setCSRFToken();\n\n // Submit Group\n const options = {\n method: this.productForm.method\n };\n\n // Add body conditionally depending on type of request\n this.constructor.addBodyToPostRequest(this.productForm, options, options.method);\n\n fetch(this.productForm.action, options).then(() => {\n this.emailAddress = this.emailElement.value;\n this.sendEmail();\n spinner.stop();\n });\n } else {\n spinner.stop();\n }\n }\n\n sendEmail() {\n const options = {\n method: this.sendEmailForm.method\n };\n\n // Add body conditionally depending on type of request\n this.constructor.addBodyToPostRequest(this.sendEmailForm, options, options.method);\n\n // Grab elements to replace text content\n const modalTitle = this.sendEmailForm.querySelector('.js-mail-modal-title');\n const modalBody = this.sendEmailForm.querySelector('.js-mail-modal-body');\n const modalFooter = this.sendEmailForm.querySelector('.js-mail-modal-footer');\n const modalCloseButton = this.sendEmailForm.querySelector('.js-mail-modal-close');\n const modalConfirmTitleText = modalTitle.dataset.confirmationTitle;\n const modalConfirmHeadingText = modalBody.dataset.confirmationHeading;\n let modalConfirmBodyText = modalBody.dataset.confirmationBody;\n const { confirmButtonCloseText } = modalFooter.dataset;\n\n if (this.emailAddress && modalConfirmBodyText.indexOf('{0}') >= 0) {\n modalConfirmBodyText = modalConfirmBodyText.replace('{0}', this.emailAddress);\n }\n\n const modalConfirmBody = `\n

${modalConfirmHeadingText}

\n

${modalConfirmBodyText}

\n `;\n\n const modalConfirmButtons = `\n \n `;\n\n fetch(this.sendEmailForm.action, options)\n .then((resp) => resp.json())\n .then((resp) => {\n this.setCSRFToken(resp.csrf_token);\n // Replace text\n modalCloseButton.remove();\n modalFooter.classList.remove('justify-content-start');\n modalFooter.classList.add('justify-content-between');\n modalTitle.textContent = modalConfirmTitleText;\n modalBody.innerHTML = modalConfirmBody;\n modalFooter.innerHTML = modalConfirmButtons;\n });\n }\n\n setCSRFToken(csrfToken) {\n if (window.csrf) {\n this.sendEmailForm.insertAdjacentHTML(\n 'beforeend',\n `\n \n `\n );\n }\n }\n}\n","'use strict';\n\nimport 'Root/product/components/VZDeleteGroup';\nimport 'Components/prompt';\nimport { documentReady } from 'app_vodafone_ziggo/util/util';\nimport initCollapsibleSpecs from 'Components/collapsibleSpecs';\n\nimport { VZProductMailModal } from 'Root/product/components/VZProductMailModal';\n\n/**\n * @private onDocumentReady\n */\nfunction onDocumentReady() {\n const basketNotEmpty = document.getElementById('basket-not-empty')?.value;\n if (basketNotEmpty === 'true') {\n new VZProductMailModal(); // eslint-disable-line\n }\n}\n\ndocumentReady(onDocumentReady);\ndocumentReady(initCollapsibleSpecs);\n","import { isMobile } from 'Util/util';\n\n/**\n * Initializes collapsible specifications.\n *\n * @param {HTMLElement} [wrapper] - The wrapper element containing collapsible specs controls.\n * @private\n */\nexport default function initCollapsibleSpecs(wrapper) {\n const collapseControls = wrapper ? [...wrapper.querySelectorAll('.js-collapsible-specs-control')] : [...document.querySelectorAll('.js-collapsible-specs-control')];\n\n collapseControls.forEach((control) => {\n const toggleState = () => {\n // Toggle aria-expanded attribute\n const isExpanded = control.getAttribute('aria-expanded') === 'true';\n control.setAttribute('aria-expanded', (!isExpanded).toString());\n\n control.classList.toggle('collapsible-specs-control-closed');\n // If the class js-collapsible-specs-independent present each control toggles one item\n // In opposite on the cart page one controll toggles all the product items\n if (control.classList.contains('js-collapsible-specs-independent')) {\n control.closest('.js-collapsible-specs')?.classList.toggle('collapsible-specs-collapsed');\n } else {\n const specs = [...(control.closest('.card')?.querySelectorAll('.js-collapsible-specs') || [])];\n specs.forEach((item) => {\n item.classList.toggle('collapsible-specs-collapsed');\n });\n }\n };\n const tapArea = control.closest('.js-collapsible-specs')?.querySelector('.js-collapsible-specs-tap-area');\n if (tapArea) {\n tapArea.addEventListener('click', toggleState);\n } else {\n control.addEventListener('click', toggleState);\n }\n // Collapse open item on mobile if indicated by the class\n if (isMobile() && control.classList.contains('js-collapsible-specs-collapse-mobile') && control.getAttribute('aria-expanded') === 'true') {\n toggleState();\n }\n });\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","__webpack_require__.amdO = {};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","__webpack_require__.j = 301;","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t301: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkvodafoneziggo\"] = globalThis[\"webpackChunkvodafoneziggo\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [395,661,139], () => (__webpack_require__(9397)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","redSpinnerData","require","VZSpinner","HTMLElement","constructor","parentEl","super","this","showing","stop","bind","veil","parentElement","document","body","tagName","appendChild","lottie","Lottie","container","querySelector","renderer","loop","autoplay","animationData","start","msg","Promise","resolve","window","getComputedStyle","getPropertyValue","style","position","classList","add","insertAdjacentHTML","setTimeout","play","contains","remove","content","connectedCallback","innerHTML","addEventListener","evt","stopPropagation","customElements","get","define","splitUpUrl","url","includes","hash","paramUrl","split","at","domain","params","appendParamToURL","name","value","newURL","urlValues","newParams","filter","param","join","removeParamFromURL","separator","encodeURIComponent","setCookie","cookieName","cookieValue","expirationDays","date","Date","setTime","getTime","cookieString","toUTCString","cookie","getJourney","parts","length","pop","shift","getCookie","item","VZDeleteGroup","onClick","deleteBtn","disconnectedCallback","removeEventListener","removeDeletedGroup","isMiniCart","closest","location","href","spinner","preventDefault","removeFromJourneyEmptyProduct","getAttribute","removeFromJourneyExistingProduct","journey","every","id","hostname","urls","internet","updateJourney","reload","fetch","method","then","finally","computedStyles","documentElement","bscanSteps","INTRO","STATEMENTS_DONE","GROUPED_QUESTIONS","ADVICE","THANKYOU","attributes","action","class","checked","csrfToken","csrfName","disabled","exclude","pattern","placeholder","required","readonly","selected","target","validation","patternMismatch","valueMissing","tooShort","breakpoints","xxs","parseInt","xs","sm","md","lg","xl","xxl","classes","active","buttons","next","previous","warning","dBlock","dFlex","dInlineBlock","dNone","empty","inactive","invalid","hidden","last","show","valid","events","blur","change","click","input","keyUp","load","mousedown","mouseleave","mouseover","paste","popstate","resize","responseError","scroll","submit","transitionEnd","update","selectors","form","checkbox","file","inputFieldClear","inputFieldFeedback","label","radio","select","textarea","html","htmlBody","img","interactiveElements","localStorage","preferredLayoutId","vzLayoutToggle","enabledBreakpoint","idDefault","localStorageKey","addEvent","parent","passedEvent","selector","handler","event","matches","apply","arguments","documentReady","fn","readyState","promptOpen","CONST","prompt","promptClose","confirm","button","setAttribute","ID_TYPES_CODES","ID_VALIDATION_RULES","ID_TYPE","setValidationPattern","element","getElementById","dispatchEvent","CustomEvent","detail","type","regex","CapsMask","onInput","selectionStart","toUpperCase","setSelectionRange","UNDO_KEYS","PostCodeMask","onKeyUp","key","toLocaleLowerCase","some","k","substring","replace","IBANMask","DateMask","field","cursorIndex","maskText","pressedCharacters","onPaste","replaceRemovedDigitWithLetter","onArrowRight","onArrowLeft","onCharacterRemoval","checkIfDashIsSelected","replaceAsYouType","onKeyDown","runRegexOnValue","totalLengthUntilLastDigit","newVal","totalLength","cursorOffset","removedCharacter","splice","addDashes","direction","offset","replaceAt","index","replacement","isDigit","isNaN","allowedDash","hasSelection","repeat","selectionEnd","push","val","charRemoved","firstPressedCharacter","maskType","mask","preventCharacters","bannedCharacters","clipboardData","dataWithoutBannedCharacters","getData","character","currValue","end","substr","preventEntry","keyCode","documentNumber","toString","lastIndex","RegExp","originalErrorMsg","dataset","patternError","selectedId","toLowerCase","startsWith","patternX00Error","patternVError","idType","Object","defineProperty","enumerable","configurable","Mask","password","feedbackElement","showPassword","set","hasAttribute","bool","forEach","enable","disable","writable","validationAttributes","toggleValidityClass","isValid","removeValidationMessageElement","createValidationMessageElement","message","el","createElement","innerText","insertAdjacentElement","validateForm","validForm","formFields","querySelectorAll","dropdowns","validField","attribute","validity","errorMessage","validateField","dropdown","checkValidity","validate","test","invalidMin","invalidMax","multipleAdditions","VZInputField","HTMLInputElement","validatePattern","setFieldStatus","decorators","disableExcludedFields","hasValue","placeholderIsShown","placeholderActive","nodeName","extends","VZProductMailModal","emailElement","sendEmailForm","productForm","onSubmit","setCSRFToken","sendEmail","addBodyToPostRequest","options","FormData","emailAddress","modalTitle","modalBody","modalFooter","modalCloseButton","modalConfirmTitleText","confirmationTitle","modalConfirmHeadingText","confirmationHeading","modalConfirmBodyText","confirmationBody","confirmButtonCloseText","indexOf","modalConfirmBody","modalConfirmButtons","resp","json","csrf_token","textContent","csrf","tokenName","token","basketNotEmpty","wrapper","control","toggleState","isExpanded","toggle","tapArea","navigator","userAgent","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","call","m","amdO","O","result","chunkIds","priority","notFulfilled","Infinity","i","fulfilled","j","keys","r","n","getter","__esModule","d","a","definition","o","g","globalThis","Function","e","obj","prop","prototype","hasOwnProperty","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","data","moreModules","runtime","chunkLoadingGlobal","__webpack_exports__"],"sourceRoot":""}