{"version":3,"sources":["model/gallery.ts","reducer/gallerySlice.ts","reducer/galleriesApi.ts","reducer/store.ts","hooks/usePopMessages.ts","components/layout/logo.tsx","reducer/hooks.ts","components/menu/subMenuItem.tsx","components/menu/menuItem.tsx","components/menu/nav.tsx","hooks/useMediaQuery.ts","hooks/useStorage.ts","hooks/useDarkMode.ts","context/darkModeContext.tsx","components/layout/darkModeToggle.tsx","components/layout/header.tsx","components/layout/footer.tsx","components/gallery/entry.tsx","hooks/useScrollTop.ts","hooks/useAsync.ts","hooks/useScrollFinish.ts","components/gallery/collection.tsx","components/gallery/gallery.tsx","components/layout/main.tsx","components/progress.tsx","components/layout/loader.tsx","components/gallery/modalNav.tsx","hooks/useOnlineStatus.ts","components/layout/popMessage.tsx","components/layout/popMessages.tsx","context/popMessageContext.tsx","components/gallery/modalImage.tsx","components/gallery/modal.tsx","hooks/useOfflinePopMessage.ts","hooks/useDeviceType.ts","App.tsx","serviceWorkerRegistration.ts","index.tsx"],"names":["getCollectionId","gallery","collection","type","collections","initialState","autoScrolling","activeCollection","openedGallery","openedCollection","openedEntry","collapsed","isDesktop","window","innerWidth","menuToggled","appSlice","createSlice","name","reducers","activateMenu","state","action","payload","scrollFinished","selectMenu","res","openEntry","entry","nextEntry","idx","entries","map","e","thumbnailPath","indexOf","length","previousEntry","closeEntry","setCollapsed","toggleMenu","undefined","setTotalCount","loadProgress","total","loaded","incrementLoadedCount","actions","selectActiveCollection","app","selectAutoScrolling","selectOpenedEntry","selectCollapsed","selectMenuToggled","selectLoadProgress","galleriesApi","createApi","reducerPath","baseQuery","fetchBaseQuery","baseUrl","process","endpoints","build","getGalleries","query","useGetGalleriesQuery","store","configureStore","reducer","appReducer","middleware","getDefaultMiddleware","concat","setupListeners","dispatch","ActionType","Logo","xmlns","className","viewBox","width","height","points","d","useAppDispatch","useDispatch","useAppSelector","useSelector","SubMenuItem","menuHandlerProvider","ref","useRef","onClick","onMouseDown","preventDefault","classes","getClasses","label","MenuItem","handleMenuItem","result","c","includes","galleryClass","Navigation","galleries","g","useMediaQuery","useState","match","setMatch","useEffect","queryList","matchMedia","handler","matches","addEventListener","passive","addListener","removeEventListener","removeListener","useStorage","key","defaultValue","storage","jsonValue","getItem","JSON","parse","Function","value","setValue","removeItem","setItem","stringify","remove","useCallback","useLocalStorage","localStorage","useDarkMode","darkMode","setDarkMode","prefersDarkMode","enabled","document","body","classList","toggle","defaultState","DarkModeContext","React","createContext","DarkModeProvider","children","Provider","DarkModeToggle","useContext","title","Header","isNarrow","headerClasses","setHeaderClasses","backdropClasses","setBackdropClasses","doubleTap","useDoubleTap","event","scrollTo","top","behavior","doubleTapProps","useMemo","toggleMenuHandler","add","href","Footer","GalleryEntryContainer","available","setAvailable","path","target","rel","src","alt","onLoad","onError","console","error","note","noteBadge","useScrollTop","scrollTop","setScrollTop","update","scrollY","useAsync","promise","deps","loading","setLoading","setError","callbackMemoized","then","catch","finally","defaultOptions","unchangedFrames","listenOnStart","useScrollFinish","callback","options","listen","setListen","memCallback","Promise","resolve","lastChangedFrame","lastX","scrollX","lastY","tick","frames","requestAnimationFrame","bind","CollectionContainer","current","offsetTop","offsetHeight","id","i","GalleryContainer","Main","Progress","size","animationLength","getStyle","style","Loader","render","setRender","setClasses","useLayoutEffect","setTimeout","ModalNavButton","icon","position","useOnlineStatus","navigator","onLine","online","setOnline","goOnline","goOffline","messages","popMessageReducer","ADD","DISMISS","index","findIndex","m","dismissed","usePopMessages","useReducer","popMessage","message","dismissMessage","PopMessage","dismiss","usePopMessageContext","timeout","styles","setStyles","timeoutId","setTimeoutId","timeoutCallback","clearTimeout","handleDismiss","swipeHandlers","useSwipeable","onSwipedRight","dismissible","renderActionButton","button","text","renderDismissButton","severity","PopMessages","filter","PopMessageContext","PopMessageProvider","pop","Date","now","Math","random","timestamp","context","Error","usePop","ModalImage","handleNext","handlePrevious","handleClose","toggled","setToggled","setLoaded","imgRef","onlineStatus","complete","img","aspectRatio","naturalWidth","naturalHeight","justifyContent","toggledPath","display","noteTitle","desc","logo","Modal","modalClasses","setModalClasses","useKeyboard","listeners","shouldListen","preventDefaultTouchmoveEvent","onSwiped","eventData","dir","onSwiping","useOfflinePopMessage","wasOffline","setWasOffline","useDeviceType","useMobileOrientation","isPortrait","isLandscape","orientation","isTablet","isMobile","App","data","isLoading","flatMap","isLocalhost","Boolean","location","hostname","registerValidSW","swUrl","config","serviceWorker","register","registration","onupdatefound","installingWorker","installing","onstatechange","controller","waiting","postMessage","onUpdate","log","onSuccess","smoothscroll","polyfill","ReactDOM","StrictMode","getElementById","URL","origin","fetch","headers","response","contentType","get","status","ready","unregister","reload","checkValidServiceWorker","serviceWorkerRegistration"],"mappings":"yhBA8BaA,EAAkB,SAACC,EAAkBC,GAA6B,IAAD,EAC1E,MAAM,GAAN,OAAUD,EAAQE,KAAlB,6BAA0BD,QAA1B,IAA0BA,OAA1B,EAA0BA,EAAYC,YAAtC,QAA8CF,EAAQG,YAAY,GAAGD,O,OCfnEE,EAAyB,CAC3BC,eAAe,EACfC,iBAAkB,KAClBC,cAAe,KACfC,iBAAkB,KAClBC,YAAa,KACbC,WAAYC,aAAaC,OAAOC,WAAa,KAC7CC,aAAa,GAcJC,EAAWC,sBAAY,CAChCC,KAAM,UACNb,eACAc,SAAU,CACNC,aAAc,SAACC,EAAOC,GAClB,GAAID,EAAMf,cACN,OAAOe,EAEX,IAAMnB,EAAaoB,EAAOC,QAAQrB,WAC5BF,EAAgBsB,EAAOC,QAAQtB,QAASqB,EAAOC,QAAQrB,YACvDF,EAAgBsB,EAAOC,QAAQtB,SACrC,OAAIoB,EAAMd,mBAAqBL,EACpB,2BAAImB,GAAX,IAAkBd,iBAAkBL,SADxC,GAIJsB,eAAgB,SAACH,GACb,OAAO,2BAAIA,GAAX,IAAkBf,eAAe,KAErCmB,WAAY,SAACJ,EAAOC,GAChB,IAAII,EAAG,2BAAOL,GAAP,IAAcf,eAAe,IAC9BJ,EAAaoB,EAAOC,QAAQrB,WAC5BF,EAAgBsB,EAAOC,QAAQtB,QAASqB,EAAOC,QAAQrB,YACvDF,EAAgBsB,EAAOC,QAAQtB,SAIrC,OAHIoB,EAAMd,mBAAqBL,IAC3BwB,EAAG,2BAAOA,GAAP,IAAYnB,iBAAkBL,KAE9BwB,GAEXC,UAAW,SAACN,EAAOC,GACf,OAAO,2BACAD,GADP,IAEIb,cAAec,EAAOC,QAAQtB,QAC9BS,YAAaY,EAAOC,QAAQK,MAC5BnB,iBAAkBa,EAAOC,QAAQrB,cAGzC2B,UAAW,SAACR,GACR,IAAKA,EAAMZ,mBAAqBY,EAAMX,YAAa,OAAOW,EAC1D,IACIO,EADEE,EAAMT,EAAMZ,iBAAiBsB,QAAQC,KAAI,SAACC,GAAD,OAAqBA,EAAEC,iBAAeC,QAAQd,EAAMX,YAAYwB,eAO/G,OAJIN,EADAE,IAAQT,EAAMZ,iBAAiBsB,QAAQK,OAAS,EACxCf,EAAMZ,iBAAiBsB,QAAQ,GAE/BV,EAAMZ,iBAAiBsB,QAAQD,EAAM,GAE1C,2BACAT,GADP,IAEIX,YAAakB,KAGrBS,cAAe,SAAChB,GACZ,IAAKA,EAAMZ,mBAAqBY,EAAMX,YAAa,OAAOW,EAC1D,IACIO,EADEE,EAAcT,EAAMZ,iBAAiBsB,QAAQC,KAAI,SAACC,GAAD,OAAqBA,EAAEC,iBAAeC,QAAQd,EAAMX,YAAYwB,eAOvH,OAJIN,EADQ,IAARE,EACQT,EAAMZ,iBAAiBsB,QAAQV,EAAMZ,iBAAiBsB,QAAQK,OAAS,GAEvEf,EAAMZ,iBAAiBsB,QAAQD,EAAM,GAE1C,2BACAT,GADP,IAEIX,YAAakB,KAGrBU,WAAY,SAAAjB,GACR,OAAO,2BAAIA,GAAX,IAAkBX,YAAa,KAAMF,cAAe,KAAMC,iBAAkB,QAEhF8B,aAAc,SAAClB,EAAOC,GAClB,OAAO,2BAAID,GAAX,IAAkBV,UAAWW,EAAOC,WAExCiB,WAAY,SAACnB,EAAOC,GAChB,OAAO,2BAAID,GAAX,IAAkBN,iBAAgC0B,IAAnBnB,EAAOC,SAAyBF,EAAMN,YAAcO,EAAOC,WAE9FmB,cAAe,SAACrB,EAAOC,GACnB,OAAO,2BAAID,GAAX,IAAkBsB,aAAc,CAACC,MAAOtB,EAAOC,QAASsB,OAAQ,MAEpEC,qBAAsB,SAAAzB,GAClB,GAAKA,EAAMsB,aACX,OAAO,2BAAItB,GAAX,IAAkBsB,aAAa,2BAAKtB,EAAMsB,cAAZ,IAA0BE,OAAQxB,EAAMsB,aAAaE,OAAO,UAK/F,EAYH7B,EAAS+B,QAXT3B,EADG,EACHA,aACAK,EAFG,EAEHA,WACAD,EAHG,EAGHA,eACAG,EAJG,EAIHA,UACAE,EALG,EAKHA,UACAQ,EANG,EAMHA,cACAC,EAPG,EAOHA,WACAC,EARG,EAQHA,aACAC,EATG,EASHA,WACAE,EAVG,EAUHA,cACAI,EAXG,EAWHA,qBAGSE,EAAyB,SAAC3B,GAAD,OAAsBA,EAAM4B,IAAI1C,kBACzD2C,EAAsB,SAAC7B,GAAD,OAAsBA,EAAM4B,IAAI3C,eACtD6C,EAAoB,SAAC9B,GAAD,OAAsBA,EAAM4B,IAAIvC,aACpD0C,EAAkB,SAAC/B,GAAD,OAAsBA,EAAM4B,IAAItC,WAClD0C,EAAoB,SAAChC,GAAD,OAAsBA,EAAM4B,IAAIlC,aACpDuC,EAAqB,SAACjC,GAAD,OAAsBA,EAAM4B,IAAIN,cAEnD3B,IAAf,Q,QCzIauC,EAAeC,oBAAU,CAClCC,YAAa,eACbC,UAAWC,yBAAe,CACtBC,QAAQ,GAAD,OAAKC,GAAL,UAEXC,UAAW,SAACC,GAAD,MAAY,CACnBC,aAAcD,EAAME,MAA6B,CAC7CA,MAAO,iBAAM,mBAKlBC,EAAwBX,EAAxBW,qB,QCXDC,EAAQC,yBAAe,CACzBC,SAAO,mBACFd,EAAaE,YAAcF,EAAac,SADtC,oBAEEC,GAFF,GAIPC,WAAY,SAAAC,GAAoB,OAAIA,IAAuBC,OAAOlB,EAAagB,eAGnFG,yBAAeP,EAAMQ,UAENR,ICPVS,EDOUT,I,mCEcAU,EA1BQ,WACnB,OACI,sBAAKC,MAAM,6BAA6BC,UAAU,OAAOC,QAAQ,cAAjE,UACI,sBAAMD,UAAU,eAAeE,MAAM,MAAMC,OAAO,QAClD,yBAASH,UAAU,iBACVI,OAAO,qHAChB,sBAAMJ,UAAU,iBACVK,EAAE,4JACR,yBAASL,UAAU,iBACVI,OAAO,6EAChB,yBAASJ,UAAU,iBACVI,OAAO,6EAChB,sBAAMJ,UAAU,iBACVK,EAAE,qKACR,sBAAML,UAAU,iBACVK,EAAE,yQACR,sBAAML,UAAU,iBACVK,EAAE,yQACR,sBAAML,UAAU,iBACVK,EAAE,8MACR,sBAAML,UAAU,iBACVK,EAAE,gZCrBPC,EAAiB,kBAAMC,yBACvBC,EAAkDC,cC4BhDC,EArBiC,SAAC,GAAkE,IAAjExF,EAAgE,EAAhEA,QAASC,EAAuD,EAAvDA,WAAYK,EAA2C,EAA3CA,iBAAkBmF,EAAyB,EAAzBA,oBAE/EC,EAAMC,iBAA0B,MActC,OACI,wBAAQD,IAAKA,EAAKE,QAJXH,EAAoB,CAACzF,UAASC,eAIK4F,YAAa,SAAC7D,GAAMA,EAAE8D,kBAAoBhB,UAbrE,WACf,IAAIiB,EAIJ,OAHIhG,EAAgBC,EAASC,KAAgBK,IACzCyF,EAAU,UAEPA,EAQwFC,GAA/F,SAA8G/F,EAAWgG,SCoBlHC,EAnC2B,SAAC,GAAiC,IAAhClG,EAA+B,EAA/BA,QAASM,EAAsB,EAAtBA,iBAC3CoE,EAAWU,IAUXe,EAAsC,SAAC7E,GAAD,OAA8B,SAACU,GACvEA,EAAE8D,iBACFpB,EAASlD,EAAWF,IAChBA,EAAQrB,YACRyE,EAASnC,GAAW,MAK5B,OACI,sBAAKuC,UAlBY,SAAC9E,GAClB,IAAIoG,EAAS,SAIb,OAHwB,MAApB9F,GAA4BN,EAAQG,YAAY4B,KAAI,SAACsE,GAAD,OAAmBtG,EAAgBC,EAASqG,MAAIC,SAAShG,KAC7G8F,EAAM,UAAMA,EAAN,YAEHA,EAaSG,CAAavG,GAA7B,UACI,wBAAQ4F,QAASO,EAAe,CAACnG,YAAW6F,YAAa,SAAC7D,GAAKA,EAAE8D,kBAAmBhB,UAAW,YAA/F,SAA6G9E,EAAQiG,QACrH,qBAAKnB,UAAW,iBAAhB,SACK9E,EAAQG,aAAeH,EAAQG,YAAY4B,KAAI,SAACsE,GAAD,OAAmB,cAAC,EAAD,CACarG,QAASA,EACTC,WAAYoG,EACZ/F,iBAAkBA,EAClBmF,oBAAqBU,GAJhBE,EAAEnG,aAHnDF,EAAQE,OCb7CsG,EAb+B,SAAC,GAAiB,IAAhBC,EAAe,EAAfA,UAEtCnG,EAAmBgF,EAAevC,GAExC,OACI,8BACI,qBAAK+B,UAAU,SAAf,SACK2B,GAAaA,EAAU1E,KAAI,SAAC2E,GAAD,OAAc,cAAC,EAAD,CAAuB1G,QAAS0G,EAAGpG,iBAAkBA,GAAtCoG,EAAExG,c,QCa5DyG,G,MA1BO,SAAC3C,GACnB,MAA0B4C,oBAAkB,GAA5C,mBAAOC,EAAP,KAAcC,EAAd,KAsBA,OApBAC,qBAAU,WACN,IAAMC,EAAYpG,OAAOqG,WAAWjD,GAC9BkD,EAAU,kBAAMJ,EAASE,EAAUG,UAEzC,IACIH,EAAUI,iBAAiB,SAAUF,EAAS,CAACG,SAAS,IAC1D,MAAOrF,GACLgF,EAAUM,YAAYJ,GAI1B,OADAA,IACO,WACH,IACIF,EAAUO,oBAAoB,SAAUL,GAC1C,MAAOlF,GACLgF,EAAUQ,eAAeN,OAGlC,CAAClD,IAEG6C,ICHLY,EAAa,YAA2E,IAAtEC,EAAqE,EAArEA,IAAKC,EAAgE,EAAhEA,aAAcC,EAAkD,EAAlDA,QACvC,EAA0BhB,oBAAwB,WAC9C,IAAMiB,EAAYD,EAAQE,QAAQJ,GAClC,OAAiB,MAAbG,EAA0BE,KAAKC,MAAMH,GAErCF,aAAwBM,SAAiBN,IACtCA,KALX,mBAAOO,EAAP,KAAcC,EAAd,KAQApB,qBAAU,WACN,QAAcvE,IAAV0F,EAAqB,OAAON,EAAQQ,WAAWV,GACnDE,EAAQS,QAAQX,EAAKK,KAAKO,UAAUJ,MACrC,CAACR,EAAKQ,EAAON,IAEhB,IAAMW,EAASC,uBAAY,WACvBL,OAAS3F,KACV,IAEH,MAAO,CAAC0F,EAAOC,EAAUI,IAGdE,EAzCgB,SAAIf,EAAaC,GAC5C,OAAOF,EAAW,CAACC,MAAKC,eAAcC,QAAShH,OAAO8H,gBCmB3CC,GAZK,WAChB,MAAgCF,EAAyB,eAAzD,mBAAOG,EAAP,KAAiBC,EAAjB,KACMC,EAAkBnC,EAAc,gCAChCoC,EAAO,OAAGH,QAAH,IAAGA,IAAYE,EAM5B,OAJA/B,qBAAU,WACNiC,SAASC,KAAKC,UAAUC,OAAO,YAAaJ,KAC7C,CAACA,IAEG,CAACA,EAASF,ICXfO,GAAqC,CACvCR,UAAU,GAGRS,GAAkBC,IAAMC,cAAoCH,IAEnDC,MAEFG,GAA6B,SAAC,GAAgB,IAAfC,EAAc,EAAdA,SACxC,EAAgCd,KAAhC,mBAAOC,EAAP,KAAiBC,EAAjB,KAEA,OACI,cAACQ,GAAgBK,SAAjB,CAA0BxB,MAAO,CAACU,WAAUC,eAA5C,SACKY,KCIEE,GAnBkB,WAC7B,MAAgCC,qBAAWP,IAApCT,EAAP,EAAOA,SAAUC,EAAjB,EAAiBA,YAMjB,OACI,yBAAQ/D,UAAW,mBACX+E,MAAOjB,EAAW,oBAAgB,qBAClChD,QAPG,WACA,OAAXiD,QAAW,IAAXA,MAAeD,IAOP/C,YAAa,SAAC7D,GAAKA,EAAE8D,kBAH7B,UAII,mBAAGhB,UAAS,mBAAc8D,EAAW,UAAU,MAC/C,mBAAG9D,UAAS,oBAAgB8D,EAAqB,GAAV,iBCsEpCkB,GA3EuB,SAAC,GAAiB,IAAhBrD,EAAe,EAAfA,UAG9B/F,EAAY4E,EAAenC,GAC3BrC,EAAcwE,EAAelC,GAC7BsB,EAAWU,IACX2E,EAAWpD,EAAc,uBAE/B,EAA0CC,qBAA1C,mBAAOoD,EAAP,KAAsBC,EAAtB,KACA,EAA8CrD,qBAA9C,mBAAOsD,EAAP,KAAwBC,EAAxB,KACMC,EAAYC,wBAAa,SAACC,GAC5BA,EAAMxE,iBACNlF,OAAO2J,SAAS,CAACC,IAAK,EAAGC,SAAU,cAEjCC,EAAiBC,mBAAQ,WAC3B,OAAIjK,IAAcI,EACPsJ,EAEJ,KACR,CAAC1J,EAAWI,EAAasJ,IAEtBQ,EAAoB,SAAC5I,GACnBtB,IACAsB,EAAE8D,iBACFpB,EAASnC,OAiCjB,OA7BAwE,qBAAU,WACFjG,EACAkI,SAASC,KAAKC,UAAU2B,IAAI,aAE5B7B,SAASC,KAAKC,UAAUX,OAAO,eAEpC,CAACzH,IAEJiG,qBAAU,WACNrC,EAASpC,GAAc3B,aAAaoJ,KAC/BpJ,aAAaoJ,EACdf,SAASC,KAAKC,UAAU2B,IAAI,cAE5B7B,SAASC,KAAKC,UAAUX,OAAO,aAC/B7D,EAASnC,GAAW,OAEzB,CAACmC,EAAUqF,IAEdhD,qBAAU,WAKN,OAJIrG,IACAuJ,EAAiBnJ,EAAc,eAAY0B,GAC3C2H,EAAmBrJ,EAAc,gBAAkB,uBAEhD,WACHmJ,OAAiBzH,GACjB2H,OAAmB3H,MAExB,CAAC1B,EAAaJ,IAGb,qCACKA,GAAa,qBAAKoE,UAAWoF,EAAiBtE,QAASgF,IACxD,iDAAQ9F,UAAWkF,GAAmBU,GAAtC,cACI,mBAAGI,KAAK,eAAejB,MAAM,aAA7B,SACI,cAAC,EAAD,MAEJ,cAAC,EAAD,CAAYpD,UAAWA,IACvB,cAAC,GAAD,IACA,wBAAQ3B,UAAU,cAAcc,QAASgF,EAAzC,SACI,qBAAK9F,UAAU,mBCpEpBiG,I,MAVU,WACrB,OACI,iCACI,qBAAKjG,UAAU,YAAf,sCCgDGkG,I,MA1CqC,SAAC,GAAkC,IAAjChL,EAAgC,EAAhCA,QAASC,EAAuB,EAAvBA,WAAY0B,EAAW,EAAXA,MAEjE+C,EAAWU,IACjB,EAAkCwB,oBAAkB,GAApD,mBAAOqE,EAAP,KAAkBC,EAAlB,KAiBA,OAAKD,EAGD,mBAAGH,KAAI,UAAKlH,IAAL,OAAyCjC,EAAMwJ,MAAQvF,QAlB/C,SAAC5D,GAChBA,EAAE8D,iBACFpB,EAAShD,EAAU,CAAC1B,UAASC,aAAY0B,YAgB0CkE,YAAa,SAAC7D,GAAKA,EAAE8D,kBAAmBsF,OAAO,SAC/HC,IAAI,aAAavG,UAAW,+BAD/B,SAEI,gCACI,qBAAKwG,IAAG,UAAK1H,IAAL,OAAyCjC,EAAMM,eAAiB4H,MAAOlI,EAAMkI,MAChF0B,IAAK5J,EAAM4J,IAAKC,OAjBd,WACf9G,EAAS7B,MAgBwC4I,QAbjC,WAChBC,QAAQC,MAAM,iBAAkBhK,EAAMM,eACtCyC,EAAS7B,KACTqI,GAAa,MAWL,qBAAKpG,UAAW,uCAAhB,SACI,sBAAMA,UAAW,qCAAjB,SAAwDnD,EAAMkI,UAEjElI,EAAMiK,MACH,uBAAM9G,UAAW,uBAAwB,kBAAiBnD,EAAMiK,KAAhE,UACI,sBAAM9G,UAAW,mCACjB,sBAAMA,UAAW,uBAAjB,SAA0CnD,EAAMkK,oBAd7C,OCfZC,I,MAfM,WACjB,MAAkClF,mBAAS,GAA3C,mBAAOmF,EAAP,KAAkBC,EAAlB,KAWA,OATAjF,qBAAU,WACN,IAAMkF,EAAS,WACXD,EAAapL,OAAOsL,UAIxB,OAFAtL,OAAOwG,iBAAiB,SAAU6E,EAAQ,CAAC5E,SAAS,IACpD4E,IACO,kBAAKrL,OAAO2G,oBAAoB,SAAU0E,MAClD,IAEIF,ICgBII,GAtBE,SAAIC,EAA2BC,GAC5C,MAA8BzF,oBAAkB,GAAhD,mBAAO0F,EAAP,KAAgBC,EAAhB,KACA,EAA0B3F,qBAA1B,mBAAO+E,EAAP,KAAca,EAAd,KACA,EAA0B5F,qBAA1B,mBAAOsB,EAAP,KAAcC,EAAd,KAEMsE,EAAmBjE,uBAAY,WACjC+D,GAAW,GACXC,OAAShK,GACT2F,OAAS3F,GACT4J,IACKM,KAAKvE,GACLwE,MAAMH,GACNI,SAAQ,kBAAML,GAAW,QAEkBF,GAKpD,OAHAtF,qBAAU,WACN0F,MACD,CAACA,IACG,CAACH,UAASX,QAAOzD,UCdtB2E,GAAiB,CACnBC,gBAAiB,GACjBC,eAAe,GAkCJC,GA/BS,SAACC,GAA6F,IAAD,EAAtEC,EAAsE,uDAAvCL,GAC1E,EAA4BjG,mBAAQ,UAAUsG,EAAQH,qBAAlB,QAAmCF,GAAeE,eAAtF,mBAAOI,EAAP,KAAeC,EAAf,KACMC,EAAc7E,uBAAY,yBAAMyE,QAAN,IAAMA,OAAN,EAAMA,MAAc,CAACA,IA0BrD,OAxBAd,IAAS,WACL,IAAKgB,EAAQ,OAAOG,QAAQC,UAC5B,IAAIC,EAAmB,EACnBC,EAAQ7M,OAAO8M,QACfC,EAAQ/M,OAAOsL,QAEnB,OAAO,IAAIoB,SAAc,YACR,SAAPM,EAAQC,GAAoB,IAAD,EACzBA,GAAU,KAAOA,EAASL,GAAT,UAA6BN,EAAQJ,uBAArC,QAAwDD,GAAeC,kBACxFM,GAAU,GACVC,MAEIzM,OAAO8M,UAAYD,GAAS7M,OAAOsL,UAAYyB,IAC/CH,EAAmBK,EACnBJ,EAAQ7M,OAAO8M,QACfC,EAAQ/M,OAAOsL,SAEnBtL,OAAOkN,sBAAsBF,EAAKG,KAAK,KAAMF,EAAS,KAG9DD,CAAK,QAEV,CAACT,IAEG,CAAEA,SAAQC,cCSNY,GAzCwC,SAAC,GAA2B,IAA1BhO,EAAyB,EAAzBA,QAASC,EAAgB,EAAhBA,WAExDyF,EAAMC,iBAAuB,MAC7BoG,EAAYD,KACZxL,EAAmBgF,EAAevC,GAClC1C,EAAgBiF,EAAerC,GAE/ByB,EAAWU,IACVgI,EAAaJ,IAAgB,kBAAMtI,EAASnD,OAAmB,CAACuL,gBAAiB,IAAjFM,UAiBP,OAfArG,qBAAU,WACN,GAAIrB,EAAIuI,SAAWvI,EAAIuI,QAAQC,UAAYxI,EAAIuI,QAAQE,aAAepC,EAAY,KAAOA,GAAarG,EAAIuI,QAAQC,UAAY,IAE1H,OADAxJ,EAASvD,EAAa,CAACnB,UAASC,gBACzB,eAGZ,CAAC8L,EAAWrH,EAAUgB,EAAK1F,EAASC,IAEvC8G,qBAAU,WACFrB,EAAIuI,SAAW5N,GAAiBC,IAAqBP,EAAgBC,EAASC,KAC9EmN,GAAU,GACVxM,OAAO2J,SAAS,CAACC,IAAK9E,EAAIuI,QAAQC,UAAY,GAAIzD,SAAU,cAEjE,CAACpK,EAAeC,EAAkB8M,EAAWpN,EAASC,IAGrD,sBAAKyF,IAAKA,EAAK0I,GAAIrO,EAAgBC,EAASC,GAAa6E,UAAW,cAApE,UACI,sBAAKA,UAAS,gBAAd,UACI,sBAAKA,UAAW,OAAhB,UAAyB9E,EAAQiG,MAAjC,MAA2ChG,EAAWgG,SACtD,qBAAKnB,UAAW,YAEpB,qBAAKA,UAAW,mCAAhB,SACK7E,EAAW6B,SACZ7B,EAAW6B,QAAQC,KAAI,SAACC,EAAiBqM,GAAlB,OAAgC,cAAC,GAAD,CAA+BrO,QAASA,EACjBC,WAAYA,EACZ0B,MAAOK,GAFFqM,YC5BpFC,I,MAVkC,SAAC,GAAe,IAAdtO,EAAa,EAAbA,QAE/C,OACI,yBAASoO,GAAIpO,EAAQE,KAArB,SACKF,EAAQG,aACTH,EAAQG,YAAY4B,KAAI,SAACsE,GAAD,OAAiB,cAAC,GAAD,CAAkCrG,QAASA,EAASC,WAAYoG,GAAtCA,EAAEnG,aCElEqO,I,MATmB,SAAC,GAAiB,IAAhB9H,EAAe,EAAfA,UAChC,OACI,+BACKA,GACDA,EAAU1E,KAAI,SAAC2E,EAAY2H,GAAb,OAA2B,cAAC,GAAD,CAA0BrO,QAAS0G,GAAZ2H,UCuB7DG,I,YAxB2B,SAAC,GAAoC,IAAnCC,EAAkC,EAAlCA,KAAMC,EAA4B,EAA5BA,gBAAiBtN,EAAW,EAAXA,MACzD4E,EAAawC,uBAA0B,WACzC,OAAKpH,GAAyB,IAAhBA,EAAMuB,MAGb,WAFI,wBAGZ,CAACvB,IAEEuN,EAAWnG,uBAAuC,WACpD,IAAIpC,EAAc,GAUlB,OATIqI,IACArI,EAAO,UAAYqI,GAEnBrN,GAASA,EAAMuB,MAAQ,IACvByD,EAAO,cAAgBhF,EAAMwB,OAASxB,EAAMuB,OAE5C+L,IACAtI,EAAO,sBAAwBsI,GAE5BtI,IACR,CAACqI,EAAMrN,EAAOsN,IACjB,OAAO,qBAAK5J,UAAWkB,IAAc4I,MAAOD,QCGjCE,GA3BU,SAAC,GAAgB,IAAfpF,EAAc,EAAdA,SACjB/G,EAAe4C,EAAejC,GACpC,EAA4BuD,oBAAkB,GAA9C,mBAAOkI,EAAP,KAAeC,EAAf,KACA,EAA8BnI,mBAAiB,IAA/C,mBAAOb,EAAP,KAAgBiJ,EAAhB,KAYA,OAVAC,2BAAgB,WACRvM,GAAgBA,EAAaC,MAAQ,GAAKD,EAAaE,SAAWF,EAAaC,QAC/EqG,SAASC,KAAKC,UAAUX,OAAO,WAC/ByG,EAAW,QACXE,YAAW,WACPH,GAAU,KACX,QAER,CAACrM,IAGA,qCACKoM,GACG,qBAAKV,GAAG,QAAQtJ,UAAWiB,EAA3B,SACI,cAAC,GAAD,CAAU3E,MAAOsB,EAAc+L,KAAM,YAG5ChF,MCRE0F,I,YAXuC,SAAC,GAAsC,IAArCjI,EAAoC,EAApCA,QAASkI,EAA2B,EAA3BA,KAAMC,EAAqB,EAArBA,SAAUxF,EAAW,EAAXA,MAE7E,OACI,qBAAK/E,UAAS,2BAAsBuK,GAAYxF,MAAOA,EAAvD,SACI,wBAAQjE,QAASsB,EAASrB,YAAa,SAAA7D,GAAMA,EAAE8D,kBAA/C,SAAkE,mBAC9DhB,UAAS,UAAKsK,EAAL,YAAaC,WCWvBC,GAlBS,WACpB,MAA4B1I,mBALA,qBAAd2I,WACkB,mBAArBA,UAAUC,QAAuBD,UAAUC,QAItD,mBAAOC,EAAP,KAAeC,EAAf,KAEMC,EAAW,kBAAMD,GAAU,IAC3BE,EAAY,kBAAMF,GAAU,IAWlC,OATA3I,qBAAU,WAGN,OAFAnG,OAAOwG,iBAAiB,SAAUuI,GAClC/O,OAAOwG,iBAAiB,UAAWwI,GAC5B,WACHhP,OAAO2G,oBAAoB,SAAUoI,GACrC/O,OAAO2G,oBAAoB,UAAWqI,MAE3C,IAEIH,G,mBvBfN9K,O,aAAAA,I,sBAAAA,M,KAQL,IAAMvE,GAAiC,CACnCyP,SAAU,IAGRC,GAAoB,SAAC1O,EAAyBC,GAChD,OAAQA,EAAOnB,MACX,KAAKyE,EAAWoL,IACZ,OAAO,2BAAI3O,GAAX,IAAkByO,SAAUzO,EAAMyO,SAASrL,OAAOnD,EAAOC,WAC7D,KAAKqD,EAAWqL,QACZ,IAAMH,EAAQ,aAAOzO,EAAMyO,UACrBI,EAAQJ,EAASK,WAAU,SAAAC,GAAC,OAAIA,EAAE/B,KAAO/M,EAAOC,WAItD,OAHI2O,GAAS,IACTJ,EAASI,GAAOG,WAAY,GAEzB,2BAAIhP,GAAX,IAAkByO,aACtB,QACI,OAAOzO,IAkBJiP,GAdQ,WACnB,MAA+BC,qBAAwDR,GAAmB1P,IAA1G,mBAAQyP,EAAR,KAAQA,SAAWnL,EAAnB,KAUA,MAAO,CAACmL,WAAUU,WARC,SAACC,GAChB9L,EAAS,CAACxE,KAAMyE,EAAWoL,IAAKzO,QAASkP,KAOfC,eAJP,SAACrC,GACpB1J,EAAS,CAACxE,KAAMyE,EAAWqL,QAAS1O,QAAS8M,O,iBwBoCtCsC,GAtE+B,SAAC,GAAe,IAAdF,EAAa,EAAbA,QAErCG,EAAWC,KAAXD,QAEP,EAA8B/J,mBAAQ,qBAAuB4J,EAAQK,QAAU,WAAa,KAA5F,mBAAO9K,EAAP,KAAgBiJ,EAAhB,KACA,EAA4BpI,mBAA8B,IAA1D,mBAAOkK,EAAP,KAAeC,EAAf,KACA,EAAkCnK,qBAAlC,mBAAOoK,EAAP,KAAkBC,EAAlB,KAGMC,EAAkB1I,uBAAY,WAChCmI,EAAQH,EAAQpC,IACZ4C,IACAG,aAAaH,GACbC,OAAazO,MAElB,CAACwO,EAAWR,EAAQpC,GAAIuC,IAGrBS,EAAgB5I,uBAAY,WAC9BwG,EAAW,cAAD,OAAewB,EAAQK,QAAU,WAAa,GAA9C,UACV3B,WAAWgC,EAAiB,OAE7B,CAACA,EAAiBV,EAAQK,UAEvBQ,EAAgBC,wBAAa,CAC/BC,cAAe,WACPf,EAAQgB,cACRxC,EAAW,cAAD,OAAewB,EAAQK,QAAU,WAAa,GAA9C,sBACV3B,WAAWgC,EAAiB,SAKxCnK,qBAAU,WAKN,OAJIyJ,EAAQK,UACRE,EAAU,CAAC,mBAAoBP,EAAQK,UACvCI,EAAa/B,WAAWkC,EAAeZ,EAAQK,WAE5C,WACCG,IACAG,aAAaH,GACbC,OAAazO,OAG0B,IAEnD,IAAMiP,EAAqBjJ,uBAAY,WACnC,OAAKgI,EAAQkB,OAGL,wBAAQ5M,UAAW,gBAAiBc,QAAS4K,EAAQkB,OAAOzE,SAA5D,SAAuEuD,EAAQkB,OAAOC,OAFnF,OAGZ,CAACnB,IAEEoB,EAAsBpJ,uBAAY,WACpC,OAAKgI,EAAQgB,YAGL,wBAAQ1M,UAAW,iBAAkBc,QAASwL,EAA9C,SAA6D,mBAAGtM,UAAW,kBAFxE,OAGZ,CAAC0L,IAEJ,OACI,8CAAK1L,UAAWiB,EAAS6I,MAAOkC,EAAQ,gBAAeN,EAAQqB,UAAcR,GAA7E,cACKb,EAAQpB,MAAQ,mBAAGtK,UAAW0L,EAAQpB,OACvC,+BAAOoB,EAAQmB,OACdF,IACAG,SC1DEE,I,MAZe,WAC1B,IAAOjC,EAAYe,KAAZf,SACP,OAAwB,IAApBA,EAAS1N,OACF,KAGP,qBAAK2C,UAAW,eAAhB,SACK+K,GAAYA,EAASkC,QAAO,SAAA5B,GAAC,OAAGA,EAAEC,aAAWrO,KAAI,SAAAoO,GAAC,OAAE,cAAC,GAAD,CAAuBK,QAASL,GAAfA,EAAE/B,WCD9E4D,GAAoBzI,6BAAkD/G,GAM/DyP,GAAwD,SAAC,GAAyB,IAAxB/E,EAAuB,EAAvBA,QAASzD,EAAc,EAAdA,SAC5E,EAA+C4G,KAAxCR,EAAP,EAAOA,SAAUU,EAAjB,EAAiBA,WAAYE,EAA7B,EAA6BA,eAkB7B,OACI,eAACuB,GAAkBtI,SAAnB,CAA4BxB,MAAO,CAAC2H,WAAUqC,IAjBtC,SAAC1B,GACTD,EAAW,yBACPnC,GAAI+D,KAAKC,MAAQC,KAAKC,SACtBT,SAAU,OACVzB,WAAW,EACXoB,aAAa,EACbe,UAAWJ,KAAKC,OACblF,GACAsD,KAS4CG,QALvC,SAACvC,GACbqC,EAAerC,KAIf,UACK3E,EACD,cAAC,GAAD,QAMCmH,GAAuB,WAChC,IAAM4B,EAAU5I,qBAAWoI,IAC3B,QAAgBxP,IAAZgQ,EACA,MAAM,IAAIC,MAAM,yDAEpB,OAAOD,GAGEE,GAAS,kBAAM9B,KAAuBsB,KCyDpCS,GA3F+B,SAAC,GAAsD,IAArDhR,EAAoD,EAApDA,MAAOiR,EAA6C,EAA7CA,WAAYC,EAAiC,EAAjCA,eAAgBC,EAAiB,EAAjBA,YAC/E,EAA8BlM,oBAAkB,GAAhD,mBAAOmM,EAAP,KAAgBC,EAAhB,KACA,EAA4BpM,oBAAkB,GAA9C,mBAAOhE,EAAP,KAAeqQ,EAAf,KACMC,EAASvN,iBAAyB,MAClCjF,EAAY4E,EAAenC,GAC3BgQ,EAAe7D,KACf4C,EAAMQ,KAkDZ,OAZA3L,qBAAU,WAAO,IAAD,GACZ,UAAImM,EAAOjF,eAAX,aAAI,EAAgBmF,YACpBH,GAAU,GACVD,GAAW,MACZ,CAACrR,EAAOuR,IAEXnM,qBAAU,WACN,IAAMsM,EAAMH,EAAOjF,QACR,MAAPoF,IACJA,EAAIzE,MAAM0E,YAAV,UAA2BD,EAAIE,aAA/B,YAA+CF,EAAIG,kBACpD,CAACN,IAECvR,EAGD,sBAAKmD,UAAW,sBAAuB8J,MAAOhM,EAAS,GAAK,CAAC6Q,eAAgB,UAA7E,UACK7Q,GAAU,cAAC,GAAD,CAAgBsE,QAAS2L,EAAgBzD,KAAM,qBAAsBC,SAAU,OAAQxF,MAAO,oBACzG,qBAAKnE,IAAKwN,EACL5H,IAAG,UAAK1H,IAAL,OAAyCmP,EAAUpR,EAAM+R,YAAc/R,EAAMwJ,MAChFI,IAAK5J,EAAM4J,IAAK3F,QAtDlBlF,EAAYoS,EAAc,aAuDxBlE,MAAO,CAAC+E,QAAS/Q,EAAS,QAAU,QACpC4I,OA/CO,WAChByH,GAAU,IA8CoBxH,QA3Cb,WASbyG,EARCiB,EAQG,CACAtB,SAAU,QACVF,KAAM,6BACNd,QAAS,KAVT,CACAgB,SAAU,QACVF,KAAM,kBACNvC,KAAM,eACNyB,QAAS,MASZkC,EAGDC,GAAW,GAFXF,OA4BClQ,GAAU,cAAC,GAAD,CAAgBsE,QAAS0L,EAAYxD,KAAM,sBAAuBC,SAAU,QAASxF,MAAO,uBACrGjH,GAAU,cAAC,GAAD,IACXA,GACD,sBAAKkC,UAAW,SAAhB,UACKnD,EAAM+R,aACH,qBAAK5O,UAAW,SAAU+E,MAAK,UAAKkJ,EAAU,YAAc,aAA5D,SACI,wBAAQnN,QA5DR,SAAC5D,GACjBA,EAAE8D,iBACFkN,GAAYD,GACZE,GAAU,IAyDM,SAA8B,mBAC1BnO,UAAS,qBAAgBiO,EAAU,iBAAmB,sBAGlE,sBAAKjO,UAAW,QAAhB,UACI,iCAAOnD,EAAMiK,MAAQ,sBAAM9G,UAAW,cAAe,kBAAiBnD,EAAMiK,KAAvD,SAA8DjK,EAAMiS,YAAmBjS,EAAMkI,SAClH,+BAAOlI,EAAMkS,UAEhBlS,EAAMmS,MACH,qBAAKhP,UAAW,OAAhB,SACI,qBAAKwG,IAAG,UAAK1H,IAAL,OAAyCjC,EAAMmS,MAAQvI,IAAK5J,EAAMmS,eA1B3E,M,iBCgBRC,GA/ES,WACpB,IAAMpS,EAA6B2D,EAAepC,GAClD,EAA4B0D,oBAAkB,GAA9C,mBAAOkI,EAAP,KAAeC,EAAf,KAEMrK,EAAWU,IACjB,EAAwCwB,mBAAiB,cAAzD,mBAAOoN,EAAP,KAAqBC,EAArB,KAEAC,aAAY,CACRC,UAAW,CACP,UAAa,kBAAMzP,EAAStC,MAC5B,WAAc,kBAAMsC,EAAS9C,MAC7B,OAAU,kBAAM8C,EAASrC,OAE7B+R,aAActF,IAGlB,IAAMuC,EAAgBC,wBAAa,CAC/B+C,8BAA8B,EAC9BC,SAAW,SAAAC,GACe,UAAlBA,EAAUC,IACV9P,EAAStC,KACgB,SAAlBmS,EAAUC,KACjB9P,EAAS9C,MAGjB6S,UAAW,SAACF,GACc,UAAlBA,EAAUC,IACVP,EAAgB,oBACS,SAAlBM,EAAUC,IACjBP,EAAgB,mBAEhBA,EAAgB,YAetBnB,EAAiC,SAAC9Q,GACnC,OAADA,QAAC,IAADA,KAAG8D,iBACHpB,EAASrC,MAeb,OAZA0E,qBAAU,WACO,MAATpF,GACAqH,SAASC,KAAKC,UAAU2B,IAAI,cAC5BoJ,EAAgB,SAChBlF,GAAU,KAEV/F,SAASC,KAAKC,UAAUX,OAAO,cAC/B0L,EAAgB,cAChB/E,YAAW,kBAAMH,GAAU,KAAQ,QAExC,CAACpN,IAECmN,EAMD,8CAAKhK,UAAWkP,GAAkB3C,GAAlC,cACI,qBAAKvM,UAAW,WAAYc,QAASkN,IACrC,cAAC,GAAD,CAAYnR,MAAOA,EAAOiR,WAnCI,SAAC5Q,GAClC,OAADA,QAAC,IAADA,KAAG8D,iBACHpB,EAAS9C,MAiC6CkR,YAAaA,EACnDD,eA/BsB,SAAC7Q,GACtC,OAADA,QAAC,IAADA,KAAG8D,iBACHpB,EAAStC,YAqBF,MC1CAsS,GA9Bc,WACzB,IAAMvB,EAAe7D,KACf4C,EAAMQ,KACZ,EAAoC9L,oBAAkB,GAAtD,mBAAO+N,EAAP,KAAmBC,EAAnB,KAwBA,OAtBA7N,qBAAU,WAiBN,OAhBKoM,GAAiBwB,IAClBzC,EAAI,CACAL,SAAU,QACVF,KAAM,uBACNvC,KAAM,iBAEVwF,GAAc,IAEdzB,GAAgBwB,IAChBzC,EAAI,CACAL,SAAU,UACVF,KAAM,0BACNvC,KAAM,eAEVwF,GAAc,IAEX,WACHA,GAAc,MAE6B,CAACzB,KAE5CA,GCbG0B,GAdO,WAElB,MAA+CC,iCAAxCC,EAAP,EAAOA,WAAYC,EAAnB,EAAmBA,YAAaC,EAAhC,EAAgCA,YAShC,OAPAlO,qBAAU,WACFmO,WACAlM,SAASC,KAAKC,UAAU2B,IAAI,UACrBsK,YACPnM,SAASC,KAAKC,UAAU2B,IAAI,YAEjC,IACI,CAACsK,oBAAUD,oBAAUvU,sBAAWoU,aAAYC,cAAaC,gBC6BrDG,GA/BO,WAClBV,KACAG,KACA,IAAMnQ,EAAWU,IACjB,EjCCiCnB,EAAqB,IiCD/CoR,EAAP,EAAOA,KAAMC,EAAb,EAAaA,UAAW3J,EAAxB,EAAwBA,MAaxB,OAXA5E,qBAAU,YACDuO,GAAaD,IACd3Q,EAASjC,EAAc4S,EAAK5O,UAAU8O,SAAQ,SAAA7O,GAAC,OAAIA,EAAEvG,eAAaoV,SAAQ,SAAAlP,GAAC,OAAIA,EAAEvE,WAASK,SAC1FuC,EAASvD,EAAa,CAACnB,QAASqV,EAAK5O,UAAU,OAE/CkF,GACAD,QAAQC,MAAMA,KAEnB,CAACjH,EAAU4Q,EAAWD,EAAM1J,IAI3B,cAAC,GAAD,UACK0J,GACG,qCACI,cAAC,GAAD,CAAQ5O,UAAW4O,EAAK5O,YACxB,cAAC,GAAD,CAAMA,UAAW4O,EAAK5O,YACtB,cAAC,GAAD,IACA,cAAC,GAAD,UCzBd+O,GAAcC,QACW,cAA7B7U,OAAO8U,SAASC,UAEe,UAA7B/U,OAAO8U,SAASC,UAEhB/U,OAAO8U,SAASC,SAAS9O,MAAM,2DA0CnC,SAAS+O,GAAgBC,EAAeC,GACtCvG,UAAUwG,cACPC,SAASH,GACTnJ,MAAK,SAACuJ,GACLA,EAAaC,cAAgB,WAC3B,IAAMC,EAAmBF,EAAaG,WACd,MAApBD,IAGJA,EAAiBE,cAAgB,WACA,cAA3BF,EAAiB/U,QACfmO,UAAUwG,cAAcO,YAEtBL,EAAaM,SACfN,EAAaM,QAAQC,YAAY,CAACtW,KAAM,iBAItC4V,GAAUA,EAAOW,UACnBX,EAAOW,SAASR,KAQlBvK,QAAQgL,IAAI,sCAGRZ,GAAUA,EAAOa,WACnBb,EAAOa,UAAUV,WAO5BtJ,OAAM,SAAChB,GACND,QAAQC,MAAM,4CAA6CA,M,qBCvFjEiL,EAAaC,WAEbC,IAAShI,OACL,cAAC,IAAMiI,WAAP,UACI,cAAC,WAAD,CAAU7S,MAAOA,EAAjB,SACI,cAAC,GAAD,UACI,cAAC,GAAD,CAAoBgJ,QAAS,CAAC2D,QAAS,KAAvC,SACI,cAAC,GAAD,YAKhB7H,SAASgO,eAAe,SDErB,SAAkBlB,GACvB,GAA6C,kBAAmBvG,UAAW,CAGzE,GADkB,IAAI0H,IAAIrT,GAAwBhD,OAAO8U,SAAS5K,MACpDoM,SAAWtW,OAAO8U,SAASwB,OAIvC,OAGFtW,OAAOwG,iBAAiB,QAAQ,WAC9B,IAAMyO,EAAK,UAAMjS,GAAN,sBAEP4R,KA+DV,SAAiCK,EAAeC,GAE9CqB,MAAMtB,EAAO,CACXuB,QAAS,CAAE,iBAAkB,YAE5B1K,MAAK,SAAC2K,GAEL,IAAMC,EAAcD,EAASD,QAAQG,IAAI,gBAEnB,MAApBF,EAASG,QACO,MAAfF,IAA8D,IAAvCA,EAAYpV,QAAQ,cAG5CqN,UAAUwG,cAAc0B,MAAM/K,MAAK,SAACuJ,GAClCA,EAAayB,aAAahL,MAAK,WAC7B9L,OAAO8U,SAASiC,eAKpB/B,GAAgBC,EAAOC,MAG1BnJ,OAAM,WACLjB,QAAQgL,IAAI,oEArFVkB,CAAwB/B,EAAOC,GAI/BvG,UAAUwG,cAAc0B,MAAM/K,MAAK,WACjChB,QAAQgL,IACN,+GAMJd,GAAgBC,EAAOC,OC3B/B+B,K","file":"static/js/main.5d2d5a04.chunk.js","sourcesContent":["export type GalleryResult = {\n galleries: Array\n}\n\ntype LabeledAndTyped = {\n type: string,\n label: string\n}\n\nexport type Gallery = LabeledAndTyped & {\n collections: Array\n}\n\nexport type Collection = LabeledAndTyped & {\n entries: Array\n}\n\nexport type GalleryEntry = {\n thumbnailPath: string,\n path: string,\n toggledPath?: string,\n title: string,\n alt: string,\n desc: string,\n logo?: string,\n noteTitle?: string,\n note?: string,\n noteBadge?: string\n}\n\nexport const getCollectionId = (gallery: Gallery, collection?: Collection) => {\n return `${gallery.type}-${collection?.type ?? gallery.collections[0].type}`\n}\n\nexport type LoadProgress = {\n total: number\n loaded: number\n}","import {createSlice, PayloadAction} from \"@reduxjs/toolkit\";\nimport {Collection, Gallery, GalleryEntry, getCollectionId, LoadProgress} from \"../model/gallery\";\nimport {RootState} from \"./store\";\nimport {isDesktop} from \"react-device-detect\";\n\ninterface AppState {\n autoScrolling: boolean\n activeCollection: string | null\n openedGallery: Gallery | null\n openedCollection: Collection | null\n openedEntry: GalleryEntry | null\n collapsed: boolean\n menuToggled: boolean\n loadProgress?: LoadProgress\n}\n\nconst initialState: AppState = {\n autoScrolling: false,\n activeCollection: null,\n openedGallery: null,\n openedCollection: null,\n openedEntry: null,\n collapsed: !isDesktop || window.innerWidth < 1260,\n menuToggled: false\n}\n\nexport interface OpenEntryPayload {\n gallery: Gallery\n collection: Collection\n entry: GalleryEntry\n}\n\nexport interface ActivatePayload {\n gallery: Gallery\n collection?: Collection\n}\n\nexport const appSlice = createSlice({\n name: \"gallery\",\n initialState,\n reducers: {\n activateMenu: (state, action: PayloadAction) => {\n if (state.autoScrolling) {\n return state\n }\n const collection = action.payload.collection\n ? getCollectionId(action.payload.gallery, action.payload.collection)\n : getCollectionId(action.payload.gallery)\n if (state.activeCollection !== collection) {\n return {...state, activeCollection: collection}\n }\n },\n scrollFinished: (state) => {\n return {...state, autoScrolling: false}\n },\n selectMenu: (state, action: PayloadAction) => {\n let res = {...state, autoScrolling: true}\n const collection = action.payload.collection\n ? getCollectionId(action.payload.gallery, action.payload.collection)\n : getCollectionId(action.payload.gallery)\n if (state.activeCollection !== collection) {\n res = {...res, activeCollection: collection}\n }\n return res\n },\n openEntry: (state, action: PayloadAction) => {\n return {\n ...state,\n openedGallery: action.payload.gallery,\n openedEntry: action.payload.entry,\n openedCollection: action.payload.collection\n }\n },\n nextEntry: (state) => {\n if (!state.openedCollection || !state.openedEntry) return state\n const idx = state.openedCollection.entries.map((e: GalleryEntry) => e.thumbnailPath).indexOf(state.openedEntry.thumbnailPath)\n let entry\n if (idx === state.openedCollection.entries.length - 1) {\n entry = state.openedCollection.entries[0]\n } else {\n entry = state.openedCollection.entries[idx + 1]\n }\n return {\n ...state,\n openedEntry: entry\n }\n },\n previousEntry: (state) => {\n if (!state.openedCollection || !state.openedEntry) return state\n const idx: number = state.openedCollection.entries.map((e: GalleryEntry) => e.thumbnailPath).indexOf(state.openedEntry.thumbnailPath)\n let entry: GalleryEntry\n if (idx === 0) {\n entry = state.openedCollection.entries[state.openedCollection.entries.length - 1]\n } else {\n entry = state.openedCollection.entries[idx - 1]\n }\n return {\n ...state,\n openedEntry: entry\n }\n },\n closeEntry: state => {\n return {...state, openedEntry: null, openedGallery: null, openedCollection: null}\n },\n setCollapsed: (state, action: PayloadAction) => {\n return {...state, collapsed: action.payload}\n },\n toggleMenu: (state, action: PayloadAction) => {\n return {...state, menuToggled: action.payload === undefined ? !state.menuToggled : action.payload}\n },\n setTotalCount: (state, action: PayloadAction) => {\n return {...state, loadProgress: {total: action.payload, loaded: 0}}\n },\n incrementLoadedCount: state => {\n if (!state.loadProgress) return\n return {...state, loadProgress: {...state.loadProgress, loaded: state.loadProgress.loaded+1}}\n }\n }\n})\n\nexport const {\n activateMenu,\n selectMenu,\n scrollFinished,\n openEntry,\n nextEntry,\n previousEntry,\n closeEntry,\n setCollapsed,\n toggleMenu,\n setTotalCount,\n incrementLoadedCount\n} = appSlice.actions\n\nexport const selectActiveCollection = (state: RootState) => state.app.activeCollection\nexport const selectAutoScrolling = (state: RootState) => state.app.autoScrolling\nexport const selectOpenedEntry = (state: RootState) => state.app.openedEntry\nexport const selectCollapsed = (state: RootState) => state.app.collapsed\nexport const selectMenuToggled = (state: RootState) => state.app.menuToggled\nexport const selectLoadProgress = (state: RootState) => state.app.loadProgress\n\nexport default appSlice.reducer","import {createApi, fetchBaseQuery} from \"@reduxjs/toolkit/dist/query/react\";\nimport {GalleryResult} from \"../model/gallery\";\n\n\nexport const galleriesApi = createApi({\n reducerPath: \"galleriesApi\",\n baseQuery: fetchBaseQuery({\n baseUrl: `${process.env.REACT_APP_BACKEND_URL}/api`,\n }),\n endpoints: (build) => ({\n getGalleries: build.query({\n query: () => \"galleries\",\n })\n })\n})\n\nconst {useGetGalleriesQuery} = galleriesApi\n\nexport const useGetGalleries = () => useGetGalleriesQuery(\"\")","import {configureStore} from \"@reduxjs/toolkit\"\nimport appReducer from \"./gallerySlice\";\nimport {galleriesApi} from \"./galleriesApi\";\nimport {setupListeners} from \"@reduxjs/toolkit/query\";\n\nconst store = configureStore({\n reducer: {\n [galleriesApi.reducerPath]: galleriesApi.reducer,\n app: appReducer,\n },\n middleware: getDefaultMiddleware => getDefaultMiddleware().concat(galleriesApi.middleware)\n})\n\nsetupListeners(store.dispatch)\n\nexport default store\n\nexport type RootState = ReturnType\nexport type AppDispatch = typeof store.dispatch","import {Reducer, useReducer} from \"react\";\nimport {Message} from \"../model/ui\";\n\n\ntype PopMessagesState = {\n messages: Array\n}\n\nenum ActionType {\n ADD, DISMISS\n}\n\ntype PopMessageAction =\n { type: ActionType.ADD; payload: Message }\n | { type: ActionType.DISMISS; payload: number }\n\nconst initialState: PopMessagesState = {\n messages: []\n}\n\nconst popMessageReducer = (state: PopMessagesState, action: PopMessageAction): PopMessagesState => {\n switch (action.type) {\n case ActionType.ADD:\n return {...state, messages: state.messages.concat(action.payload)}\n case ActionType.DISMISS:\n const messages = [...state.messages]\n const index = messages.findIndex(m => m.id === action.payload)\n if (index > -1) {\n messages[index].dismissed = true\n }\n return {...state, messages}\n default:\n return state\n }\n}\n\nconst usePopMessages = () => {\n const [{messages}, dispatch] = useReducer>(popMessageReducer, initialState)\n\n const popMessage = (message: Message) => {\n dispatch({type: ActionType.ADD, payload: message})\n }\n\n const dismissMessage = (id: number) => {\n dispatch({type: ActionType.DISMISS, payload: id})\n }\n\n return {messages, popMessage, dismissMessage}\n}\n\nexport default usePopMessages","import React from \"react\";\nimport \"./logo.scss\"\n\nconst Logo: React.FC = () => {\n return (\n \n \n \n \n \n \n \n \n \n \n \n \n )\n}\n\nexport default Logo","import type {RootState, AppDispatch} from \"./store\";\nimport {TypedUseSelectorHook, useDispatch, useSelector} from \"react-redux\";\n\nexport const useAppDispatch = () => useDispatch()\nexport const useAppSelector: TypedUseSelectorHook = useSelector","import React, {useRef} from \"react\";\nimport {Collection, Gallery, getCollectionId} from \"../../model/gallery\";\nimport {MenuHandlerProvider} from \"./menuItem\";\n\ntype SubMenuItemProps = {\n gallery: Gallery,\n collection: Collection,\n activeCollection: string | null,\n menuHandlerProvider: MenuHandlerProvider\n}\n\nconst SubMenuItem: React.FC = ({gallery, collection, activeCollection, menuHandlerProvider}) => {\n\n const ref = useRef(null)\n\n const getClasses = () => {\n let classes\n if (getCollectionId(gallery, collection) === activeCollection) {\n classes = \"active\"\n }\n return classes\n }\n\n const menuHandler = () => {\n return menuHandlerProvider({gallery, collection})\n }\n\n return (\n \n )\n}\n\nexport default SubMenuItem","import React from \"react\";\nimport {Collection, Gallery, getCollectionId} from \"../../model/gallery\";\nimport {ActivatePayload, selectMenu, toggleMenu} from \"../../reducer/gallerySlice\";\nimport {useAppDispatch} from \"../../reducer/hooks\";\nimport SubMenuItem from \"./subMenuItem\";\n\ntype MenuItemProps = {\n gallery: Gallery\n activeCollection: string | null\n}\n\nexport type MenuHandlerProvider = (payload: ActivatePayload) => React.MouseEventHandler\n\nconst MenuItem: React.FC = ({gallery, activeCollection}) => {\n const dispatch = useAppDispatch()\n\n const galleryClass = (gallery: Gallery) => {\n let result = \"subnav\"\n if (activeCollection != null && gallery.collections.map((c: Collection) => getCollectionId(gallery, c)).includes(activeCollection)) {\n result = `${result} active`\n }\n return result;\n }\n\n const handleMenuItem: MenuHandlerProvider = (payload: ActivatePayload) => (e: React.MouseEvent) => {\n e.preventDefault()\n dispatch(selectMenu(payload))\n if (payload.collection) {\n dispatch(toggleMenu(false))\n }\n }\n\n\n return (\n
\n \n
\n {gallery.collections && gallery.collections.map((c: Collection) => )}\n
\n
\n )\n\n}\n\nexport default MenuItem","import React from \"react\";\nimport {Gallery, GalleryResult} from \"../../model/gallery\";\nimport MenuItem from \"./menuItem\";\nimport {useAppSelector} from \"../../reducer/hooks\";\nimport {selectActiveCollection} from \"../../reducer/gallerySlice\";\n\ntype NavigationProps = GalleryResult\n\nconst Navigation: React.FC = ({galleries}) => {\n\n const activeCollection = useAppSelector(selectActiveCollection)\n\n return (\n \n )\n}\n\nexport default Navigation","import {useEffect, useState} from \"react\";\n\nconst useMediaQuery = (query: string): boolean => {\n const [match, setMatch] = useState(false)\n\n useEffect(()=>{\n const queryList = window.matchMedia(query)\n const handler = () => setMatch(queryList.matches)\n\n try {\n queryList.addEventListener(\"change\", handler, {passive: true})\n } catch (e) {\n queryList.addListener(handler)\n }\n\n handler()\n return () => {\n try {\n queryList.removeEventListener(\"change\", handler)\n } catch (e) {\n queryList.removeListener(handler)\n }\n }\n }, [query])\n\n return match\n}\n\nexport default useMediaQuery","import React, {useCallback, useEffect, useState} from \"react\";\n\nexport const useLocalStorage = (key: string, defaultValue?: T | (() => T)) => {\n return useStorage({key, defaultValue, storage: window.localStorage})\n}\n\nexport const useSessionStorage = (key: string, defaultValue?: T | (() => T)) => {\n return useStorage({key, defaultValue, storage: window.sessionStorage})\n}\n\ntype StorageOptions = {\n key: string\n defaultValue?: T | (() => T)\n storage: Storage\n}\n\ntype StorageResult = [\n value: T | undefined,\n setValue: React.Dispatch>,\n remove: () => void,\n]\n\nconst useStorage = ({key, defaultValue, storage}: StorageOptions): StorageResult => {\n const [value, setValue] = useState(()=>{\n const jsonValue = storage.getItem(key)\n if (jsonValue != null) return JSON.parse(jsonValue)\n\n if (defaultValue instanceof Function) return defaultValue()\n return defaultValue\n })\n\n useEffect(()=>{\n if (value === undefined) return storage.removeItem(key)\n storage.setItem(key, JSON.stringify(value))\n }, [key, value, storage])\n\n const remove = useCallback(()=>{\n setValue(undefined)\n }, [])\n\n return [value, setValue, remove]\n}\n\nexport default useLocalStorage","import React, {useEffect} from \"react\";\nimport useMediaQuery from \"./useMediaQuery\";\nimport useLocalStorage from \"./useStorage\";\n\n\ntype DarkModeResult = [\n boolean,\n React.Dispatch>\n]\n\nconst useDarkMode = (): DarkModeResult => {\n const [darkMode, setDarkMode] = useLocalStorage(\"useDarkMode\")\n const prefersDarkMode = useMediaQuery(\"(prefers-color-scheme: dark)\")\n const enabled = darkMode ?? prefersDarkMode\n\n useEffect(() => {\n document.body.classList.toggle(\"dark-mode\", enabled)\n }, [enabled])\n\n return [enabled, setDarkMode]\n}\n\nexport default useDarkMode","import React from \"react\";\nimport useDarkMode from \"../hooks/useDarkMode\";\n\ntype DarkModeContextProps = {\n darkMode: boolean\n setDarkMode?: React.Dispatch>\n}\n\nconst defaultState: DarkModeContextProps = {\n darkMode: false\n}\n\nconst DarkModeContext = React.createContext(defaultState)\n\nexport default DarkModeContext\n\nexport const DarkModeProvider: React.FC = ({children}) => {\n const [darkMode, setDarkMode] = useDarkMode()\n\n return (\n \n {children}\n \n\n )\n}","import React, {useContext} from \"react\";\n\nimport \"./darkModeToggle.scss\"\nimport DarkModeContext from \"../../context/darkModeContext\";\n\n\nconst DarkModeToggle: React.FC = () => {\n const {darkMode, setDarkMode} = useContext(DarkModeContext)\n\n const toggle = () => {\n setDarkMode?.(!darkMode)\n }\n\n return (\n \n )\n\n}\n\nexport default DarkModeToggle","import React, {useEffect, useMemo, useState} from \"react\";\nimport {GalleryResult} from \"../../model/gallery\";\nimport \"./header.scss\"\nimport Logo from \"./logo\";\nimport Navigation from \"../menu/nav\";\nimport {useAppDispatch, useAppSelector} from \"../../reducer/hooks\";\nimport {selectCollapsed, selectMenuToggled, setCollapsed, toggleMenu} from \"../../reducer/gallerySlice\";\nimport {useDoubleTap} from \"use-double-tap\";\nimport DarkModeToggle from \"./darkModeToggle\";\nimport useMediaQuery from \"../../hooks/useMediaQuery\";\nimport {isDesktop} from \"react-device-detect\";\n\ntype NavBarProps = GalleryResult\n\nconst Header: React.FC = ({galleries}) => {\n\n\n const collapsed = useAppSelector(selectCollapsed)\n const menuToggled = useAppSelector(selectMenuToggled)\n const dispatch = useAppDispatch()\n const isNarrow = useMediaQuery(\"(max-width: 1260px)\")\n\n const [headerClasses, setHeaderClasses] = useState()\n const [backdropClasses, setBackdropClasses] = useState()\n const doubleTap = useDoubleTap((event)=>{\n event.preventDefault()\n window.scrollTo({top: 0, behavior: \"smooth\"})\n })\n const doubleTapProps = useMemo(()=>{\n if (collapsed && !menuToggled) {\n return doubleTap\n }\n return {}\n }, [collapsed, menuToggled, doubleTap])\n\n const toggleMenuHandler = (e: React.MouseEvent | React.TouchEvent) => {\n if (collapsed) {\n e.preventDefault()\n dispatch(toggleMenu())\n }\n }\n\n useEffect(()=>{\n if (menuToggled) {\n document.body.classList.add(\"menu-open\")\n } else {\n document.body.classList.remove(\"menu-open\")\n }\n }, [menuToggled])\n\n useEffect(() => {\n dispatch(setCollapsed(!isDesktop || isNarrow))\n if (!isDesktop || isNarrow) {\n document.body.classList.add(\"collapsed\")\n } else {\n document.body.classList.remove(\"collapsed\")\n dispatch(toggleMenu(false))\n }\n }, [dispatch, isNarrow])\n\n useEffect(() => {\n if (collapsed) {\n setHeaderClasses(menuToggled ? \"toggled\" : undefined)\n setBackdropClasses(menuToggled ? \"menu-backdrop\" : \"menu-backdrop hide\")\n }\n return () => {\n setHeaderClasses(undefined)\n setBackdropClasses(undefined)\n }\n }, [menuToggled, collapsed])\n\n return (\n <>\n {collapsed &&
}\n
\n \n \n \n \n \n \n
\n \n );\n};\n\n\nexport default Header\n\n","import React from \"react\";\nimport \"./footer.scss\"\n\nconst Footer: React.FC = () => {\n return (\n
\n
\n © Full Doors 2021\n
\n
\n );\n}\n\nexport default Footer","import React, {useState} from \"react\";\nimport {Collection, Gallery, GalleryEntry} from \"../../model/gallery\"\nimport {incrementLoadedCount, openEntry} from \"../../reducer/gallerySlice\";\nimport {useAppDispatch} from \"../../reducer/hooks\";\nimport \"./entry.scss\"\n\ntype EntryProps = {\n gallery: Gallery\n collection: Collection\n entry: GalleryEntry\n}\n\nconst GalleryEntryContainer: React.FC = ({gallery, collection, entry}) => {\n\n const dispatch = useAppDispatch()\n const [available, setAvailable] = useState(true)\n\n const handleOpen = (e: React.MouseEvent) => {\n e.preventDefault()\n dispatch(openEntry({gallery, collection, entry}))\n }\n\n const handleLoad = () => {\n dispatch(incrementLoadedCount())\n }\n\n const handleError = () => {\n console.error(\"Failed to load\", entry.thumbnailPath)\n dispatch(incrementLoadedCount())\n setAvailable(false)\n }\n\n if (!available) return null\n\n return (\n {e.preventDefault()}} target=\"_blank\"\n rel=\"noreferrer\" className={\"lightboxgallery-gallery-item\"}>\n
\n {entry.alt}\n
\n {entry.title}\n
\n {entry.note && (\n \n \n {entry.noteBadge}\n \n )}\n
\n
\n )\n}\n\nexport default GalleryEntryContainer","import {useEffect, useState} from \"react\";\n\nconst useScrollTop = (): number => {\n const [scrollTop, setScrollTop] = useState(0)\n\n useEffect(()=>{\n const update = () => {\n setScrollTop(window.scrollY)\n }\n window.addEventListener(\"scroll\", update, {passive: true})\n update()\n return ()=> window.removeEventListener(\"scroll\", update)\n }, [])\n\n return scrollTop\n}\n\nexport default useScrollTop","import {DependencyList, useCallback, useEffect, useState} from \"react\";\n\ntype AsyncResult = {\n loading: boolean,\n error?: Error,\n value?: T\n}\n\nconst useAsync = (promise: () => Promise, deps: DependencyList): AsyncResult => {\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState()\n const [value, setValue] = useState()\n\n const callbackMemoized = useCallback(() => {\n setLoading(true)\n setError(undefined)\n setValue(undefined)\n promise()\n .then(setValue)\n .catch(setError)\n .finally(() => setLoading(false))\n\n }, /* eslint-disable react-hooks/exhaustive-deps */ deps)\n\n useEffect(() => {\n callbackMemoized()\n }, [callbackMemoized])\n return {loading, error, value}\n}\n\nexport default useAsync","import React, {useCallback, useState} from \"react\";\nimport useAsync from \"./useAsync\";\n\ntype ScrollFinishResult = {\n listen: boolean,\n setListen: React.Dispatch>\n}\n\ntype ScrollFinishOptions = {\n unchangedFrames?: number,\n listenOnStart?: boolean\n}\n\nconst defaultOptions = {\n unchangedFrames: 20,\n listenOnStart: false\n}\n\nconst useScrollFinish = (callback: () => void, options: ScrollFinishOptions = defaultOptions): ScrollFinishResult => {\n const [listen, setListen] = useState(options.listenOnStart ?? defaultOptions.listenOnStart)\n const memCallback = useCallback(() => callback?.(), [callback])\n\n useAsync(() => {\n if (!listen) return Promise.resolve()\n let lastChangedFrame = 0\n let lastX = window.scrollX\n let lastY = window.scrollY\n\n return new Promise(() => {\n const tick = (frames: number) => {\n if (frames >= 500 || frames - lastChangedFrame > (options.unchangedFrames ?? defaultOptions.unchangedFrames)) {\n setListen(false)\n memCallback()\n } else {\n if (window.scrollX !== lastX || window.scrollY !== lastY) {\n lastChangedFrame = frames\n lastX = window.scrollX\n lastY = window.scrollY\n }\n window.requestAnimationFrame(tick.bind(null, frames + 1))\n }\n }\n tick(0)\n })\n }, [listen])\n\n return { listen, setListen }\n}\n\nexport default useScrollFinish","import React, {useEffect, useRef} from \"react\";\nimport {Collection, Gallery, GalleryEntry, getCollectionId} from \"../../model/gallery\"\nimport GalleryEntryContainer from \"./entry\";\nimport \"./collection.scss\"\nimport useScrollTop from \"../../hooks/useScrollTop\";\nimport {useAppDispatch, useAppSelector} from \"../../reducer/hooks\";\nimport {activateMenu, selectAutoScrolling, scrollFinished, selectActiveCollection} from \"../../reducer/gallerySlice\";\nimport useScrollFinish from \"../../hooks/useScrollFinish\";\n\ntype CollectionProps = {\n gallery: Gallery\n collection: Collection\n}\n\nconst CollectionContainer: React.FC = ({gallery, collection}) => {\n\n const ref = useRef(null)\n const scrollTop = useScrollTop()\n const activeCollection = useAppSelector(selectActiveCollection)\n const autoScrolling = useAppSelector(selectAutoScrolling)\n\n const dispatch = useAppDispatch()\n const {setListen} = useScrollFinish(() => dispatch(scrollFinished()), {unchangedFrames: 5})\n\n useEffect(() => {\n if (ref.current && ref.current.offsetTop + ref.current.offsetHeight > scrollTop + 400 && scrollTop >= ref.current.offsetTop - 400) {\n dispatch(activateMenu({gallery, collection}))\n return () => {\n }\n }\n }, [scrollTop, dispatch, ref, gallery, collection])\n\n useEffect(() => {\n if (ref.current && autoScrolling && activeCollection === getCollectionId(gallery, collection)) {\n setListen(true)\n window.scrollTo({top: ref.current.offsetTop - 70, behavior: \"smooth\"})\n }\n }, [autoScrolling, activeCollection, setListen, gallery, collection])\n\n return (\n
\n
\n
{gallery.label} / {collection.label}
\n
\n
\n
\n {collection.entries &&\n collection.entries.map((e: GalleryEntry, i: number) => )}\n
\n
\n )\n}\n\nexport default CollectionContainer","import React from \"react\";\nimport {Collection, Gallery} from \"../../model/gallery\"\nimport CollectionContainer from \"./collection\";\nimport \"./gallery.scss\"\n\ntype GalleryProps = {\n gallery: Gallery\n}\n\nconst GalleryContainer: React.FC = ({gallery}) => {\n\n return (\n
\n {gallery.collections &&\n gallery.collections.map((c: Collection)=>)}\n
\n )\n}\n\nexport default GalleryContainer\n\n","import React from \"react\";\nimport {Gallery, GalleryResult} from \"../../model/gallery\";\nimport GalleryContainer from \"../gallery/gallery\";\nimport \"./main.scss\"\n\ntype MainProps = GalleryResult\n\nconst Main: React.FC = ({galleries}) => {\n return (\n
\n {galleries &&\n galleries.map((g: Gallery, i: number) => )}\n
\n )\n}\n\nexport default Main\n","import React, {useCallback} from \"react\";\nimport \"./progress.scss\"\nimport {LoadProgress} from \"../model/gallery\";\n\ntype ProgressProps = {\n size?: string\n animationLength?: string\n state?: LoadProgress\n}\n\nconst Progress: React.FC = ({size, animationLength, state}) => {\n const getClasses = useCallback<() => string>(() => {\n if (!state || state.total === 0) {\n return \"progress indefinite\"\n }\n return \"progress\"\n }, [state])\n\n const getStyle = useCallback<() => React.CSSProperties>(() => {\n let result: any = {}\n if (size) {\n result[\"--size\"] = size\n }\n if (state && state.total > 0) {\n result[\"--progress\"] = state.loaded / state.total\n }\n if (animationLength) {\n result[\"--animation-length\"] = animationLength\n }\n return result as React.CSSProperties\n }, [size, state, animationLength])\n return
\n}\n\nexport default Progress","import React, {useLayoutEffect, useState} from \"react\";\nimport \"./loader.scss\"\nimport Progress from \"../progress\";\nimport {useAppSelector} from \"../../reducer/hooks\";\nimport {selectLoadProgress} from \"../../reducer/gallerySlice\";\n\n\nconst Loader: React.FC = ({children}) => {\n const loadProgress = useAppSelector(selectLoadProgress)\n const [render, setRender] = useState(true)\n const [classes, setClasses] = useState(\"\")\n\n useLayoutEffect(()=>{\n if (loadProgress && loadProgress.total > 0 && loadProgress.loaded === loadProgress.total) {\n document.body.classList.remove(\"loading\")\n setClasses(\"hide\")\n setTimeout(()=> {\n setRender(false)\n }, 200)\n }\n }, [loadProgress])\n\n return (\n <>\n {render && (\n
\n \n
\n )}\n {children}\n \n )\n}\n\nexport default Loader","import React from \"react\";\nimport \"./modalNav.scss\"\n\ntype ModalNavButtonProps = {\n handler: React.EventHandler,\n icon: string,\n position: \"left\" | \"right\",\n title?: string\n}\n\nconst ModalNavButton: React.FC = ({handler, icon, position, title}) => {\n\n return (\n
\n \n
\n\n )\n}\n\nexport default ModalNavButton","import {useEffect, useState} from \"react\"\n\n\nexport const getOnlineStatus = () => {\n return typeof navigator !== \"undefined\" &&\n typeof navigator.onLine === \"boolean\" ? navigator.onLine : true\n}\n\nconst useOnlineStatus = () => {\n const [online, setOnline] = useState(getOnlineStatus())\n\n const goOnline = () => setOnline(true)\n const goOffline = () => setOnline(false)\n\n useEffect(() => {\n window.addEventListener(\"online\", goOnline)\n window.addEventListener(\"offline\", goOffline)\n return () => {\n window.removeEventListener(\"online\", goOnline)\n window.removeEventListener(\"offline\", goOffline)\n }\n }, [])\n\n return online\n}\n\nexport default useOnlineStatus","import React, {useCallback, useEffect, useState} from \"react\";\nimport {Message} from \"../../model/ui\";\nimport \"./popMessage.scss\"\nimport {useSwipeable} from \"react-swipeable\";\nimport {usePopMessageContext} from \"../../context/popMessageContext\";\n\ntype PopMessageProps = {\n message: Message\n}\n\nconst PopMessage: React.FC = ({message}) => {\n\n const {dismiss} = usePopMessageContext()\n\n const [classes, setClasses] = useState(`pop-message${message.timeout ? \" timeout\" : \"\"}`)\n const [styles, setStyles] = useState({})\n const [timeoutId, setTimeoutId] = useState()\n\n\n const timeoutCallback = useCallback(() => {\n dismiss(message.id)\n if (timeoutId) {\n clearTimeout(timeoutId)\n setTimeoutId(undefined)\n }\n }, [timeoutId, message.id, dismiss])\n\n\n const handleDismiss = useCallback(() => {\n setClasses(`pop-message${message.timeout ? \" timeout\" : \"\"} hide`)\n setTimeout(timeoutCallback, 150)\n\n }, [timeoutCallback, message.timeout])\n\n const swipeHandlers = useSwipeable({\n onSwipedRight: () => {\n if (message.dismissible) {\n setClasses(`pop-message${message.timeout ? \" timeout\" : \"\"} hide slide-right`)\n setTimeout(timeoutCallback, 150)\n }\n }\n })\n\n useEffect(() => {\n if (message.timeout) {\n setStyles({\"--length-timeout\": message.timeout} as React.CSSProperties)\n setTimeoutId(setTimeout(handleDismiss, message.timeout))\n }\n return () => {\n if (timeoutId) {\n clearTimeout(timeoutId)\n setTimeoutId(undefined)\n }\n }\n }, /* eslint-disable react-hooks/exhaustive-deps */[])\n\n const renderActionButton = useCallback((): JSX.Element | null => {\n if (!message.button) {\n return null;\n }\n return ()\n }, [message])\n\n const renderDismissButton = useCallback((): JSX.Element | null => {\n if (!message.dismissible) {\n return null;\n }\n return ()\n }, [message])\n\n return (\n
\n {message.icon && }\n {message.text}\n {renderActionButton()}\n {renderDismissButton()}\n
\n )\n}\n\nexport default PopMessage","import React from \"react\";\nimport PopMessage from \"./popMessage\";\nimport \"./popMessages.scss\"\nimport {usePopMessageContext} from \"../../context/popMessageContext\";\n\nconst PopMessages: React.FC = () => {\n const {messages} = usePopMessageContext()\n if (messages.length === 0) {\n return null\n }\n return (\n
\n {messages && messages.filter(m=>!m.dismissed).map(m=>)}\n
\n )\n}\n\nexport default PopMessages","import React, {createContext, useContext} from \"react\";\nimport usePopMessages from \"../hooks/usePopMessages\";\nimport {CreateMessageOptions, Message, MessageOptions} from \"../model/ui\";\nimport PopMessages from \"../components/layout/popMessages\";\n\ntype PopMessageContextProps = {\n messages: Array\n pop: (message: CreateMessageOptions) => void\n dismiss: (id: number) => void\n}\n\nconst PopMessageContext = createContext(undefined)\n\ntype PopMessageProviderProps = {\n options?: MessageOptions\n}\n\nexport const PopMessageProvider: React.FC = ({options, children}) => {\n const {messages, popMessage, dismissMessage} = usePopMessages()\n\n const pop = (message: CreateMessageOptions) => {\n popMessage({\n id: Date.now() * Math.random(),\n severity: \"INFO\",\n dismissed: false,\n dismissible: true,\n timestamp: Date.now(),\n ...options,\n ...message\n })\n }\n\n const dismiss = (id: number) => {\n dismissMessage(id)\n }\n\n return (\n \n {children}\n \n \n )\n\n}\n\nexport const usePopMessageContext = (): PopMessageContextProps => {\n const context = useContext(PopMessageContext)\n if (context === undefined) {\n throw new Error(\"usePopMessageContext must be within PopMessageContext\")\n }\n return context\n}\n\nexport const usePop = () => usePopMessageContext().pop","import React, {useEffect, useRef, useState} from \"react\";\nimport {GalleryEntry} from \"../../model/gallery\";\nimport \"./modalImage.scss\"\nimport Progress from \"../progress\";\nimport {useAppSelector} from \"../../reducer/hooks\";\nimport {selectCollapsed} from \"../../reducer/gallerySlice\";\nimport ModalNavButton from \"./modalNav\";\nimport useOnlineStatus from \"../../hooks/useOnlineStatus\";\nimport {ModalEventHandler} from \"./modal\";\nimport {usePop} from \"../../context/popMessageContext\";\n\ntype ModalImageProps = {\n entry: GalleryEntry|null,\n handleNext: ModalEventHandler,\n handlePrevious: ModalEventHandler,\n handleClose: ModalEventHandler,\n}\n\n\nconst ModalImage: React.FC = ({entry, handleNext, handlePrevious, handleClose}) => {\n const [toggled, setToggled] = useState(false)\n const [loaded, setLoaded] = useState(false)\n const imgRef = useRef(null)\n const collapsed = useAppSelector(selectCollapsed)\n const onlineStatus = useOnlineStatus()\n const pop = usePop()\n\n const getHandler = () => {\n return collapsed ? handleClose : ()=>{}\n }\n\n const toggleImage = (e: React.MouseEvent) => {\n e.preventDefault()\n setToggled(!toggled)\n setLoaded(false)\n }\n\n const loadHandler = () => {\n setLoaded(true)\n }\n\n const errorHandler = ()=>{\n if (!onlineStatus) {\n pop({\n severity: \"ERROR\",\n text: \"Nincs kapcsolat\",\n icon: \"fa fa-unlink\",\n timeout: 7000\n })\n } else {\n pop({\n severity: \"ERROR\",\n text: \"Kép nem található\",\n timeout: 7000\n })\n }\n if (!toggled) {\n handleClose()\n } else {\n setToggled(false)\n }\n }\n\n useEffect(() => {\n if (imgRef.current?.complete) return\n setLoaded(false)\n setToggled(false)\n }, [entry, imgRef])\n\n useEffect(() => {\n const img = imgRef.current\n if (img == null) return\n img.style.aspectRatio = `${img.naturalWidth}/${img.naturalHeight}`\n }, [imgRef])\n\n if (!entry) return null\n\n return (\n
\n {loaded && }\n {entry.alt}\n {loaded && }\n {!loaded && }\n {loaded && (\n
\n {entry.toggledPath && (\n
\n \n
\n )}\n
\n {entry.note && {entry.noteTitle}}{entry.title}\n {entry.desc}\n
\n {entry.logo && (\n
\n {entry.logo}/\n
\n )}\n
\n )}\n
\n )\n}\n\nexport default ModalImage","import React, {useEffect, useState} from \"react\";\nimport {GalleryEntry} from \"../../model/gallery\";\nimport {useAppDispatch, useAppSelector} from \"../../reducer/hooks\";\nimport {closeEntry, nextEntry, previousEntry, selectOpenedEntry} from \"../../reducer/gallerySlice\";\nimport ModalImage from \"./modalImage\";\nimport \"./modal.scss\"\nimport {useSwipeable} from \"react-swipeable\";\nimport {useKeyboard} from \"react-keyboard-event\";\n\ntype ModalEvent = React.MouseEvent | React.KeyboardEvent | React.TouchEvent\nexport type ModalEventHandler = (e?: ModalEvent) => void\n\nconst Modal: React.FC = () => {\n const entry: GalleryEntry | null = useAppSelector(selectOpenedEntry)\n const [render, setRender] = useState(false)\n\n const dispatch = useAppDispatch()\n const [modalClasses, setModalClasses] = useState(\"modal hide\")\n\n useKeyboard({\n listeners: {\n \"ArrowLeft\": () => dispatch(previousEntry()),\n \"ArrowRight\": () => dispatch(nextEntry()),\n \"Escape\": () => dispatch(closeEntry())\n },\n shouldListen: render\n })\n\n const swipeHandlers = useSwipeable({\n preventDefaultTouchmoveEvent: true,\n onSwiped: (eventData => {\n if (eventData.dir === \"Right\") {\n dispatch(previousEntry())\n } else if (eventData.dir === \"Left\") {\n dispatch(nextEntry())\n }\n }),\n onSwiping: (eventData) => {\n if (eventData.dir === \"Right\") {\n setModalClasses(\"modal tilt-right\")\n } else if (eventData.dir === \"Left\") {\n setModalClasses(\"modal tilt-left\")\n } else {\n setModalClasses(\"modal\")\n }\n }\n })\n\n const handleNext: ModalEventHandler = (e?: ModalEvent) => {\n e?.preventDefault()\n dispatch(nextEntry())\n }\n\n const handlePrevious: ModalEventHandler = (e?: ModalEvent) => {\n e?.preventDefault()\n dispatch(previousEntry())\n }\n\n const handleClose: ModalEventHandler = (e?: ModalEvent) => {\n e?.preventDefault()\n dispatch(closeEntry())\n }\n\n useEffect(() => {\n if (entry != null) {\n document.body.classList.add(\"modal-open\")\n setModalClasses(\"modal\")\n setRender(true)\n } else {\n document.body.classList.remove(\"modal-open\")\n setModalClasses(\"modal hide\")\n setTimeout(() => setRender(false), 350)\n }\n }, [entry])\n\n if (!render) {\n return null\n }\n\n\n return (\n
\n
\n \n
\n )\n\n\n}\n\nexport default Modal","import {useEffect, useState} from \"react\";\nimport useOnlineStatus from \"./useOnlineStatus\";\nimport {usePop} from \"../context/popMessageContext\";\n\nconst useOfflinePopMessage = (): boolean => {\n const onlineStatus = useOnlineStatus()\n const pop = usePop()\n const [wasOffline, setWasOffline] = useState(false)\n\n useEffect(()=>{\n if (!onlineStatus && !wasOffline) {\n pop({\n severity: \"ERROR\",\n text: \"Kapcsolat megszakadt\",\n icon: \"fa fa-unlink\"\n })\n setWasOffline(true)\n }\n if (onlineStatus && wasOffline) {\n pop({\n severity: \"SUCCESS\",\n text: \"Kapcsolat helyreállt\",\n icon: \"fa fa-link\"\n })\n setWasOffline(false)\n }\n return () => {\n setWasOffline(false)\n }\n }, /* eslint-disable react-hooks/exhaustive-deps */[onlineStatus])\n\n return !onlineStatus\n}\n\nexport default useOfflinePopMessage","import {useEffect} from \"react\";\nimport {isMobile, isTablet, isDesktop, useMobileOrientation} from \"react-device-detect\";\n\n\nconst useDeviceType = () => {\n\n const {isPortrait, isLandscape, orientation} = useMobileOrientation()\n\n useEffect(() => {\n if (isTablet) {\n document.body.classList.add(\"tablet\")\n } else if (isMobile) {\n document.body.classList.add(\"mobile\")\n }\n }, [])\n return {isMobile, isTablet, isDesktop, isPortrait, isLandscape, orientation}\n}\n\nexport default useDeviceType","import React, {useEffect} from 'react';\nimport Header from \"./components/layout/header\";\nimport Footer from \"./components/layout/footer\";\nimport {activateMenu, setTotalCount} from \"./reducer/gallerySlice\";\nimport {useAppDispatch} from \"./reducer/hooks\";\nimport Main from \"./components/layout/main\";\nimport Loader from \"./components/layout/loader\";\nimport {useGetGalleries} from './reducer/galleriesApi';\nimport Modal from \"./components/gallery/modal\";\nimport useOfflinePopMessage from \"./hooks/useOfflinePopMessage\";\nimport useDeviceType from \"./hooks/useDeviceType\";\n\n\nconst App: React.FC = () => {\n useOfflinePopMessage()\n useDeviceType()\n const dispatch = useAppDispatch()\n const {data, isLoading, error} = useGetGalleries()\n\n useEffect(() => {\n if (!isLoading && data) {\n dispatch(setTotalCount(data.galleries.flatMap(g => g.collections).flatMap(c => c.entries).length))\n dispatch(activateMenu({gallery: data.galleries[0]}))\n }\n if (error) {\n console.error(error)\n }\n }, [dispatch, isLoading, data, error])\n\n\n return (\n \n {data && (\n <>\n
\n
\n