@jekrch/react-viewport-lightbox 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -21
- package/dist/index.cjs +190 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -6
- package/dist/index.d.ts +50 -6
- package/dist/index.js +190 -34
- package/dist/index.js.map +1 -1
- package/dist/styles.css +33 -0
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/math.ts","../src/hooks/useImageZoomPan.ts","../src/hooks/useSlideNavigation.ts","../src/hooks/useGestureHandler.ts","../src/hooks/useBarMeasure.ts","../src/hooks/useBodyScrollLock.ts","../src/hooks/useFocusTrap.ts","../src/components/icons.tsx","../src/components/cx.ts","../src/components/NavButton.tsx","../src/components/ImageViewer.tsx"],"names":["clampTranslate","useRef","useState","useCallback","useLayoutEffect","useEffect","sg","jsx","jsxs"],"mappings":";;;;;;AAeO,SAAS,cAAA,CACd,CAAA,EACA,CAAA,EACA,KAAA,EACA,UACA,QAAA,EAC0B;AAC1B,EAAA,IAAI,SAAS,CAAA,EAAG,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAE;AACpC,EAAA,MAAM,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,OAAM,GAAI,QAAA;AACxC,EAAA,IAAI,KAAA,KAAU,KAAK,KAAA,KAAU,CAAA,SAAU,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE;AAEpD,EAAA,MAAM,WAAA,GAAe,QAAQ,KAAA,GAAS,CAAA;AACtC,EAAA,MAAM,WAAA,GAAe,QAAQ,KAAA,GAAS,CAAA;AACtC,EAAA,MAAM,OAAA,GAAU,SAAS,KAAA,GAAQ,CAAA;AACjC,EAAA,MAAM,OAAA,GAAU,SAAS,MAAA,GAAS,CAAA;AAElC,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,cAAc,OAAO,CAAA;AAC9C,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,cAAc,OAAO,CAAA;AAE9C,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,KAAK,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,CAAC,CAAC,CAAA;AAAA,IACpC,CAAA,EAAG,KAAK,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,CAAC,CAAC;AAAA,GACtC;AACF;AAsBO,SAAS,qBAAA,CAAsB;AAAA,EACpC,MAAA;AAAA,EACA,SAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA,GAAoB,IAAA;AAAA,EACpB,iBAAA,GAAoB;AACtB,CAAA,EAAkC;AAChC,EAAA,MAAM,QAAA,GAAW,KAAK,GAAA,CAAI,MAAM,IAAI,IAAA,CAAK,GAAA,CAAI,WAAW,CAAC,CAAA;AACzD,EAAA,MAAM,YAAY,aAAA,GAAgB,iBAAA;AAClC,EAAA,MAAM,YAAY,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA,GAAI,aAAa,QAAA,GAAW,iBAAA;AAE7D,EAAA,IAAI,MAAA,GAAS,CAAA,IAAK,OAAA,IAAW,SAAA,EAAW,OAAO,MAAA;AAC/C,EAAA,IAAI,MAAA,GAAS,CAAA,IAAK,OAAA,IAAW,SAAA,EAAW,OAAO,MAAA;AAC/C,EAAA,OAAO,MAAA;AACT;;;ACzEA,IAAM,SAAA,GAAY;AAClB,IAAM,SAAA,GAAY;AAqCX,SAAS,eAAA,CACd,aAAA,EACA,YAAA,EAEA,OAAA,GAAU,IAAA,EACS;AACnB,EAAA,MAAM,MAAA,GAAS,OAAyB,IAAI,CAAA;AAC5C,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,CAAC,CAAA;AAClD,EAAA,MAAM,YAAA,GAAe,OAAuB,EAAE,KAAA,EAAO,GAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA;AACpE,EAAA,MAAM,cAAc,MAAA,CAA0C,EAAE,OAAO,CAAA,EAAG,MAAA,EAAQ,GAAG,CAAA;AAIrF,EAAA,MAAM,cAAA,GAAiB,WAAA;AAAA,IACrB,CAAC,CAAA,EAAmB,OAAA,GAAU,KAAA,KAAU;AACtC,MAAA,MAAM,UAAU,aAAA,CAAc,OAAA;AAC9B,MAAA,IAAI,CAAC,OAAA,EAAS;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,UAAA,GAAa,OAAA,GAAU,yBAAA,GAA4B,MAAA;AAEjE,MAAA,IAAI,CAAA,CAAE,SAAS,CAAA,EAAG;AAChB,QAAA,OAAA,CAAQ,MAAM,SAAA,GAAY,MAAA;AAC1B,QAAA,OAAA,CAAQ,MAAM,QAAA,GAAW,EAAA;AACzB,QAAA,OAAA,CAAQ,MAAM,KAAA,GAAQ,EAAA;AACtB,QAAA,OAAA,CAAQ,MAAM,MAAA,GAAS,EAAA;AACvB,QAAA,OAAA,CAAQ,MAAM,eAAA,GAAkB,EAAA;AAChC,QAAA,OAAA,CAAQ,MAAM,MAAA,GAAS,EAAA;AAAA,MACzB,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,KAAA,CAAM,SAAA,GAAY,CAAA,MAAA,EAAS,CAAA,CAAE,KAAK,CAAA,YAAA,EAAe,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,KAAK,CAAA,IAAA,EAAO,CAAA,CAAE,CAAA,GAAI,EAAE,KAAK,CAAA,GAAA,CAAA;AAC1F,QAAA,OAAA,CAAQ,MAAM,QAAA,GAAW,UAAA;AACzB,QAAA,OAAA,CAAQ,MAAM,KAAA,GAAQ,GAAA;AACtB,QAAA,OAAA,CAAQ,MAAM,MAAA,GAAS,IAAA;AACvB,QAAA,OAAA,CAAQ,MAAM,eAAA,GAAkB,OAAA;AAChC,QAAA,OAAA,CAAQ,MAAM,MAAA,GAAS,MAAA;AAAA,MACzB;AAGA,MAAA,eAAA,CAAgB,EAAE,KAAK,CAAA;AAAA,IACzB,CAAA;AAAA,IACA,CAAC,aAAa;AAAA,GAChB;AAEA,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,CAAC,CAAA,EAAmB,OAAA,GAAU,KAAA,KAAU;AACtC,MAAA,YAAA,CAAa,OAAA,GAAU,CAAA;AACvB,MAAA,cAAA,CAAe,GAAG,OAAO,CAAA;AACzB,MAAA,eAAA,CAAgB,EAAE,KAAK,CAAA;AAAA,IACzB,CAAA;AAAA,IACA,CAAC,cAAc;AAAA,GACjB;AAEA,EAAA,MAAM,cAAA,GAAiB,YAAY,MAAM;AACvC,IAAA,YAAA,CAAa,EAAE,OAAO,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,IAAK,IAAI,CAAA;AAAA,EAC7C,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAEjB,EAAA,MAAM,eAAA,GAAkB,YAAY,MAAM;AACxC,IAAA,MAAM,MAAM,MAAA,CAAO,OAAA;AACnB,IAAA,IAAI,CAAC,GAAA,EAAK;AACV,IAAA,WAAA,CAAY,UAAU,EAAE,KAAA,EAAO,IAAI,WAAA,EAAa,MAAA,EAAQ,IAAI,YAAA,EAAa;AAAA,EAC3E,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAMA,eAAAA,GAAiB,WAAA;AAAA,IACrB,CAAC,GAAW,CAAA,EAAW,KAAA,KACrB,eAAmB,CAAA,EAAG,CAAA,EAAG,KAAA,EAAO,WAAA,CAAY,OAAA,EAAS;AAAA,MACnD,OAAO,MAAA,CAAO,UAAA;AAAA,MACd,QAAQ,MAAA,CAAO;AAAA,KAChB,CAAA;AAAA,IACH;AAAC,GACH;AAIA,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,MAAM,UAAU,aAAA,CAAc,OAAA;AAC9B,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,OAAA,CAAQ,MAAM,UAAA,GAAa,MAAA;AAC3B,MAAA,OAAA,CAAQ,MAAM,SAAA,GAAY,MAAA;AAC1B,MAAA,OAAA,CAAQ,MAAM,QAAA,GAAW,EAAA;AACzB,MAAA,OAAA,CAAQ,MAAM,KAAA,GAAQ,EAAA;AACtB,MAAA,OAAA,CAAQ,MAAM,MAAA,GAAS,EAAA;AACvB,MAAA,OAAA,CAAQ,MAAM,eAAA,GAAkB,EAAA;AAChC,MAAA,OAAA,CAAQ,MAAM,MAAA,GAAS,EAAA;AAAA,IACzB;AACA,IAAA,YAAA,CAAa,UAAU,EAAE,KAAA,EAAO,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAE;AAAA,EAChD,CAAA,EAAG,CAAC,YAAA,EAAc,aAAa,CAAC,CAAA;AAEhC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,eAAA,CAAgB,CAAC,CAAA;AAAA,EACnB,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAIjB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,MAAM,UAAU,aAAA,CAAc,OAAA;AAC9B,IAAA,IAAI,CAAC,OAAA,EAAS;AAEd,IAAA,MAAM,WAAA,GAAc,CAAC,CAAA,KAAkB;AACrC,MAAA,CAAA,CAAE,cAAA,EAAe;AAGjB,MAAA,IAAI,WAAA,CAAY,OAAA,CAAQ,KAAA,KAAU,CAAA,EAAG;AACnC,QAAA,MAAM,MAAM,MAAA,CAAO,OAAA;AACnB,QAAA,IAAI,GAAA,cAAiB,OAAA,GAAU,EAAE,OAAO,GAAA,CAAI,WAAA,EAAa,MAAA,EAAQ,GAAA,CAAI,YAAA,EAAa;AAAA,MACpF;AAEA,MAAA,MAAM,IAAI,YAAA,CAAa,OAAA;AAEvB,MAAA,IAAI,KAAK,CAAA,CAAE,MAAA;AACX,MAAA,IAAI,CAAA,CAAE,SAAA,KAAc,CAAA,EAAG,EAAA,IAAM,EAAA;AAC7B,MAAA,IAAI,CAAA,CAAE,SAAA,KAAc,CAAA,EAAG,EAAA,IAAM,GAAA;AAE7B,MAAA,MAAM,UAAA,GAAa,KAAK,GAAA,CAAI,IAAA,EAAM,KAAK,GAAA,CAAI,GAAA,EAAK,EAAE,CAAC,CAAA;AACnD,MAAA,MAAM,IAAA,GAAO,EAAE,UAAA,GAAa,GAAA,CAAA,GAAO,IAAA;AACnC,MAAA,MAAM,SAAS,CAAA,GAAI,IAAA;AAEnB,MAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,IAAA,CAAK,IAAI,SAAA,EAAW,CAAA,CAAE,KAAA,GAAQ,MAAM,CAAC,CAAA;AAC3E,MAAA,MAAM,OAAA,GAAU,SAAA,IAAa,CAAA,GAAI,EAAE,GAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE,GAAIA,eAAAA,CAAe,CAAA,CAAE,CAAA,EAAG,CAAA,CAAE,GAAG,SAAS,CAAA;AACpF,MAAA,YAAA,CAAa,EAAE,KAAA,EAAO,SAAA,EAAW,GAAG,SAAS,CAAA;AAAA,IAC/C,CAAA;AAEA,IAAA,OAAA,CAAQ,iBAAiB,OAAA,EAAS,WAAA,EAAa,EAAE,OAAA,EAAS,OAAO,CAAA;AACjE,IAAA,OAAO,MAAM,OAAA,CAAQ,mBAAA,CAAoB,OAAA,EAAS,WAAW,CAAA;AAAA,EAC/D,GAAG,CAAC,aAAA,EAAe,YAAA,EAAcA,eAAAA,EAAgB,OAAO,CAAC,CAAA;AAIzD,EAAA,MAAM,iBAAA,GAAoB,WAAA;AAAA,IACxB,CAAC,CAAA,KAAwB;AACvB,MAAA,IAAI,CAAC,OAAA,EAAS;AACd,MAAA,CAAA,CAAE,eAAA,EAAgB;AAGlB,MAAA,IAAI,WAAA,CAAY,OAAA,CAAQ,KAAA,KAAU,CAAA,EAAG;AACnC,QAAA,MAAM,MAAM,MAAA,CAAO,OAAA;AACnB,QAAA,IAAI,GAAA,cAAiB,OAAA,GAAU,EAAE,OAAO,GAAA,CAAI,WAAA,EAAa,MAAA,EAAQ,GAAA,CAAI,YAAA,EAAa;AAAA,MACpF;AAEA,MAAA,IAAI,YAAA,CAAa,OAAA,CAAQ,KAAA,GAAQ,CAAA,EAAG;AAClC,QAAA,cAAA,EAAe;AAAA,MACjB,CAAA,MAAO;AACL,QAAA,YAAA,CAAa,EAAE,OAAO,GAAA,EAAK,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,IAAK,IAAI,CAAA;AAAA,MAC/C;AAAA,IACF,CAAA;AAAA,IACA,CAAC,cAAA,EAAgB,YAAA,EAAc,OAAO;AAAA,GACxC;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,YAAA;AAAA,IACA,UAAU,YAAA,GAAe,CAAA;AAAA,IACzB,YAAA;AAAA,IACA,WAAA;AAAA,IACA,cAAA;AAAA,IACA,YAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA,EAAAA,eAAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACF;AACF;AChLO,SAAS,kBAAA,CACd,KAAA,EACA,YAAA,EACA,UAAA,EACA,YAAA,EACsB;AACtB,EAAA,MAAM,aAAA,GAAgBC,OAAuB,IAAI,CAAA;AACjD,EAAA,MAAM,cAAA,GAAiBA,OAAO,CAAC,CAAA;AAC/B,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIC,SAAS,CAAC,CAAA;AAChD,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIA,SAAS,KAAK,CAAA;AAC1D,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIA,SAAS,KAAK,CAAA;AACpD,EAAA,MAAM,aAAA,GAAgBD,OAAO,KAAK,CAAA;AAElC,EAAA,MAAM,UAAU,YAAA,GAAe,CAAA;AAC/B,EAAA,MAAM,OAAA,GAAU,YAAA,GAAe,KAAA,CAAM,MAAA,GAAS,CAAA;AAE9C,EAAA,MAAM,gBAAA,GAAmBE,WAAAA,CAAY,CAAC,MAAA,EAAgB,UAAU,KAAA,KAAU;AACxE,IAAA,cAAA,CAAe,OAAA,GAAU,MAAA;AACzB,IAAA,MAAM,QAAQ,aAAA,CAAc,OAAA;AAC5B,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,KAAA,CAAM,KAAA,CAAM,UAAA,GAAa,OAAA,GAAU,4CAAA,GAA+C,MAAA;AAClF,MAAA,KAAA,CAAM,KAAA,CAAM,SAAA,GAAY,CAAA,WAAA,EAAc,MAAM,CAAA,GAAA,CAAA;AAAA,IAC9C;AACA,IAAA,cAAA,CAAe,MAAM,CAAA;AAAA,EACvB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,QAAA,GAAWA,YAAY,MAAM;AACjC,IAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,IAAA,gBAAA,CAAiB,GAAG,IAAI,CAAA;AAExB,IAAA,MAAM,QAAQ,aAAA,CAAc,OAAA;AAC5B,IAAA,IAAI,IAAA,GAAO,KAAA;AACX,IAAA,MAAM,QAAQ,MAAM;AAClB,MAAA,IAAI,IAAA,EAAM;AACV,MAAA,IAAA,GAAO,IAAA;AACP,MAAA,KAAA,EAAO,mBAAA,CAAoB,iBAAiB,KAAK,CAAA;AACjD,MAAA,iBAAA,CAAkB,KAAK,CAAA;AACvB,MAAA,cAAA,CAAe,KAAK,CAAA;AAAA,IACtB,CAAA;AACA,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,KAAA,CAAM,iBAAiB,eAAA,EAAiB,KAAA,EAAO,EAAE,IAAA,EAAM,MAAM,CAAA;AAC7D,MAAA,UAAA,CAAW,OAAO,GAAG,CAAA;AAAA,IACvB;AAAA,EACF,CAAA,EAAG,CAAC,gBAAgB,CAAC,CAAA;AAErB,EAAA,MAAM,QAAA,GAAWF,OAAO,IAAI,CAAA;AAE5B,EAAA,MAAM,WAAA,GAAcE,WAAAA;AAAA,IAClB,CAAC,SAAA,KAA+B;AAC9B,MAAA,IAAI,aAAA,CAAc,OAAA,IAAW,CAAC,QAAA,CAAS,OAAA,EAAS;AAChD,MAAA,aAAA,CAAc,OAAA,GAAU,IAAA;AACxB,MAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AAEnB,MAAA,MAAM,KAAK,MAAA,CAAO,UAAA;AAClB,MAAA,MAAM,YAAA,GAAe,SAAA,KAAc,MAAA,GAAS,EAAA,GAAK,CAAC,EAAA;AAClD,MAAA,cAAA,CAAe,IAAI,CAAA;AACnB,MAAA,iBAAA,CAAkB,IAAI,CAAA;AAGtB,MAAA,YAAA,GAAe,SAAS,CAAA;AAExB,MAAA,qBAAA,CAAsB,MAAM;AAC1B,QAAA,gBAAA,CAAiB,cAAc,IAAI,CAAA;AAEnC,QAAA,MAAM,QAAQ,aAAA,CAAc,OAAA;AAC5B,QAAA,IAAI,OAAA,GAAU,KAAA;AAEd,QAAA,MAAM,UAAU,MAAM;AACpB,UAAA,IAAI,OAAA,EAAS;AACb,UAAA,OAAA,GAAU,IAAA;AACV,UAAA,KAAA,EAAO,mBAAA,CAAoB,iBAAiB,eAAe,CAAA;AAE3D,UAAA,MAAM,QAAA,GAAW,SAAA,KAAc,MAAA,GAAS,YAAA,GAAe,IAAI,YAAA,GAAe,CAAA;AAC1E,UAAA,IAAI,QAAA,GAAW,CAAA,IAAK,QAAA,IAAY,KAAA,CAAM,MAAA,EAAQ;AAC5C,YAAA,aAAA,CAAc,OAAA,GAAU,KAAA;AACxB,YAAA;AAAA,UACF;AAEA,UAAA,MAAM,OAAA,GAAU,MAAM,QAAQ,CAAA;AAC9B,UAAA,MAAM,OAAA,GAAU,IAAI,KAAA,EAAM;AAC1B,UAAA,OAAA,CAAQ,MAAM,OAAA,CAAQ,GAAA;AAEtB,UAAA,MAAM,UAAA,GAAa,MAAM,UAAA,CAAW,QAAQ,CAAA;AAG5C,UAAA,MAAM,OAAA,GAAU,UAAA,CAAW,UAAA,EAAY,GAAG,CAAA;AAC1C,UAAA,OAAA,CACG,MAAA,EAAO,CACP,IAAA,CAAK,MAAM;AACV,YAAA,YAAA,CAAa,OAAO,CAAA;AACpB,YAAA,UAAA,EAAW;AAAA,UACb,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AACX,YAAA,YAAA,CAAa,OAAO,CAAA;AACpB,YAAA,UAAA,EAAW;AAAA,UACb,CAAC,CAAA;AAAA,QACL,CAAA;AAEA,QAAA,MAAM,eAAA,GAAkB,MAAM,OAAA,EAAQ;AACtC,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,KAAA,CAAM,iBAAiB,eAAA,EAAiB,eAAA,EAAiB,EAAE,IAAA,EAAM,MAAM,CAAA;AACvE,UAAA,UAAA,CAAW,SAAS,GAAG,CAAA;AAAA,QACzB;AAAA,MACF,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,CAAC,gBAAA,EAAkB,YAAA,EAAc,KAAA,EAAO,YAAY,YAAY;AAAA,GAClE;AAEA,EAAA,MAAM,YAAA,GAAeA,WAAAA;AAAA,IACnB,CAAC,gBAAA,KAA6B;AAC5B,MAAA,MAAM,SAAS,qBAAA,CAAsB;AAAA,QACnC,QAAQ,cAAA,CAAe,OAAA;AAAA,QACvB,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,GAAI,gBAAA;AAAA,QACxB,eAAe,MAAA,CAAO,UAAA;AAAA,QACtB,OAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,IAAI,MAAA,KAAW,MAAA,EAAQ,WAAA,CAAY,MAAM,CAAA;AAAA,WAAA,IAChC,MAAA,KAAW,MAAA,EAAQ,WAAA,CAAY,MAAM,CAAA;AAAA,WACzC,QAAA,EAAS;AAAA,IAChB,CAAA;AAAA,IACA,CAAC,OAAA,EAAS,OAAA,EAAS,WAAA,EAAa,QAAQ;AAAA,GAC1C;AAIA,EAAAC,gBAAgB,MAAM;AACpB,IAAA,MAAM,QAAQ,aAAA,CAAc,OAAA;AAC5B,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,KAAA,CAAM,MAAM,UAAA,GAAa,MAAA;AACzB,MAAA,KAAA,CAAM,YAAA;AACN,MAAA,KAAA,CAAM,MAAM,SAAA,GAAY,iBAAA;AAAA,IAC1B;AACA,IAAA,cAAA,CAAe,OAAA,GAAU,CAAA;AACzB,IAAA,aAAA,CAAc,OAAA,GAAU,KAAA;AAAA,EAC1B,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAGjB,EAAAC,UAAU,MAAM;AACd,IAAA,cAAA,CAAe,CAAC,CAAA;AAChB,IAAA,iBAAA,CAAkB,KAAK,CAAA;AACvB,IAAA,cAAA,CAAe,KAAK,CAAA;AAEpB,IAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,EACrB,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAEjB,EAAA,OAAO;AAAA,IACL,aAAA;AAAA,IACA,WAAA;AAAA,IACA,cAAA;AAAA,IACA,WAAA;AAAA,IACA,cAAA;AAAA,IACA,aAAA;AAAA,IACA,gBAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF;AACF;ACnJO,SAAS,kBACd,OAAA,EACA,KAAA,EACA,OAAA,EACA,OAAA,EAEA,cAAc,IAAA,EACG;AACjB,EAAA,MAAM,EAAE,YAAA,EAAc,cAAA,EAAAL,iBAAgB,YAAA,EAAc,cAAA,EAAgB,gBAAe,GAAI,OAAA;AACvF,EAAA,MAAM,EAAE,gBAAA,EAAkB,YAAA,EAAc,QAAA,EAAU,cAAA,EAAgB,gBAAe,GAAI,KAAA;AAErF,EAAA,MAAM,SAASC,MAAAA,CAAmB;AAAA,IAChC,UAAA,EAAY,KAAA;AAAA,IACZ,YAAA,EAAc,EAAE,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAE;AAAA,IAC3B,cAAA,EAAgB,EAAE,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAE;AAAA,IAC7B,cAAA,EAAgB,IAAA;AAAA,IAChB,eAAA,EAAiB,CAAA;AAAA,IACjB,aAAA,EAAe,IAAA;AAAA,IACf,YAAA,EAAc;AAAA,GACf,CAAA;AAED,EAAA,MAAM,WAAWA,MAAAA,CAAqB;AAAA,IACpC,MAAA,EAAQ,KAAA;AAAA,IACR,MAAA,EAAQ,CAAA;AAAA,IACR,MAAA,EAAQ,CAAA;AAAA,IACR,SAAA,EAAW,CAAA;AAAA,IACX,MAAA,EAAQ,KAAA;AAAA,IACR,QAAA,EAAU;AAAA,GACX,CAAA;AAGD,EAAA,MAAM,aAAaA,MAAAA,CAA+C;AAAA,IAChE,IAAA,EAAM,CAAA;AAAA,IACN,CAAA,EAAG,CAAA;AAAA,IACH,CAAA,EAAG;AAAA,GACJ,CAAA;AAID,EAAA,MAAM,UAAA,GAAaE,WAAAA;AAAA,IACjB,CAAC,GAAW,CAAA,KAAc;AACxB,MAAA,cAAA,CAAe,IAAI,CAAA;AACnB,MAAA,MAAM,KAAK,QAAA,CAAS,OAAA;AACpB,MAAA,EAAA,CAAG,MAAA,GAAS,IAAA;AACZ,MAAA,EAAA,CAAG,MAAA,GAAS,CAAA;AACZ,MAAA,EAAA,CAAG,MAAA,GAAS,CAAA;AACZ,MAAA,EAAA,CAAG,SAAA,GAAY,KAAK,GAAA,EAAI;AACxB,MAAA,EAAA,CAAG,MAAA,GAAS,KAAA;AACZ,MAAA,EAAA,CAAG,QAAA,GAAW,KAAA;AAAA,IAChB,CAAA;AAAA,IACA,CAAC,cAAc;AAAA,GACjB;AAEA,EAAA,MAAM,WAAA,GAAcA,WAAAA;AAAA,IAClB,CAAC,OAAA,EAAiB,OAAA,EAAiB,aAAA,EAAuB,SAAA,KAAsB;AAC9E,MAAA,MAAM,KAAK,QAAA,CAAS,OAAA;AACpB,MAAA,IAAI,CAAC,EAAA,CAAG,MAAA,IAAU,EAAA,CAAG,QAAA,EAAU;AAE/B,MAAA,MAAM,EAAA,GAAK,UAAU,EAAA,CAAG,MAAA;AACxB,MAAA,MAAM,EAAA,GAAK,UAAU,EAAA,CAAG,MAAA;AAExB,MAAA,IAAI,CAAC,GAAG,MAAA,EAAQ;AACd,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA;AACzB,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA;AACzB,QAAA,IAAI,KAAA,GAAQ,aAAA,IAAiB,KAAA,GAAQ,aAAA,EAAe;AACpD,QAAA,IAAI,KAAA,GAAQ,QAAQ,SAAA,EAAW;AAC7B,UAAA,EAAA,CAAG,QAAA,GAAW,IAAA;AACd,UAAA;AAAA,QACF;AACA,QAAA,EAAA,CAAG,MAAA,GAAS,IAAA;AAAA,MACd;AAEA,MAAA,IAAI,MAAA,GAAS,EAAA;AACb,MAAA,IAAK,SAAS,CAAA,IAAK,CAAC,WAAa,MAAA,GAAS,CAAA,IAAK,CAAC,OAAA,EAAU;AACxD,QAAA,MAAA,IAAU,GAAA;AAAA,MACZ;AACA,MAAA,gBAAA,CAAiB,MAAM,CAAA;AAAA,IACzB,CAAA;AAAA,IACA,CAAC,OAAA,EAAS,OAAA,EAAS,gBAAgB;AAAA,GACrC;AAEA,EAAA,MAAM,QAAA,GAAWA,WAAAA;AAAA,IACf,CAAC,YAAA,KAA0B;AACzB,MAAA,MAAM,KAAK,QAAA,CAAS,OAAA;AACpB,MAAA,IAAI,GAAG,MAAA,IAAU,EAAA,CAAG,UAAU,CAAC,EAAA,CAAG,YAAY,YAAA,EAAc;AAC1D,QAAA,MAAM,YAAY,EAAA,CAAG,SAAA;AACrB,QAAA,EAAA,CAAG,MAAA,GAAS,KAAA;AACZ,QAAA,YAAA,CAAa,SAAS,CAAA;AAAA,MACxB,CAAA,MAAO;AACL,QAAA,EAAA,CAAG,MAAA,GAAS,KAAA;AACZ,QAAA,IAAI,cAAA,CAAe,OAAA,KAAY,CAAA,EAAG,cAAA,CAAe,KAAK,CAAA;AAAA,MACxD;AAAA,IACF,CAAA;AAAA,IACA,CAAC,YAAA,EAAc,cAAA,EAAgB,cAAc;AAAA,GAC/C;AAIA,EAAA,MAAM,iBAAA,GAAoBA,WAAAA;AAAA,IACxB,CAAC,CAAA,KAA0B;AACzB,MAAA,IAAI,CAAA,CAAE,gBAAgB,OAAA,EAAS;AAE/B,MAAA,IAAI,YAAA,CAAa,OAAA,CAAQ,KAAA,GAAQ,CAAA,EAAG;AAClC,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,MAAM,IAAI,MAAA,CAAO,OAAA;AACjB,QAAA,CAAA,CAAE,UAAA,GAAa,IAAA;AACf,QAAA,CAAA,CAAE,eAAe,EAAE,CAAA,EAAG,EAAE,OAAA,EAAS,CAAA,EAAG,EAAE,OAAA,EAAQ;AAC9C,QAAA,CAAA,CAAE,cAAA,GAAiB,EAAE,CAAA,EAAG,YAAA,CAAa,QAAQ,CAAA,EAAG,CAAA,EAAG,YAAA,CAAa,OAAA,CAAQ,CAAA,EAAE;AAAA,MAC5E,CAAA,MAAO;AACL,QAAA,UAAA,CAAW,CAAA,CAAE,OAAA,EAAS,CAAA,CAAE,OAAO,CAAA;AAAA,MACjC;AAAA,IACF,CAAA;AAAA,IACA,CAAC,cAAc,UAAU;AAAA,GAC3B;AAEA,EAAA,MAAM,iBAAA,GAAoBA,WAAAA;AAAA,IACxB,CAAC,CAAA,KAA0B;AACzB,MAAA,IAAI,CAAA,CAAE,gBAAgB,OAAA,EAAS;AAE/B,MAAA,MAAM,IAAI,MAAA,CAAO,OAAA;AACjB,MAAA,IAAI,CAAA,CAAE,UAAA,IAAc,YAAA,CAAa,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAClD,QAAA,MAAM,EAAA,GAAK,CAAA,CAAE,OAAA,GAAU,CAAA,CAAE,YAAA,CAAa,CAAA;AACtC,QAAA,MAAM,EAAA,GAAK,CAAA,CAAE,OAAA,GAAU,CAAA,CAAE,YAAA,CAAa,CAAA;AACtC,QAAA,MAAM,IAAI,YAAA,CAAa,OAAA;AACvB,QAAA,MAAM,OAAA,GAAUH,eAAAA,CAAe,CAAA,CAAE,cAAA,CAAe,CAAA,GAAI,EAAA,EAAI,CAAA,CAAE,cAAA,CAAe,CAAA,GAAI,EAAA,EAAI,CAAA,CAAE,KAAK,CAAA;AACxF,QAAA,YAAA,CAAa,EAAE,KAAA,EAAO,CAAA,CAAE,KAAA,EAAO,GAAG,SAAS,CAAA;AAC3C,QAAA;AAAA,MACF;AAGA,MAAA,WAAA,CAAY,CAAA,CAAE,OAAA,EAAS,CAAA,CAAE,OAAA,EAAS,GAAG,CAAC,CAAA;AAAA,IACxC,CAAA;AAAA,IACA,CAAC,YAAA,EAAcA,eAAAA,EAAgB,YAAA,EAAc,WAAW;AAAA,GAC1D;AAEA,EAAA,MAAM,eAAA,GAAkBG,WAAAA;AAAA,IACtB,CAAC,CAAA,KAA0B;AACzB,MAAA,IAAI,CAAA,CAAE,gBAAgB,OAAA,EAAS;AAC/B,MAAA,MAAA,CAAO,QAAQ,UAAA,GAAa,KAAA;AAC5B,MAAA,QAAA,CAAS,IAAI,CAAA;AAAA,IACf,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAIA,EAAA,MAAM,gBAAA,GAAmBA,WAAAA;AAAA,IACvB,CAAC,CAAA,KAAwB;AACvB,MAAA,MAAM,IAAI,MAAA,CAAO,OAAA;AAEjB,MAAA,IAAI,CAAA,CAAE,OAAA,CAAQ,MAAA,KAAW,CAAA,IAAK,WAAA,EAAa;AAEzC,QAAA,MAAM,EAAA,GAAK,EAAE,OAAA,CAAQ,CAAC,EAAE,OAAA,GAAU,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA;AAC/C,QAAA,MAAM,EAAA,GAAK,EAAE,OAAA,CAAQ,CAAC,EAAE,OAAA,GAAU,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA;AAC/C,QAAA,CAAA,CAAE,cAAA,GAAiB,IAAA,CAAK,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA;AACpC,QAAA,CAAA,CAAE,eAAA,GAAkB,aAAa,OAAA,CAAQ,KAAA;AACzC,QAAA,CAAA,CAAE,aAAA,GAAgB;AAAA,UAChB,CAAA,EAAA,CAAI,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE,UAAU,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA,IAAW,CAAA;AAAA,UACnD,CAAA,EAAA,CAAI,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE,UAAU,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA,IAAW;AAAA,SACrD;AACA,QAAA,CAAA,CAAE,YAAA,GAAe,IAAA;AAGjB,QAAA,IAAI,QAAA,CAAS,QAAQ,MAAA,EAAQ;AAC3B,UAAA,QAAA,CAAS,QAAQ,MAAA,GAAS,KAAA;AAC1B,UAAA,QAAA,EAAS;AAAA,QACX;AAAA,MACF,CAAA,MAAA,IAAW,CAAA,CAAE,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG;AACjC,QAAA,IAAI,YAAA,CAAa,OAAA,CAAQ,KAAA,GAAQ,CAAA,EAAG;AAClC,UAAA,CAAA,CAAE,YAAA,GAAe;AAAA,YACf,CAAA,EAAG,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA;AAAA,YAChB,CAAA,EAAG,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE;AAAA,WAClB;AAAA,QACF,CAAA,MAAO;AACL,UAAA,UAAA,CAAW,CAAA,CAAE,QAAQ,CAAC,CAAA,CAAE,SAAS,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAO,CAAA;AAAA,QACvD;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA,CAAC,YAAA,EAAc,QAAA,EAAU,UAAA,EAAY,WAAW;AAAA,GAClD;AAEA,EAAA,MAAM,eAAA,GAAkBA,WAAAA;AAAA,IACtB,CAAC,CAAA,KAAwB;AACvB,MAAA,MAAM,IAAI,MAAA,CAAO,OAAA;AAEjB,MAAA,IAAI,EAAE,OAAA,CAAQ,MAAA,KAAW,CAAA,IAAK,CAAA,CAAE,mBAAmB,IAAA,EAAM;AAEvD,QAAA,MAAM,EAAA,GAAK,EAAE,OAAA,CAAQ,CAAC,EAAE,OAAA,GAAU,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA;AAC/C,QAAA,MAAM,EAAA,GAAK,EAAE,OAAA,CAAQ,CAAC,EAAE,OAAA,GAAU,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA;AAC/C,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA;AAC9B,QAAA,MAAM,KAAA,GAAQ,OAAO,CAAA,CAAE,cAAA;AACvB,QAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,CAAE,eAAA,GAAkB,KAAK,CAAC,CAAA;AACpE,QAAA,MAAM,IAAI,YAAA,CAAa,OAAA;AACvB,QAAA,MAAM,OAAA,GAAU,SAAA,IAAa,CAAA,GAAI,EAAE,GAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE,GAAIH,eAAAA,CAAe,CAAA,CAAE,CAAA,EAAG,CAAA,CAAE,GAAG,SAAS,CAAA;AAEpF,QAAA,MAAM,IAAA,GAAO,EAAE,KAAA,EAAO,SAAA,EAAW,GAAG,OAAA,EAAQ;AAC5C,QAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AACvB,QAAA,cAAA,CAAe,IAAI,CAAA;AAAA,MAIrB,CAAA,MAAA,IAAW,CAAA,CAAE,OAAA,CAAQ,MAAA,KAAW,CAAA,IAAK,EAAE,YAAA,IAAgB,YAAA,CAAa,OAAA,CAAQ,KAAA,GAAQ,CAAA,EAAG;AAErF,QAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AACzB,QAAA,MAAM,EAAA,GAAK,KAAA,CAAM,OAAA,GAAU,CAAA,CAAE,YAAA,CAAa,CAAA;AAC1C,QAAA,MAAM,EAAA,GAAK,KAAA,CAAM,OAAA,GAAU,CAAA,CAAE,YAAA,CAAa,CAAA;AAC1C,QAAA,CAAA,CAAE,eAAe,EAAE,CAAA,EAAG,MAAM,OAAA,EAAS,CAAA,EAAG,MAAM,OAAA,EAAQ;AAEtD,QAAA,MAAM,IAAI,YAAA,CAAa,OAAA;AACvB,QAAA,MAAM,OAAA,GAAUA,gBAAe,CAAA,CAAE,CAAA,GAAI,IAAI,CAAA,CAAE,CAAA,GAAI,EAAA,EAAI,CAAA,CAAE,KAAK,CAAA;AAC1D,QAAA,MAAM,OAAO,EAAE,KAAA,EAAO,CAAA,CAAE,KAAA,EAAO,GAAG,OAAA,EAAQ;AAC1C,QAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AACvB,QAAA,cAAA,CAAe,IAAI,CAAA;AAAA,MACrB,CAAA,MAAA,IAAW,CAAA,CAAE,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG;AAEjC,QAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AACzB,QAAA,WAAA,CAAY,KAAA,CAAM,OAAA,EAAS,KAAA,CAAM,OAAA,EAAS,GAAG,GAAG,CAAA;AAAA,MAClD;AAAA,IACF,CAAA;AAAA,IACA,CAAC,YAAA,EAAcA,eAAAA,EAAgB,cAAA,EAAgB,WAAW;AAAA,GAC5D;AAEA,EAAA,MAAM,cAAA,GAAiBG,WAAAA;AAAA,IACrB,CAAC,CAAA,KAAwB;AACvB,MAAA,MAAM,IAAI,MAAA,CAAO,OAAA;AACjB,MAAA,MAAM,QAAA,GAAW,EAAE,cAAA,KAAmB,IAAA;AACtC,MAAA,CAAA,CAAE,cAAA,GAAiB,IAAA;AACnB,MAAA,CAAA,CAAE,aAAA,GAAgB,IAAA;AAElB,MAAA,IAAI,EAAE,OAAA,CAAQ,MAAA,KAAW,KAAK,YAAA,CAAa,OAAA,CAAQ,SAAS,CAAA,EAAG;AAE7D,QAAA,MAAMG,MAAK,QAAA,CAAS,OAAA;AACpB,QAAA,IAAIA,IAAG,MAAA,IAAUA,GAAAA,CAAG,MAAA,IAAU,CAACA,IAAG,QAAA,EAAU;AAC1C,UAAA,MAAM,YAAYA,GAAAA,CAAG,SAAA;AACrB,UAAAA,IAAG,MAAA,GAAS,KAAA;AACZ,UAAA,YAAA,CAAa,SAAS,CAAA;AACtB,UAAA,YAAA,CAAa,UAAU,EAAE,KAAA,EAAO,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAE;AAC9C,UAAA;AAAA,QACF;AACA,QAAAA,IAAG,MAAA,GAAS,KAAA;AACZ,QAAA,cAAA,EAAe;AAAA,MACjB;AAGA,MAAA,IAAI,EAAE,OAAA,CAAQ,MAAA,KAAW,KAAK,YAAA,CAAa,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAC5D,QAAA,CAAA,CAAE,YAAA,GAAe;AAAA,UACf,CAAA,EAAG,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA;AAAA,UAChB,CAAA,EAAG,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,CAAE;AAAA,SAClB;AAAA,MACF,CAAA,MAAO;AACL,QAAA,CAAA,CAAE,YAAA,GAAe,IAAA;AAAA,MACnB;AAGA,MAAA,MAAM,KAAK,QAAA,CAAS,OAAA;AACpB,MAAA,IACE,WAAA,IACA,CAAA,CAAE,OAAA,CAAQ,MAAA,KAAW,CAAA,IACrB,CAAA,CAAE,cAAA,CAAe,MAAA,KAAW,CAAA,IAC5B,CAAC,QAAA,IACD,CAAC,GAAG,MAAA,EACJ;AACA,QAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,cAAA,CAAe,CAAC,CAAA;AAChC,QAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,QAAA,MAAM,OAAO,UAAA,CAAW,OAAA;AACxB,QAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,IAAA;AAC7B,QAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,OAAA,GAAU,KAAK,CAAA,EAAG,KAAA,CAAM,OAAA,GAAU,IAAA,CAAK,CAAC,CAAA;AAE3E,QAAA,IAAI,SAAA,GAAY,GAAA,IAAO,SAAA,GAAY,EAAA,EAAI;AACrC,UAAA,UAAA,CAAW,UAAU,EAAE,IAAA,EAAM,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAE;AAC3C,UAAA,IAAI,YAAA,CAAa,OAAA,CAAQ,KAAA,GAAQ,CAAA,EAAG;AAClC,YAAA,cAAA,EAAe;AAAA,UACjB,CAAA,MAAO;AACL,YAAA,YAAA,CAAa,EAAE,OAAO,GAAA,EAAK,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,IAAK,IAAI,CAAA;AAAA,UAC/C;AAAA,QACF,CAAA,MAAO;AACL,UAAA,UAAA,CAAW,OAAA,GAAU,EAAE,IAAA,EAAM,GAAA,EAAK,GAAG,KAAA,CAAM,OAAA,EAAS,CAAA,EAAG,KAAA,CAAM,OAAA,EAAQ;AAAA,QACvE;AAAA,MACF;AAGA,MAAA,IAAI,CAAA,CAAE,QAAQ,MAAA,KAAW,CAAA,IAAK,GAAG,MAAA,IAAU,CAAC,GAAG,MAAA,EAAQ;AACrD,QAAA,EAAA,CAAG,MAAA,GAAS,KAAA;AACZ,QAAA,IAAI,cAAA,CAAe,OAAA,KAAY,CAAA,EAAG,cAAA,CAAe,KAAK,CAAA;AAAA,MACxD;AAAA,IACF,CAAA;AAAA,IACA;AAAA,MACE,YAAA;AAAA,MACA,cAAA;AAAA,MACA,YAAA;AAAA,MACA,YAAA;AAAA,MACA,cAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA;AACF,GACF;AAEA,EAAA,OAAO;AAAA,IACL,iBAAA;AAAA,IACA,iBAAA;AAAA,IACA,eAAA;AAAA,IACA,gBAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACF;AACF;ACnVO,SAAS,aAAA,CACd,SAAA,EACA,YAAA,EAEA,UAAA,EACA;AACA,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIJ,SAAS,CAAC,CAAA;AACxC,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAIA,SAAS,CAAC,CAAA;AAE9C,EAAAG,UAAU,MAAM;AACd,IAAA,MAAM,UAAU,MAAM;AACpB,MAAA,IAAI,SAAA,CAAU,OAAA,EAAS,UAAA,CAAW,SAAA,CAAU,QAAQ,YAAY,CAAA;AAChE,MAAA,IAAI,YAAA,CAAa,OAAA,EAAS,aAAA,CAAc,YAAA,CAAa,QAAQ,YAAY,CAAA;AAAA,IAC3E,CAAA;AACA,IAAA,OAAA,EAAQ;AAER,IAAA,MAAM,EAAA,GAAK,IAAI,cAAA,CAAe,OAAO,CAAA;AACrC,IAAA,IAAI,SAAA,CAAU,OAAA,EAAS,EAAA,CAAG,OAAA,CAAQ,UAAU,OAAO,CAAA;AACnD,IAAA,IAAI,YAAA,CAAa,OAAA,EAAS,EAAA,CAAG,OAAA,CAAQ,aAAa,OAAO,CAAA;AACzD,IAAA,OAAO,MAAM,GAAG,UAAA,EAAW;AAAA,EAE7B,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAA,OAAO,EAAE,SAAS,UAAA,EAAW;AAC/B;AChBA,IAAI,SAAA,GAAY,CAAA;AAChB,IAAI,gBAAA,GAAmB,EAAA;AACvB,IAAI,oBAAA,GAAuB,EAAA;AAEpB,SAAS,kBAAkB,QAAA,EAAyB;AACzD,EAAAA,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,QAAA,EAAU;AACf,IAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AAErC,IAAA,IAAI,cAAc,CAAA,EAAG;AACnB,MAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,UAAA,GAAa,QAAA,CAAS,eAAA,CAAgB,WAAA;AAEpE,MAAA,gBAAA,GAAmB,QAAA,CAAS,KAAK,KAAA,CAAM,QAAA;AACvC,MAAA,oBAAA,GAAuB,QAAA,CAAS,KAAK,KAAA,CAAM,YAAA;AAE3C,MAAA,QAAA,CAAS,IAAA,CAAK,MAAM,QAAA,GAAW,QAAA;AAC/B,MAAA,IAAI,iBAAiB,CAAA,EAAG;AACtB,QAAA,MAAM,mBAAA,GACJ,WAAW,MAAA,CAAO,gBAAA,CAAiB,SAAS,IAAI,CAAA,CAAE,YAAY,CAAA,IAAK,CAAA;AACrE,QAAA,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,YAAA,GAAe,CAAA,EAAG,sBAAsB,cAAc,CAAA,EAAA,CAAA;AAAA,MAC5E;AAAA,IACF;AACA,IAAA,SAAA,IAAa,CAAA;AAEb,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,IAAa,CAAA;AACb,MAAA,IAAI,cAAc,CAAA,EAAG;AACnB,QAAA,QAAA,CAAS,IAAA,CAAK,MAAM,QAAA,GAAW,gBAAA;AAC/B,QAAA,QAAA,CAAS,IAAA,CAAK,MAAM,YAAA,GAAe,oBAAA;AAAA,MACrC;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AACf;AC5CA,IAAM,SAAA,GACJ,2FAAA;AAOK,SAAS,YAAA,CAAa,cAA6C,MAAA,EAAuB;AAC/F,EAAAA,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,MAAA,EAAQ;AACb,IAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AAErC,IAAA,MAAM,oBAAoB,QAAA,CAAS,aAAA;AACnC,IAAA,MAAM,YAAY,YAAA,CAAa,OAAA;AAG/B,IAAA,SAAA,EAAW,KAAA,EAAM;AAEjB,IAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAqB;AACtC,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,KAAA,IAAS,CAAC,SAAA,EAAW;AACnC,MAAA,MAAM,YAAY,KAAA,CAAM,IAAA,CAAK,UAAU,gBAAA,CAA8B,SAAS,CAAC,CAAA,CAAE,MAAA;AAAA,QAC/E,CAAC,EAAA,KAAO,EAAA,CAAG,YAAA,KAAiB,IAAA,IAAQ,OAAO,QAAA,CAAS;AAAA,OACtD;AACA,MAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC1B,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,SAAA,CAAU,KAAA,EAAM;AAChB,QAAA;AAAA,MACF;AACA,MAAA,MAAM,KAAA,GAAQ,UAAU,CAAC,CAAA;AACzB,MAAA,MAAM,IAAA,GAAO,SAAA,CAAU,SAAA,CAAU,MAAA,GAAS,CAAC,CAAA;AAC3C,MAAA,MAAM,WAAW,QAAA,CAAS,aAAA;AAE1B,MAAA,IAAI,CAAA,CAAE,QAAA,KAAa,QAAA,KAAa,KAAA,IAAS,aAAa,SAAA,CAAA,EAAY;AAChE,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,IAAA,CAAK,KAAA,EAAM;AAAA,MACb,CAAA,MAAA,IAAW,CAAC,CAAA,CAAE,QAAA,IAAY,aAAa,IAAA,EAAM;AAC3C,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,KAAA,CAAM,KAAA,EAAM;AAAA,MACd;AAAA,IACF,CAAA;AAEA,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC9C,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,WAAW,SAAS,CAAA;AACjD,MAAA,iBAAA,EAAmB,KAAA,IAAQ;AAAA,IAC7B,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,YAAA,EAAc,MAAM,CAAC,CAAA;AAC3B;AC3CA,SAAS,KAAK,KAAA,EAAgC;AAC5C,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,EAAA;AAAA,IACP,MAAA,EAAQ,EAAA;AAAA,IACR,OAAA,EAAS,WAAA;AAAA,IACT,IAAA,EAAM,MAAA;AAAA,IACN,MAAA,EAAQ,cAAA;AAAA,IACR,WAAA,EAAa,IAAA;AAAA,IACb,aAAA,EAAe,OAAA;AAAA,IACf,cAAA,EAAgB,OAAA;AAAA,IAChB,aAAA,EAAe,IAAA;AAAA,IACf,SAAA,EAAW,KAAA;AAAA,IACX,GAAG;AAAA,GACL;AACF;AAEO,SAAS,UAAU,KAAA,EAAgC;AACxD,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAK,GAAG,IAAA,CAAK,KAAK,CAAA,EACjB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,YAAA,EAAa,CAAA;AAAA,oBACrB,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,YAAA,EAAa;AAAA,GAAA,EACvB,CAAA;AAEJ;AAEO,SAAS,WAAW,KAAA,EAAgC;AACzD,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAK,GAAG,IAAA,CAAK,KAAK,CAAA,EACjB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,YAAO,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,GAAE,GAAA,EAAI,CAAA;AAAA,oBAC9B,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,gBAAA,EAAiB,CAAA;AAAA,oBACzB,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,SAAA,EAAU,CAAA;AAAA,oBAClB,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,SAAA,EAAU;AAAA,GAAA,EACpB,CAAA;AAEJ;AAEO,SAAS,YAAY,KAAA,EAAgC;AAC1D,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAK,GAAG,IAAA,CAAK,KAAK,CAAA,EACjB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,YAAO,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,GAAE,GAAA,EAAI,CAAA;AAAA,oBAC9B,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,gBAAA,EAAiB,CAAA;AAAA,oBACzB,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,SAAA,EAAU;AAAA,GAAA,EACpB,CAAA;AAEJ;AAEO,SAAS,gBAAgB,KAAA,EAAgC;AAC9D,EAAA,2BACG,KAAA,EAAA,EAAK,GAAG,KAAK,EAAE,KAAA,EAAO,IAAI,MAAA,EAAQ,EAAA,EAAI,aAAa,GAAA,EAAK,GAAG,OAAO,CAAA,EACjE,8BAAC,MAAA,EAAA,EAAK,CAAA,EAAE,kBAAiB,CAAA,EAC3B,CAAA;AAEJ;AAEO,SAAS,iBAAiB,KAAA,EAAgC;AAC/D,EAAA,2BACG,KAAA,EAAA,EAAK,GAAG,KAAK,EAAE,KAAA,EAAO,IAAI,MAAA,EAAQ,EAAA,EAAI,aAAa,GAAA,EAAK,GAAG,OAAO,CAAA,EACjE,8BAAC,MAAA,EAAA,EAAK,CAAA,EAAE,iBAAgB,CAAA,EAC1B,CAAA;AAEJ;AAGO,IAAM,YAAA,GAA4B;AAAA,EACvC,KAAA,sBAAQ,SAAA,EAAA,EAAU,CAAA;AAAA,EAClB,MAAA,sBAAS,UAAA,EAAA,EAAW,CAAA;AAAA,EACpB,OAAA,sBAAU,WAAA,EAAA,EAAY,CAAA;AAAA,EACtB,IAAA,sBAAO,eAAA,EAAA,EAAgB,CAAA;AAAA,EACvB,IAAA,sBAAO,gBAAA,EAAA,EAAiB;AAC1B;;;AC3EO,SAAS,MAAM,KAAA,EAAyD;AAC7E,EAAA,OAAO,KAAA,CAAM,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AACvC;ACQO,SAAS,UAAU,EAAE,SAAA,EAAW,SAAS,OAAA,EAAS,IAAA,EAAM,WAAU,EAAmB;AAC1F,EAAA,uBACEE,GAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,QAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,QAAA,IAAI,SAAS,OAAA,EAAQ;AAAA,MACvB,CAAA;AAAA,MACA,UAAU,CAAC,OAAA;AAAA,MACX,SAAA,EAAW,EAAA,CAAG,aAAA,EAAe,SAAS,CAAA;AAAA,MACtC,YAAA,EAAY,SAAA,KAAc,MAAA,GAAS,gBAAA,GAAmB,YAAA;AAAA,MAErD,QAAA,EAAA;AAAA;AAAA,GACH;AAEJ;ACdA,IAAM,OAAA,GAAU,GAAA;AAChB,IAAM,WAAA,GAAc,EAAA;AAEpB,SAAS,oBAAA,GAAgC;AACvC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,MAAA,CAAO,YAAY,OAAO,KAAA;AAChE,EAAA,OAAO,MAAA,CAAO,UAAA,CAAW,kCAAkC,CAAA,CAAE,OAAA;AAC/D;AAQO,SAAS,WAAA,CAA6B;AAAA,EAC3C,KAAA;AAAA,EACA,KAAA;AAAA,EACA,aAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA,GAAO,IAAA;AAAA,EACP,WAAA,GAAc,IAAA;AAAA,EACd,IAAA,GAAO,KAAA;AAAA,EACP,YAAA;AAAA,EACA,mBAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,UAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAA4B;AAC1B,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIL,SAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,SAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAIA,SAAS,KAAK,CAAA;AACxD,EAAA,MAAM,CAAC,YAAA,EAAc,oBAAoB,CAAA,GAAIA,QAAAA,CAG1C,EAAE,SAAA,EAAW,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,CAAA;AAErC,EAAA,MAAM,YAAA,GAAeD,OAAuB,IAAI,CAAA;AAChD,EAAA,MAAM,aAAA,GAAgBA,OAAuB,IAAI,CAAA;AACjD,EAAA,MAAM,SAAA,GAAYA,OAAuB,IAAI,CAAA;AAC7C,EAAA,MAAM,YAAA,GAAeA,OAAuB,IAAI,CAAA;AAEhD,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAIC,QAAAA;AAAA,IAAS,MACjD,OAAO,MAAA,KAAW,WAAA,GAAc,IAAI,MAAA,CAAO;AAAA,GAC7C;AAEA,EAAA,MAAM,IAAA,GAAO,MAAM,KAAK,CAAA;AAExB,EAAA,MAAM,gBAAgB,KAAA,GAAQ,CAAA;AAC9B,EAAA,MAAM,aAAA,GAAgB,KAAA,GAAQ,KAAA,CAAM,MAAA,GAAS,CAAA;AAC7C,EAAA,MAAM,OAAA,GAAU,IAAA,GAAO,KAAA,CAAM,MAAA,GAAS,CAAA,GAAI,aAAA;AAC1C,EAAA,MAAM,OAAA,GAAU,IAAA,GAAO,KAAA,CAAM,MAAA,GAAS,CAAA,GAAI,aAAA;AAE1C,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,OAAO,EAAE,GAAG,YAAA,EAAc,GAAG,KAAA,EAAM,CAAA,EAAI,CAAC,KAAK,CAAC,CAAA;AAC1E,EAAA,MAAM,EAAA,GAAK,CAAC,IAAA,KAA4D,UAAA,GAAa,IAAI,CAAA;AAEzF,EAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,EAAA,YAAA,CAAa,YAAA,EAAc,OAAA,IAAW,CAAC,OAAO,CAAA;AAC9C,EAAA,MAAM,EAAE,OAAA,EAAS,UAAA,KAAe,aAAA,CAAc,SAAA,EAAW,cAAc,KAAK,CAAA;AAE5E,EAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,aAAA,EAAe,KAAA,EAAO,IAAI,CAAA;AAC1D,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,YAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA,cAAA;AAAA,IACA,YAAA;AAAA,IACA,cAAA,EAAAF,eAAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACF,GAAI,OAAA;AAEJ,EAAA,MAAM,KAAA,GAAQ,kBAAA,CAAmB,KAAA,EAAO,KAAA,EAAO,eAAe,UAAU,CAAA;AACxE,EAAA,MAAM,EAAE,aAAA,EAAe,WAAA,EAAa,cAAA,EAAgB,WAAA,EAAa,aAAY,GAAI,KAAA;AAEjF,EAAA,MAAM,WAAW,iBAAA,CAAkB,OAAA,EAAS,KAAA,EAAO,aAAA,EAAe,eAAe,IAAI,CAAA;AAErF,EAAAK,UAAU,MAAM;AACd,IAAA,gBAAA,CAAiB,cAAA,IAAkB,MAAA,IAAU,SAAA,CAAU,cAAA,GAAiB,CAAC,CAAA;AAAA,EAC3E,CAAA,EAAG,EAAE,CAAA;AAEL,EAAAA,UAAU,MAAM;AACd,IAAA,MAAM,QAAA,GAAW,MAAM,gBAAA,CAAiB,MAAA,CAAO,UAAU,CAAA;AACzD,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AAC1C,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,QAAQ,CAAA;AAAA,EAC5D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAAA,UAAU,MAAM;AACd,IAAA,MAAM,GAAA,GAAM,qBAAA,CAAsB,MAAM,UAAA,CAAW,IAAI,CAAC,CAAA;AACxD,IAAA,OAAO,MAAM,qBAAqB,GAAG,CAAA;AAAA,EACvC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,WAAA,GAAcF,YAAY,MAAM;AACpC,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,UAAA,CAAW,KAAK,CAAA;AAChB,IAAA,MAAM,KAAA,GAAQ,oBAAA,EAAqB,GAAI,CAAA,GAAI,OAAA;AAC3C,IAAA,UAAA,CAAW,SAAS,KAAK,CAAA;AAAA,EAC3B,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,MAAM,QAAA,GAAWA,WAAAA;AAAA,IACf,CAAC,GAAA,KAAyB;AACxB,MAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,QAAA,IAAI,aAAA,cAA2B,MAAM,CAAA;AAAA,aAAA,IAC5B,IAAA,EAAM;AAGb,UAAA,UAAA,GAAa,MAAM,CAAA;AACnB,UAAA,aAAA,CAAc,KAAA,CAAM,SAAS,CAAC,CAAA;AAAA,QAChC;AAAA,MACF,CAAA,MAAO;AACL,QAAA,IAAI,aAAA,cAA2B,MAAM,CAAA;AAAA,aAAA,IAC5B,IAAA,EAAM;AACb,UAAA,UAAA,GAAa,MAAM,CAAA;AACnB,UAAA,aAAA,CAAc,CAAC,CAAA;AAAA,QACjB;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA,CAAC,eAAe,aAAA,EAAe,IAAA,EAAM,aAAa,aAAA,EAAe,UAAA,EAAY,MAAM,MAAM;AAAA,GAC3F;AAEA,EAAAE,UAAU,MAAM;AACd,IAAA,MAAM,OAAA,GAAU,CAAC,CAAA,KAAqB;AACpC,MAAA,IAAI,CAAA,CAAE,QAAQ,QAAA,EAAU;AACtB,QAAA,WAAA,EAAY;AACZ,QAAA;AAAA,MACF;AACA,MAAA,IAAI,eAAe,CAAA,EAAG;AACtB,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,WAAA,IAAe,OAAA,WAAkB,MAAM,CAAA;AACrD,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,YAAA,IAAgB,OAAA,WAAkB,MAAM,CAAA;AAAA,IACxD,CAAA;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,OAAO,CAAA;AAC1C,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,OAAO,CAAA;AAAA,EAC5D,GAAG,CAAC,WAAA,EAAa,SAAS,OAAA,EAAS,YAAA,EAAc,QAAQ,CAAC,CAAA;AAE1D,EAAA,MAAM,eAAA,GAAkBF,WAAAA,CAAY,CAAC,SAAA,EAA0B,UAAU,IAAA,KAAS;AAChF,IAAA,oBAAA,CAAqB,EAAE,SAAA,EAAW,OAAA,EAAS,CAAA;AAAA,EAC7C,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,GAAA,GAA4B;AAAA,IAChC,KAAA;AAAA,IACA,KAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAO,KAAA,CAAM,MAAA;AAAA,IACb,OAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA,EAAQ,MAAM,QAAA,CAAS,MAAM,CAAA;AAAA,IAC7B,MAAA,EAAQ,MAAM,QAAA,CAAS,MAAM,CAAA;AAAA,IAC7B,IAAA,EAAM,CAAC,CAAA,KAAc;AACnB,MAAA,IAAI,CAAA,KAAM,SAAS,CAAA,IAAK,CAAA,IAAK,IAAI,KAAA,CAAM,MAAA,gBAAsB,CAAC,CAAA;AAAA,IAChE,CAAA;AAAA,IACA,KAAA,EAAO,WAAA;AAAA,IACP,QAAA;AAAA,IACA,YAAA;AAAA,IACA,QAAQ,MAAM;AACZ,MAAA,MAAM,IAAI,YAAA,CAAa,OAAA;AACvB,MAAA,MAAM,OAAO,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,CAAA,CAAE,QAAQ,GAAG,CAAA;AAC9C,MAAA,MAAM,UAAUH,eAAAA,CAAe,CAAA,CAAE,CAAA,EAAG,CAAA,CAAE,GAAG,IAAI,CAAA;AAC7C,MAAA,YAAA,CAAa,EAAE,KAAA,EAAO,IAAA,EAAM,GAAG,OAAA,IAAW,IAAI,CAAA;AAAA,IAChD,CAAA;AAAA,IACA,SAAS,MAAM;AACb,MAAA,MAAM,IAAI,YAAA,CAAa,OAAA;AACvB,MAAA,MAAM,OAAO,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,CAAA,CAAE,QAAQ,GAAG,CAAA;AAC9C,MAAA,MAAM,OAAA,GAAU,IAAA,IAAQ,CAAA,GAAI,EAAE,GAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE,GAAIA,eAAAA,CAAe,CAAA,CAAE,CAAA,EAAG,CAAA,CAAE,GAAG,IAAI,CAAA;AAC1E,MAAA,YAAA,CAAa,EAAE,KAAA,EAAO,IAAA,EAAM,GAAG,OAAA,IAAW,IAAI,CAAA;AAAA,IAChD,CAAA;AAAA,IACA,SAAA,EAAW,cAAA;AAAA,IACX,aAAA;AAAA,IACA,YAAA,EAAc,OAAA;AAAA,IACd,eAAA,EAAiB,UAAA;AAAA,IACjB;AAAA,GACF;AAEA,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,EAAA,MAAM,SAAA,GAAY,aAAa,WAAA,GAAc,CAAA;AAC7C,EAAA,MAAM,YAAA,GAAe,gBAAgB,SAAS,CAAA,GAAA,CAAA;AAC9C,EAAA,MAAM,QAAA,GAAgC,EAAE,SAAA,EAAW,YAAA,EAAa;AAEhE,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,CAAE,MAAA;AACzC,EAAA,MAAM,eAAA,GAAkB,CAAA,EAAG,WAAA,GAAc,CAAA,GAAI,MAAM,GAAG,CAAA,EAAA,CAAA;AAEtD,EAAA,MAAM,QAAA,GAAW,aAAA,GAAgB,KAAA,CAAM,KAAA,GAAQ,CAAC,CAAA,GAAI,IAAA;AACpD,EAAA,MAAM,QAAA,GAAW,aAAA,GAAgB,KAAA,CAAM,KAAA,GAAQ,CAAC,CAAA,GAAI,IAAA;AACpD,EAAA,MAAM,YAAA,GAAe,WAAA,IAAe,cAAA,IAAkB,WAAA,KAAgB,CAAA;AACtE,EAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,IAAI,WAAW,CAAA,IAAK,aAAA,GAAgB,GAAA,IAAO,CAAA,CAAE,CAAA;AAEtF,EAAA,MAAM,gBAAA,GAAmB,QAAQ,CAAC,aAAA;AAClC,EAAA,MAAM,aAAA,GAAgB,sBAAsB,GAAG,CAAA;AAC/C,EAAA,MAAM,QAAA,GAAW,iBAAiB,GAAG,CAAA;AACrC,EAAA,MAAM,MAAA,GAAS,eAAe,GAAG,CAAA;AACjC,EAAA,MAAM,cAAc,OAAA,IAAW,OAAA;AAC/B,EAAA,MAAM,aAAa,CAAC,QAAA,KAAa,WAAA,IAAe,QAAA,IAAY,QAAQ,MAAA,IAAU,IAAA,CAAA;AAE9E,EAAA,uBACEQ,IAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,YAAA;AAAA,MACL,SAAA,EAAW,GAAG,UAAA,EAAY,OAAA,IAAW,CAAC,OAAA,IAAW,aAAA,EAAe,EAAA,CAAG,MAAM,CAAC,CAAA;AAAA,MAC1E,IAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAW,MAAA;AAAA,MACX,YAAA,EAAY,SAAA,IAAa,IAAA,CAAK,GAAA,IAAO,cAAA;AAAA,MACrC,QAAA,EAAU,EAAA;AAAA,MAEV,QAAA,EAAA;AAAA,wBAAAD,GAAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,EAAA,CAAG,cAAA,EAAgB,EAAA,CAAG,UAAU,CAAC,CAAA;AAAA,YAC5C,OAAA,EAAS,WAAA;AAAA,YACT,aAAA,EAAY;AAAA;AAAA,SACd;AAAA,wBAEAC,IAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,aAAA,EAAe,EAAA,CAAG,QAAQ,CAAC,CAAA,EACvE,QAAA,EAAA;AAAA,0BAAAD,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,YAAA,EAAc,EAAA,CAAG,QAAQ,CAAC,CAAA,EAAI,QAAA,EAAA,YAAA,GAAe,GAAG,CAAA,EAAE,CAAA;AAAA,0BAErEC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oBAAA,EACZ,QAAA,EAAA;AAAA,YAAA,aAAA;AAAA,YAEA,gBAAA,IAAoB,4BACnBA,IAAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,WAAW,EAAA,CAAG,SAAA,EAAW,eAAA,EAAiB,EAAA,CAAG,QAAQ,CAAC,CAAA;AAAA,gBACtD,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,kBAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,kBAAA,cAAA,EAAe;AAAA,gBACjB,CAAA;AAAA,gBACA,KAAA,EAAM,YAAA;AAAA,gBACN,YAAA,EAAW,YAAA;AAAA,gBAEV,QAAA,EAAA;AAAA,kBAAA,IAAA,CAAK,KAAA,CAAM,eAAe,GAAG,CAAA;AAAA,kBAAE;AAAA;AAAA;AAAA,aAClC;AAAA,YAGD,oCACCD,GAAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,EAAA,CAAG,QAAQ,CAAC,CAAA;AAAA,gBACrC,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,kBAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,kBAAA,GAAA,CAAI,MAAA,EAAO;AAAA,gBACb,CAAA;AAAA,gBACA,KAAA,EAAM,SAAA;AAAA,gBACN,YAAA,EAAW,SAAA;AAAA,gBAEV,QAAA,EAAA,WAAA,CAAY;AAAA;AAAA,aACf;AAAA,YAGD,oCACCA,GAAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,EAAA,CAAG,QAAQ,CAAC,CAAA;AAAA,gBACrC,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,kBAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,kBAAA,GAAA,CAAI,OAAA,EAAQ;AAAA,gBACd,CAAA;AAAA,gBACA,KAAA,EAAM,UAAA;AAAA,gBACN,YAAA,EAAW,UAAA;AAAA,gBAEV,QAAA,EAAA,WAAA,CAAY;AAAA;AAAA,aACf;AAAA,4BAGFA,GAAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,EAAA,CAAG,QAAQ,CAAC,CAAA;AAAA,gBACrC,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,kBAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,kBAAA,WAAA,EAAY;AAAA,gBACd,CAAA;AAAA,gBACA,KAAA,EAAM,aAAA;AAAA,gBACN,YAAA,EAAW,OAAA;AAAA,gBAEV,QAAA,EAAA,WAAA,CAAY;AAAA;AAAA;AACf,WAAA,EACF;AAAA,SAAA,EACF,CAAA;AAAA,wBAEAA,GAAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,WAAA;AAAA,YACV,KAAA,EAAO;AAAA,cACL,SAAA,EAAW,aAAa,SAAA,IAAa,eAAA;AAAA;AAAA,cAErC,UAAA,EAAY,YAAA,CAAa,OAAA,GAAU,MAAA,GAAY;AAAA,aACjD;AAAA,YAEA,QAAA,kBAAAC,IAAAA;AAAA,cAAC,KAAA;AAAA,cAAA;AAAA,gBACC,GAAA,EAAK,aAAA;AAAA,gBACL,WAAW,EAAA,CAAG,WAAA,EAAa,OAAA,IAAW,CAAC,WAAW,mBAAmB,CAAA;AAAA,gBAEpE,QAAA,EAAA;AAAA,kBAAA,YAAA,IAAgB,4BACfD,GAAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,SAAA,EAAU,cAAA;AAAA,sBACV,OAAO,EAAE,SAAA,EAAW,eAAe,aAAa,CAAA,GAAA,CAAA,EAAO,SAAS,eAAA,EAAgB;AAAA,sBAEhF,QAAA,kBAAAA,GAAAA;AAAA,wBAAC,KAAA;AAAA,wBAAA;AAAA,0BACC,KAAK,QAAA,CAAS,GAAA;AAAA,0BACd,GAAA,EAAI,EAAA;AAAA,0BACJ,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,EAAA,CAAG,OAAO,CAAC,CAAA;AAAA,0BACpC,KAAA,EAAO,QAAA;AAAA,0BACP,SAAA,EAAW;AAAA;AAAA;AACb;AAAA,mBACF;AAAA,kCAGFA,GAAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,GAAA,EAAK,aAAA;AAAA,sBACL,SAAA,EAAU,iBAAA;AAAA,sBACV,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,CAAE,eAAA,EAAgB;AAAA,sBAClC,aAAA,EAAe,iBAAA;AAAA,sBACf,eAAe,QAAA,CAAS,iBAAA;AAAA,sBACxB,eAAe,QAAA,CAAS,iBAAA;AAAA,sBACxB,aAAa,QAAA,CAAS,eAAA;AAAA,sBACtB,gBAAgB,QAAA,CAAS,eAAA;AAAA,sBACzB,cAAc,QAAA,CAAS,gBAAA;AAAA,sBACvB,aAAa,QAAA,CAAS,eAAA;AAAA,sBACtB,YAAY,QAAA,CAAS,cAAA;AAAA,sBAErB,QAAA,kBAAAA,GAAAA;AAAA,wBAAC,KAAA;AAAA,wBAAA;AAAA,0BACC,GAAA,EAAK,MAAA;AAAA,0BACL,KAAK,IAAA,CAAK,GAAA;AAAA,0BACV,GAAA,EAAK,KAAK,GAAA,IAAO,EAAA;AAAA,0BACjB,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,EAAA,CAAG,OAAO,CAAC,CAAA;AAAA,0BACpC,KAAA,EAAO,QAAA;AAAA,0BACP,SAAA,EAAW,KAAA;AAAA,0BACX,MAAA,EAAQ;AAAA;AAAA;AACV;AAAA,mBACF;AAAA,kBAEC,YAAA,IAAgB,4BACfA,GAAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,SAAA,EAAU,cAAA;AAAA,sBACV,OAAO,EAAE,SAAA,EAAW,cAAc,aAAa,CAAA,GAAA,CAAA,EAAO,SAAS,eAAA,EAAgB;AAAA,sBAE/E,QAAA,kBAAAA,GAAAA;AAAA,wBAAC,KAAA;AAAA,wBAAA;AAAA,0BACC,KAAK,QAAA,CAAS,GAAA;AAAA,0BACd,GAAA,EAAI,EAAA;AAAA,0BACJ,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,EAAA,CAAG,OAAO,CAAC,CAAA;AAAA,0BACpC,KAAA,EAAO,QAAA;AAAA,0BACP,SAAA,EAAW;AAAA;AAAA;AACb;AAAA;AACF;AAAA;AAAA;AAEJ;AAAA,SACF;AAAA,wBAEAC,IAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,YAAA,EAAc,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,gBAAA,EAAkB,EAAA,CAAG,WAAW,CAAC,CAAA,EAC/E,QAAA,EAAA;AAAA,UAAA,UAAA,oBACCD,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,eACb,QAAA,kBAAAC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,eAAA,EACZ,QAAA,EAAA;AAAA,YAAA,QAAA,IAAY,IAAA,oBACXD,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,eAAA,EAAiB,EAAA,CAAG,UAAU,CAAC,CAAA,EAAI,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,YAEhE,WAAA,oBACCC,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,eAAA,EACb,QAAA,EAAA;AAAA,8BAAAD,GAAAA;AAAA,gBAAC,SAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAU,MAAA;AAAA,kBACV,OAAA,EAAS,OAAA;AAAA,kBACT,OAAA,EAAS,MAAM,QAAA,CAAS,MAAM,CAAA;AAAA,kBAC9B,MAAM,WAAA,CAAY,IAAA;AAAA,kBAClB,SAAA,EAAW,GAAG,WAAW;AAAA;AAAA,eAC3B;AAAA,cACC,+BACCC,IAAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAW,EAAA,CAAG,aAAA,EAAe,EAAA,CAAG,SAAS,CAAC,CAAA;AAAA,kBAC1C,KAAA,EAAO,EAAE,QAAA,EAAU,eAAA,EAAgB;AAAA,kBAElC,QAAA,EAAA;AAAA,oBAAA,KAAA,GAAQ,CAAA;AAAA,oBAAE,KAAA;AAAA,oBAAI,KAAA,CAAM;AAAA;AAAA;AAAA,eACvB;AAAA,8BAEFD,GAAAA;AAAA,gBAAC,SAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAU,MAAA;AAAA,kBACV,OAAA,EAAS,OAAA;AAAA,kBACT,OAAA,EAAS,MAAM,QAAA,CAAS,MAAM,CAAA;AAAA,kBAC9B,MAAM,WAAA,CAAY,IAAA;AAAA,kBAClB,SAAA,EAAW,GAAG,WAAW;AAAA;AAAA;AAC3B,aAAA,EACF,CAAA;AAAA,YAED,MAAA,IAAU,IAAA,oBAAQA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,aAAA,EAAe,EAAA,CAAG,QAAQ,CAAC,CAAA,EAAI,QAAA,EAAA,MAAA,EAAO;AAAA,WAAA,EAC9E,CAAA,EACF,CAAA;AAAA,UAGD,YAAA,oBAAgBA,GAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,YAAA,EAAc,QAAA,EAAA,YAAA,CAAa,GAAG,CAAA,EAAE;AAAA,SAAA,EAClE,CAAA;AAAA,QAEC,aAAA,oBACCA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,aAAA,EAAe,EAAA,CAAG,SAAS,CAAC,CAAA,EAAI,QAAA,EAAA,aAAA,CAAc,GAAG,CAAA,EAAE;AAAA;AAAA;AAAA,GAE1E;AAEJ","file":"index.js","sourcesContent":["/**\n * Pure geometry/threshold helpers shared by the interaction hooks. Kept free of\n * React and DOM globals so they can be unit-tested in isolation.\n */\n\nexport interface Dims {\n width: number;\n height: number;\n}\n\n/**\n * Clamp a pan translation so the scaled image edge can't move past the\n * viewport edge. Returns `{ x: 0, y: 0 }` when not zoomed or when base\n * dimensions are unknown.\n */\nexport function clampTranslate(\n x: number,\n y: number,\n scale: number,\n baseDims: Dims,\n viewport: Dims,\n): { x: number; y: number } {\n if (scale <= 1) return { x: 0, y: 0 };\n const { width: baseW, height: baseH } = baseDims;\n if (baseW === 0 || baseH === 0) return { x: 0, y: 0 };\n\n const scaledHalfW = (baseW * scale) / 2;\n const scaledHalfH = (baseH * scale) / 2;\n const vpHalfW = viewport.width / 2;\n const vpHalfH = viewport.height / 2;\n\n const maxX = Math.max(0, scaledHalfW - vpHalfW);\n const maxY = Math.max(0, scaledHalfH - vpHalfH);\n\n return {\n x: Math.max(-maxX, Math.min(maxX, x)),\n y: Math.max(-maxY, Math.min(maxY, y)),\n };\n}\n\nexport type SlideAction = \"prev\" | \"next\" | \"snap\";\n\nexport interface ResolveSlideArgs {\n /** Current horizontal swipe offset in px (positive = dragged right). */\n offset: number;\n /** Elapsed time of the gesture in ms (used for fling velocity). */\n elapsedMs: number;\n viewportWidth: number;\n hasPrev: boolean;\n hasNext: boolean;\n /** Fraction of viewport width past which a drag commits. Default 0.25. */\n distanceThreshold?: number;\n /** px/ms past which a fast fling commits regardless of distance. Default 0.4. */\n velocityThreshold?: number;\n}\n\n/**\n * Decide whether a released swipe should navigate `prev`/`next` or `snap` back,\n * based on distance and fling velocity.\n */\nexport function resolveSlideDirection({\n offset,\n elapsedMs,\n viewportWidth,\n hasPrev,\n hasNext,\n distanceThreshold = 0.25,\n velocityThreshold = 0.4,\n}: ResolveSlideArgs): SlideAction {\n const velocity = Math.abs(offset) / Math.max(elapsedMs, 1);\n const threshold = viewportWidth * distanceThreshold;\n const committed = Math.abs(offset) > threshold || velocity > velocityThreshold;\n\n if (offset > 0 && hasPrev && committed) return \"prev\";\n if (offset < 0 && hasNext && committed) return \"next\";\n return \"snap\";\n}\n","import { useCallback, useEffect, useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport { clampTranslate as clampTranslatePure } from \"./math\";\n\nconst MIN_SCALE = 1;\nconst MAX_SCALE = 5;\n\nexport interface ImageTransform {\n scale: number;\n x: number;\n y: number;\n}\n\nexport interface ImageZoomPanState {\n imgRef: RefObject<HTMLImageElement | null>;\n displayScale: number;\n isZoomed: boolean;\n transformRef: React.MutableRefObject<ImageTransform>;\n\n /** Base (unscaled) image dimensions for clamp calculations */\n baseDimsRef: React.MutableRefObject<{ width: number; height: number }>;\n\n resetTransform: () => void;\n setTransform: (t: ImageTransform, animate?: boolean) => void;\n applyTransform: (t: ImageTransform, animate?: boolean) => void;\n clampTranslate: (x: number, y: number, scale: number) => { x: number; y: number };\n measureBaseDims: () => void;\n handleDoubleClick: (e: React.MouseEvent) => void;\n}\n\n/**\n * Manages zoom/pan state for an image viewer.\n *\n * Applies scale + translate transforms to the **wrapper** element rather\n * than the image itself. This avoids an iOS Safari compositing bug where\n * CSS scale() on an element clips its painted output to the element's\n * original layout bounds.\n *\n * When zoomed, the wrapper is positioned absolute inset-0 (full viewport),\n * so its layout bounds already match the viewport and scaling it won't clip.\n * The image stays at its natural constrained size, centered via flexbox.\n */\nexport function useImageZoomPan(\n imgWrapperRef: RefObject<HTMLDivElement | null>,\n currentIndex: number,\n /** When false, wheel-zoom and double-click-zoom are disabled. Default true. */\n enabled = true,\n): ImageZoomPanState {\n const imgRef = useRef<HTMLImageElement>(null);\n const [displayScale, setDisplayScale] = useState(1);\n const transformRef = useRef<ImageTransform>({ scale: 1, x: 0, y: 0 });\n const baseDimsRef = useRef<{ width: number; height: number }>({ width: 0, height: 0 });\n\n // Core helpers\n\n const applyTransform = useCallback(\n (t: ImageTransform, animate = false) => {\n const wrapper = imgWrapperRef.current;\n if (!wrapper) return;\n wrapper.style.transition = animate ? \"transform 0.2s ease-out\" : \"none\";\n\n if (t.scale <= 1) {\n wrapper.style.transform = \"none\";\n wrapper.style.position = \"\";\n wrapper.style.inset = \"\";\n wrapper.style.zIndex = \"\";\n wrapper.style.backgroundColor = \"\";\n wrapper.style.cursor = \"\";\n } else {\n wrapper.style.transform = `scale(${t.scale}) translate(${t.x / t.scale}px, ${t.y / t.scale}px)`;\n wrapper.style.position = \"absolute\";\n wrapper.style.inset = \"0\";\n wrapper.style.zIndex = \"30\";\n wrapper.style.backgroundColor = \"black\";\n wrapper.style.cursor = \"grab\";\n }\n\n // Keep React state in sync so isZoomed reflects reality\n setDisplayScale(t.scale);\n },\n [imgWrapperRef],\n );\n\n const setTransform = useCallback(\n (t: ImageTransform, animate = false) => {\n transformRef.current = t;\n applyTransform(t, animate);\n setDisplayScale(t.scale);\n },\n [applyTransform],\n );\n\n const resetTransform = useCallback(() => {\n setTransform({ scale: 1, x: 0, y: 0 }, true);\n }, [setTransform]);\n\n const measureBaseDims = useCallback(() => {\n const img = imgRef.current;\n if (!img) return;\n baseDimsRef.current = { width: img.offsetWidth, height: img.offsetHeight };\n }, []);\n\n /**\n * Clamp so the image edge can't pan past the viewport edge.\n */\n const clampTranslate = useCallback(\n (x: number, y: number, scale: number): { x: number; y: number } =>\n clampTranslatePure(x, y, scale, baseDimsRef.current, {\n width: window.innerWidth,\n height: window.innerHeight,\n }),\n [],\n );\n\n // Reset on navigation\n\n useLayoutEffect(() => {\n const wrapper = imgWrapperRef.current;\n if (wrapper) {\n wrapper.style.transition = \"none\";\n wrapper.style.transform = \"none\";\n wrapper.style.position = \"\";\n wrapper.style.inset = \"\";\n wrapper.style.zIndex = \"\";\n wrapper.style.backgroundColor = \"\";\n wrapper.style.cursor = \"\";\n }\n transformRef.current = { scale: 1, x: 0, y: 0 };\n }, [currentIndex, imgWrapperRef]);\n\n useEffect(() => {\n setDisplayScale(1);\n }, [currentIndex]);\n\n // Wheel zoom (desktop)\n\n useEffect(() => {\n if (!enabled) return;\n const wrapper = imgWrapperRef.current;\n if (!wrapper) return;\n\n const handleWheel = (e: WheelEvent) => {\n e.preventDefault();\n\n // Ensure base dims\n if (baseDimsRef.current.width === 0) {\n const img = imgRef.current;\n if (img) baseDimsRef.current = { width: img.offsetWidth, height: img.offsetHeight };\n }\n\n const t = transformRef.current;\n\n let dy = e.deltaY;\n if (e.deltaMode === 1) dy *= 16;\n if (e.deltaMode === 2) dy *= 100;\n\n const normalized = Math.max(-100, Math.min(100, dy));\n const step = -(normalized / 100) * 0.05;\n const factor = 1 + step;\n\n const nextScale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, t.scale * factor));\n const clamped = nextScale <= 1 ? { x: 0, y: 0 } : clampTranslate(t.x, t.y, nextScale);\n setTransform({ scale: nextScale, ...clamped });\n };\n\n wrapper.addEventListener(\"wheel\", handleWheel, { passive: false });\n return () => wrapper.removeEventListener(\"wheel\", handleWheel);\n }, [imgWrapperRef, setTransform, clampTranslate, enabled]);\n\n // Double-click toggle\n\n const handleDoubleClick = useCallback(\n (e: React.MouseEvent) => {\n if (!enabled) return;\n e.stopPropagation();\n\n // Ensure base dims\n if (baseDimsRef.current.width === 0) {\n const img = imgRef.current;\n if (img) baseDimsRef.current = { width: img.offsetWidth, height: img.offsetHeight };\n }\n\n if (transformRef.current.scale > 1) {\n resetTransform();\n } else {\n setTransform({ scale: 1.8, x: 0, y: 0 }, true);\n }\n },\n [resetTransform, setTransform, enabled],\n );\n\n return {\n imgRef,\n displayScale,\n isZoomed: displayScale > 1,\n transformRef,\n baseDimsRef,\n resetTransform,\n setTransform,\n applyTransform,\n clampTranslate,\n measureBaseDims,\n handleDoubleClick,\n };\n}\n\nexport { MIN_SCALE, MAX_SCALE };\n","import { useCallback, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport type { ViewerItem } from \"../types\";\nimport { resolveSlideDirection } from \"./math\";\n\nexport interface SlideNavigationState {\n slideTrackRef: React.RefObject<HTMLDivElement | null>;\n slideActive: boolean;\n slideAnimating: boolean;\n swipeOffset: number;\n swipeOffsetRef: React.MutableRefObject<number>;\n commitLockRef: React.MutableRefObject<boolean>;\n\n applySlideOffset: (offset: number, animate?: boolean) => void;\n commitSlide: (direction: \"prev\" | \"next\") => void;\n snapBack: () => void;\n resolveSlide: (gestureStartTime: number) => void;\n setSlideActive: React.Dispatch<React.SetStateAction<boolean>>;\n}\n\n/**\n * Manages the three-slot slide carousel: swipe offset tracking, animated\n * commit/snap-back, and DOM resets on navigation.\n *\n * `items[i].src` is treated as a final, ready-to-load url — the next image is\n * preloaded/decoded before navigation commits so the swipe lands on a painted\n * frame.\n */\nexport function useSlideNavigation(\n items: ViewerItem[],\n currentIndex: number,\n onNavigate: (index: number) => void,\n onSlideStart?: (direction: \"prev\" | \"next\") => void,\n): SlideNavigationState {\n const slideTrackRef = useRef<HTMLDivElement>(null);\n const swipeOffsetRef = useRef(0);\n const [swipeOffset, setSwipeOffset] = useState(0);\n const [slideAnimating, setSlideAnimating] = useState(false);\n const [slideActive, setSlideActive] = useState(false);\n const commitLockRef = useRef(false);\n\n const hasPrev = currentIndex > 0;\n const hasNext = currentIndex < items.length - 1;\n\n const applySlideOffset = useCallback((offset: number, animate = false) => {\n swipeOffsetRef.current = offset;\n const track = slideTrackRef.current;\n if (track) {\n track.style.transition = animate ? \"transform 0.28s cubic-bezier(0.2, 0, 0, 1)\" : \"none\";\n track.style.transform = `translateX(${offset}px)`;\n }\n setSwipeOffset(offset);\n }, []);\n\n const snapBack = useCallback(() => {\n setSlideAnimating(true);\n applySlideOffset(0, true);\n\n const track = slideTrackRef.current;\n let done = false;\n const onEnd = () => {\n if (done) return;\n done = true;\n track?.removeEventListener(\"transitionend\", onEnd);\n setSlideAnimating(false);\n setSlideActive(false);\n };\n if (track) {\n track.addEventListener(\"transitionend\", onEnd, { once: true });\n setTimeout(onEnd, 350);\n }\n }, [applySlideOffset]);\n\n const readyRef = useRef(true);\n\n const commitSlide = useCallback(\n (direction: \"prev\" | \"next\") => {\n if (commitLockRef.current || !readyRef.current) return;\n commitLockRef.current = true;\n readyRef.current = false;\n\n const vw = window.innerWidth;\n const targetOffset = direction === \"prev\" ? vw : -vw;\n setSlideActive(true);\n setSlideAnimating(true);\n // Fire at the START of the slide so overlays (info drawers) can animate\n // out in sync with the image — onNavigate only fires once it completes.\n onSlideStart?.(direction);\n\n requestAnimationFrame(() => {\n applySlideOffset(targetOffset, true);\n\n const track = slideTrackRef.current;\n let cleaned = false;\n\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n track?.removeEventListener(\"transitionend\", onTransitionEnd);\n\n const newIndex = direction === \"prev\" ? currentIndex - 1 : currentIndex + 1;\n if (newIndex < 0 || newIndex >= items.length) {\n commitLockRef.current = false;\n return;\n }\n\n const newItem = items[newIndex];\n const preload = new Image();\n preload.src = newItem.src;\n\n const doNavigate = () => onNavigate(newIndex);\n\n // Add a timeout so a stalled decode can't block navigation forever\n const timeout = setTimeout(doNavigate, 300);\n preload\n .decode()\n .then(() => {\n clearTimeout(timeout);\n doNavigate();\n })\n .catch(() => {\n clearTimeout(timeout);\n doNavigate();\n });\n };\n\n const onTransitionEnd = () => cleanup();\n if (track) {\n track.addEventListener(\"transitionend\", onTransitionEnd, { once: true });\n setTimeout(cleanup, 400);\n }\n });\n },\n [applySlideOffset, currentIndex, items, onNavigate, onSlideStart],\n );\n\n const resolveSlide = useCallback(\n (gestureStartTime: number) => {\n const action = resolveSlideDirection({\n offset: swipeOffsetRef.current,\n elapsedMs: Date.now() - gestureStartTime,\n viewportWidth: window.innerWidth,\n hasPrev,\n hasNext,\n });\n\n if (action === \"prev\") commitSlide(\"prev\");\n else if (action === \"next\") commitSlide(\"next\");\n else snapBack();\n },\n [hasPrev, hasNext, commitSlide, snapBack],\n );\n\n // DOM resets on navigation (pre-paint)\n\n useLayoutEffect(() => {\n const track = slideTrackRef.current;\n if (track) {\n track.style.transition = \"none\";\n track.offsetHeight;\n track.style.transform = \"translateX(0px)\";\n }\n swipeOffsetRef.current = 0;\n commitLockRef.current = false;\n }, [currentIndex]);\n\n // React state cleanup — runs after paint\n useEffect(() => {\n setSwipeOffset(0);\n setSlideAnimating(false);\n setSlideActive(false);\n // Allow next commit only after React has painted the new panel\n readyRef.current = true;\n }, [currentIndex]);\n\n return {\n slideTrackRef,\n slideActive,\n slideAnimating,\n swipeOffset,\n swipeOffsetRef,\n commitLockRef,\n applySlideOffset,\n commitSlide,\n snapBack,\n resolveSlide,\n setSlideActive,\n };\n}\n","import { useCallback, useRef } from \"react\";\nimport type { ImageZoomPanState } from \"./useImageZoomPan\";\nimport type { SlideNavigationState } from \"./useSlideNavigation\";\n\ninterface GestureHandlers {\n handlePointerDown: (e: React.PointerEvent) => void;\n handlePointerMove: (e: React.PointerEvent) => void;\n handlePointerUp: (e: React.PointerEvent) => void;\n handleTouchStart: (e: React.TouchEvent) => void;\n handleTouchMove: (e: React.TouchEvent) => void;\n handleTouchEnd: (e: React.TouchEvent) => void;\n}\n\ninterface PanGesture {\n isDragging: boolean;\n pointerStart: { x: number; y: number };\n translateStart: { x: number; y: number };\n pinchStartDist: number | null;\n pinchStartScale: number;\n pinchMidpoint: { x: number; y: number } | null;\n lastTouchPos: { x: number; y: number } | null;\n}\n\ninterface SlideGesture {\n active: boolean;\n startX: number;\n startY: number;\n startTime: number;\n locked: boolean;\n rejected: boolean;\n}\n\n/**\n * Coordinates zoom/pan and slide gestures, routing pointer and touch events\n * to the appropriate behavior based on current zoom state.\n *\n * When zoomed (scale > 1): pointer/touch drags are pans.\n * When unzoomed (scale === 1): pointer/touch drags are slide-to-navigate.\n * Two-finger touch is always a pinch-zoom.\n */\nexport function useGestureHandler(\n zoomPan: ImageZoomPanState,\n slide: SlideNavigationState,\n hasPrev: boolean,\n hasNext: boolean,\n /** When false, pinch-zoom and double-tap-zoom are disabled. Default true. */\n zoomEnabled = true,\n): GestureHandlers {\n const { transformRef, clampTranslate, setTransform, applyTransform, resetTransform } = zoomPan;\n const { applySlideOffset, resolveSlide, snapBack, setSlideActive, swipeOffsetRef } = slide;\n\n const panRef = useRef<PanGesture>({\n isDragging: false,\n pointerStart: { x: 0, y: 0 },\n translateStart: { x: 0, y: 0 },\n pinchStartDist: null,\n pinchStartScale: 1,\n pinchMidpoint: null,\n lastTouchPos: null,\n });\n\n const slideRef = useRef<SlideGesture>({\n active: false,\n startX: 0,\n startY: 0,\n startTime: 0,\n locked: false,\n rejected: false,\n });\n\n // Double-tap detection for touch\n const lastTapRef = useRef<{ time: number; x: number; y: number }>({\n time: 0,\n x: 0,\n y: 0,\n });\n\n // Shared slide start helper\n\n const beginSlide = useCallback(\n (x: number, y: number) => {\n setSlideActive(true);\n const sg = slideRef.current;\n sg.active = true;\n sg.startX = x;\n sg.startY = y;\n sg.startTime = Date.now();\n sg.locked = false;\n sg.rejected = false;\n },\n [setSlideActive],\n );\n\n const updateSlide = useCallback(\n (clientX: number, clientY: number, lockThreshold: number, angleBias: number) => {\n const sg = slideRef.current;\n if (!sg.active || sg.rejected) return;\n\n const dx = clientX - sg.startX;\n const dy = clientY - sg.startY;\n\n if (!sg.locked) {\n const absDx = Math.abs(dx);\n const absDy = Math.abs(dy);\n if (absDx < lockThreshold && absDy < lockThreshold) return;\n if (absDy > absDx * angleBias) {\n sg.rejected = true;\n return;\n }\n sg.locked = true;\n }\n\n let offset = dx;\n if ((offset > 0 && !hasPrev) || (offset < 0 && !hasNext)) {\n offset *= 0.2; // rubber-band resistance at edges\n }\n applySlideOffset(offset);\n },\n [hasPrev, hasNext, applySlideOffset],\n );\n\n const endSlide = useCallback(\n (allowResolve: boolean) => {\n const sg = slideRef.current;\n if (sg.active && sg.locked && !sg.rejected && allowResolve) {\n const startTime = sg.startTime;\n sg.active = false;\n resolveSlide(startTime);\n } else {\n sg.active = false;\n if (swipeOffsetRef.current === 0) setSlideActive(false);\n }\n },\n [resolveSlide, setSlideActive, swipeOffsetRef],\n );\n\n // Pointer (mouse) handlers\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (e.pointerType === \"touch\") return;\n\n if (transformRef.current.scale > 1) {\n e.preventDefault();\n const p = panRef.current;\n p.isDragging = true;\n p.pointerStart = { x: e.clientX, y: e.clientY };\n p.translateStart = { x: transformRef.current.x, y: transformRef.current.y };\n } else {\n beginSlide(e.clientX, e.clientY);\n }\n },\n [transformRef, beginSlide],\n );\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent) => {\n if (e.pointerType === \"touch\") return;\n\n const p = panRef.current;\n if (p.isDragging && transformRef.current.scale > 1) {\n const dx = e.clientX - p.pointerStart.x;\n const dy = e.clientY - p.pointerStart.y;\n const t = transformRef.current;\n const clamped = clampTranslate(p.translateStart.x + dx, p.translateStart.y + dy, t.scale);\n setTransform({ scale: t.scale, ...clamped });\n return;\n }\n\n // Mouse slide: lockThreshold=4, angleBias=1 (45° cutoff)\n updateSlide(e.clientX, e.clientY, 4, 1);\n },\n [transformRef, clampTranslate, setTransform, updateSlide],\n );\n\n const handlePointerUp = useCallback(\n (e: React.PointerEvent) => {\n if (e.pointerType === \"touch\") return;\n panRef.current.isDragging = false;\n endSlide(true);\n },\n [endSlide],\n );\n\n // Touch handlers\n\n const handleTouchStart = useCallback(\n (e: React.TouchEvent) => {\n const p = panRef.current;\n\n if (e.touches.length === 2 && zoomEnabled) {\n // Pinch start\n const dx = e.touches[0].clientX - e.touches[1].clientX;\n const dy = e.touches[0].clientY - e.touches[1].clientY;\n p.pinchStartDist = Math.hypot(dx, dy);\n p.pinchStartScale = transformRef.current.scale;\n p.pinchMidpoint = {\n x: (e.touches[0].clientX + e.touches[1].clientX) / 2,\n y: (e.touches[0].clientY + e.touches[1].clientY) / 2,\n };\n p.lastTouchPos = null;\n\n // Cancel any slide in progress\n if (slideRef.current.active) {\n slideRef.current.active = false;\n snapBack();\n }\n } else if (e.touches.length === 1) {\n if (transformRef.current.scale > 1) {\n p.lastTouchPos = {\n x: e.touches[0].clientX,\n y: e.touches[0].clientY,\n };\n } else {\n beginSlide(e.touches[0].clientX, e.touches[0].clientY);\n }\n }\n },\n [transformRef, snapBack, beginSlide, zoomEnabled],\n );\n\n const handleTouchMove = useCallback(\n (e: React.TouchEvent) => {\n const p = panRef.current;\n\n if (e.touches.length === 2 && p.pinchStartDist !== null) {\n // Pinch zoom\n const dx = e.touches[0].clientX - e.touches[1].clientX;\n const dy = e.touches[0].clientY - e.touches[1].clientY;\n const dist = Math.hypot(dx, dy);\n const ratio = dist / p.pinchStartDist;\n const nextScale = Math.min(5, Math.max(1, p.pinchStartScale * ratio));\n const t = transformRef.current;\n const clamped = nextScale <= 1 ? { x: 0, y: 0 } : clampTranslate(t.x, t.y, nextScale);\n\n const next = { scale: nextScale, ...clamped };\n transformRef.current = next;\n applyTransform(next);\n // Sync display state for UI\n // (We set displayScale indirectly through setTransform would cause extra work,\n // so we just write to transformRef + applyTransform, and let touchEnd sync.)\n } else if (e.touches.length === 1 && p.lastTouchPos && transformRef.current.scale > 1) {\n // Zoomed pan\n const touch = e.touches[0];\n const dx = touch.clientX - p.lastTouchPos.x;\n const dy = touch.clientY - p.lastTouchPos.y;\n p.lastTouchPos = { x: touch.clientX, y: touch.clientY };\n\n const t = transformRef.current;\n const clamped = clampTranslate(t.x + dx, t.y + dy, t.scale);\n const next = { scale: t.scale, ...clamped };\n transformRef.current = next;\n applyTransform(next);\n } else if (e.touches.length === 1) {\n // Touch slide: lockThreshold=6, angleBias=0.8\n const touch = e.touches[0];\n updateSlide(touch.clientX, touch.clientY, 6, 0.8);\n }\n },\n [transformRef, clampTranslate, applyTransform, updateSlide],\n );\n\n const handleTouchEnd = useCallback(\n (e: React.TouchEvent) => {\n const p = panRef.current;\n const wasPinch = p.pinchStartDist !== null;\n p.pinchStartDist = null;\n p.pinchMidpoint = null;\n\n if (e.touches.length === 0 && transformRef.current.scale <= 1) {\n // Resolve slide if active\n const sg = slideRef.current;\n if (sg.active && sg.locked && !sg.rejected) {\n const startTime = sg.startTime;\n sg.active = false;\n resolveSlide(startTime);\n transformRef.current = { scale: 1, x: 0, y: 0 };\n return;\n }\n sg.active = false;\n resetTransform();\n }\n\n // One finger remaining after pinch → start pan from that finger\n if (e.touches.length === 1 && transformRef.current.scale > 1) {\n p.lastTouchPos = {\n x: e.touches[0].clientX,\n y: e.touches[0].clientY,\n };\n } else {\n p.lastTouchPos = null;\n }\n\n // Double-tap detection (single finger, not after pinch, not after slide)\n const sg = slideRef.current;\n if (\n zoomEnabled &&\n e.touches.length === 0 &&\n e.changedTouches.length === 1 &&\n !wasPinch &&\n !sg.locked\n ) {\n const touch = e.changedTouches[0];\n const now = Date.now();\n const last = lastTapRef.current;\n const timeDelta = now - last.time;\n const distDelta = Math.hypot(touch.clientX - last.x, touch.clientY - last.y);\n\n if (timeDelta < 300 && distDelta < 30) {\n lastTapRef.current = { time: 0, x: 0, y: 0 };\n if (transformRef.current.scale > 1) {\n resetTransform();\n } else {\n setTransform({ scale: 2.5, x: 0, y: 0 }, true);\n }\n } else {\n lastTapRef.current = { time: now, x: touch.clientX, y: touch.clientY };\n }\n }\n\n // Cleanup slide if released without committing\n if (e.touches.length === 0 && sg.active && !sg.locked) {\n sg.active = false;\n if (swipeOffsetRef.current === 0) setSlideActive(false);\n }\n },\n [\n transformRef,\n resetTransform,\n setTransform,\n resolveSlide,\n setSlideActive,\n swipeOffsetRef,\n zoomEnabled,\n ],\n );\n\n return {\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n handleTouchStart,\n handleTouchMove,\n handleTouchEnd,\n };\n}\n","import { useEffect, useState, type RefObject } from \"react\";\n\n/**\n * Measures the height of the top and bottom bars so the image area\n * can be constrained to fit between them.\n */\nexport function useBarMeasure(\n topBarRef: RefObject<HTMLDivElement | null>,\n bottomBarRef: RefObject<HTMLDivElement | null>,\n /** Re-measure whenever this key changes (e.g. currentIndex) */\n measureKey: unknown,\n) {\n const [topBarH, setTopBarH] = useState(0);\n const [bottomBarH, setBottomBarH] = useState(0);\n\n useEffect(() => {\n const measure = () => {\n if (topBarRef.current) setTopBarH(topBarRef.current.offsetHeight);\n if (bottomBarRef.current) setBottomBarH(bottomBarRef.current.offsetHeight);\n };\n measure();\n\n const ro = new ResizeObserver(measure);\n if (topBarRef.current) ro.observe(topBarRef.current);\n if (bottomBarRef.current) ro.observe(bottomBarRef.current);\n return () => ro.disconnect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [measureKey]);\n\n return { topBarH, bottomBarH };\n}\n","import { useEffect } from \"react\";\n\n/**\n * Locks scrolling on the document body while `isLocked` is true (e.g. while the\n * lightbox is open), so content behind the overlay can't be scrolled. To\n * prevent the content from shifting when the scrollbar disappears, the width\n * the scrollbar occupied is added back as right padding while locked. Restores\n * the previous overflow/padding values on unlock/unmount, and reference-counts\n * concurrent locks so closing one overlay doesn't release a lock held by\n * another.\n *\n * SSR-safe: the effect only runs in the browser, so importing this on the\n * server is a no-op.\n */\nlet lockCount = 0;\nlet previousOverflow = \"\";\nlet previousPaddingRight = \"\";\n\nexport function useBodyScrollLock(isLocked: boolean): void {\n useEffect(() => {\n if (!isLocked) return;\n if (typeof document === \"undefined\") return;\n\n if (lockCount === 0) {\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;\n\n previousOverflow = document.body.style.overflow;\n previousPaddingRight = document.body.style.paddingRight;\n\n document.body.style.overflow = \"hidden\";\n if (scrollbarWidth > 0) {\n const currentPaddingRight =\n parseFloat(window.getComputedStyle(document.body).paddingRight) || 0;\n document.body.style.paddingRight = `${currentPaddingRight + scrollbarWidth}px`;\n }\n }\n lockCount += 1;\n\n return () => {\n lockCount -= 1;\n if (lockCount === 0) {\n document.body.style.overflow = previousOverflow;\n document.body.style.paddingRight = previousPaddingRight;\n }\n };\n }, [isLocked]);\n}\n","import { useEffect, type RefObject } from \"react\";\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Traps Tab focus within `containerRef` while `active`, and restores focus to\n * the previously-focused element on deactivate/unmount. SSR-safe (effect only\n * runs in the browser).\n */\nexport function useFocusTrap(containerRef: RefObject<HTMLElement | null>, active: boolean): void {\n useEffect(() => {\n if (!active) return;\n if (typeof document === \"undefined\") return;\n\n const previouslyFocused = document.activeElement as HTMLElement | null;\n const container = containerRef.current;\n\n // Move focus into the dialog so screen readers/keyboard land inside it.\n container?.focus();\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\" || !container) return;\n const focusable = Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => el.offsetParent !== null || el === document.activeElement,\n );\n if (focusable.length === 0) {\n e.preventDefault();\n container.focus();\n return;\n }\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeEl = document.activeElement;\n\n if (e.shiftKey && (activeEl === first || activeEl === container)) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && activeEl === last) {\n e.preventDefault();\n first.focus();\n }\n };\n\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n previouslyFocused?.focus?.();\n };\n }, [containerRef, active]);\n}\n","import type { SVGProps } from \"react\";\nimport type { ViewerIcons } from \"../types\";\n\n// Inline default icons so the package has no runtime icon dependency (e.g.\n// lucide-react). Each is a 24x24 stroked glyph that inherits `currentColor`.\n// Consumers can override any of them via the `icons` prop.\n\nfunction base(props: SVGProps<SVGSVGElement>) {\n return {\n width: 18,\n height: 18,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.75,\n strokeLinecap: \"round\" as const,\n strokeLinejoin: \"round\" as const,\n \"aria-hidden\": true,\n focusable: false,\n ...props,\n };\n}\n\nexport function CloseIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg {...base(props)}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nexport function ZoomInIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg {...base(props)}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n <path d=\"M11 8v6\" />\n <path d=\"M8 11h6\" />\n </svg>\n );\n}\n\nexport function ZoomOutIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg {...base(props)}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n <path d=\"M8 11h6\" />\n </svg>\n );\n}\n\nexport function ChevronLeftIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg {...base({ width: 36, height: 36, strokeWidth: 1.5, ...props })}>\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n );\n}\n\nexport function ChevronRightIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg {...base({ width: 36, height: 36, strokeWidth: 1.5, ...props })}>\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n );\n}\n\n/** The full default icon set, merged with any consumer overrides. */\nexport const defaultIcons: ViewerIcons = {\n close: <CloseIcon />,\n zoomIn: <ZoomInIcon />,\n zoomOut: <ZoomOutIcon />,\n prev: <ChevronLeftIcon />,\n next: <ChevronRightIcon />,\n};\n","/** Tiny className joiner: drops falsy values and joins with a space. */\nexport function cx(...parts: Array<string | false | null | undefined>): string {\n return parts.filter(Boolean).join(\" \");\n}\n","import type { ReactNode } from \"react\";\nimport { cx } from \"./cx\";\n\ninterface NavButtonProps {\n direction: \"prev\" | \"next\";\n enabled: boolean;\n onClick: () => void;\n icon: ReactNode;\n className?: string;\n}\n\nexport function NavButton({ direction, enabled, onClick, icon, className }: NavButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n if (enabled) onClick();\n }}\n disabled={!enabled}\n className={cx(\"rvl-nav-btn\", className)}\n aria-label={direction === \"prev\" ? \"Previous image\" : \"Next image\"}\n >\n {icon}\n </button>\n );\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ImageViewerProps, ViewerContext } from \"../types\";\nimport { useImageZoomPan, MIN_SCALE, MAX_SCALE } from \"../hooks/useImageZoomPan\";\nimport { useSlideNavigation } from \"../hooks/useSlideNavigation\";\nimport { useGestureHandler } from \"../hooks/useGestureHandler\";\nimport { useBarMeasure } from \"../hooks/useBarMeasure\";\nimport { useBodyScrollLock } from \"../hooks/useBodyScrollLock\";\nimport { useFocusTrap } from \"../hooks/useFocusTrap\";\nimport { defaultIcons } from \"./icons\";\nimport { NavButton } from \"./NavButton\";\nimport { cx } from \"./cx\";\n\nconst ANIM_MS = 250;\nconst IMG_PADDING = 44;\n\nfunction prefersReducedMotion(): boolean {\n if (typeof window === \"undefined\" || !window.matchMedia) return false;\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/**\n * Batteries-included fullscreen image viewer: zoom, pan, pinch, and swipe\n * navigation with themeable chrome and render slots. Controlled via `index` /\n * `onIndexChange`; mount it when open and it runs its own enter/exit animation,\n * calling `onClose` after the exit completes.\n */\nexport function ImageViewer<TData = unknown>({\n items,\n index,\n onIndexChange,\n onNavigate,\n onClose,\n zoom = true,\n showCounter = true,\n loop = false,\n renderHeader,\n renderHeaderActions,\n renderNavStart,\n renderNavEnd,\n renderFooter,\n renderOverlay,\n classNames,\n icons,\n ariaLabel,\n}: ImageViewerProps<TData>) {\n const [visible, setVisible] = useState(false);\n const [closing, setClosing] = useState(false);\n const [isTouchDevice, setIsTouchDevice] = useState(false);\n const [contentShift, setContentShiftState] = useState<{\n transform: string | null;\n animate: boolean;\n }>({ transform: null, animate: true });\n\n const containerRef = useRef<HTMLDivElement>(null);\n const imgWrapperRef = useRef<HTMLDivElement>(null);\n const topBarRef = useRef<HTMLDivElement>(null);\n const bottomBarRef = useRef<HTMLDivElement>(null);\n\n const [viewportWidth, setViewportWidth] = useState(() =>\n typeof window === \"undefined\" ? 0 : window.innerWidth,\n );\n\n const item = items[index];\n\n const hasPrevLinear = index > 0;\n const hasNextLinear = index < items.length - 1;\n const hasPrev = loop ? items.length > 1 : hasPrevLinear;\n const hasNext = loop ? items.length > 1 : hasNextLinear;\n\n const mergedIcons = useMemo(() => ({ ...defaultIcons, ...icons }), [icons]);\n const cn = (slot: keyof NonNullable<ImageViewerProps[\"classNames\"]>) => classNames?.[slot];\n\n useBodyScrollLock(true);\n useFocusTrap(containerRef, visible && !closing);\n const { topBarH, bottomBarH } = useBarMeasure(topBarRef, bottomBarRef, index);\n\n const zoomPan = useImageZoomPan(imgWrapperRef, index, zoom);\n const {\n imgRef,\n displayScale,\n isZoomed,\n transformRef,\n resetTransform,\n setTransform,\n clampTranslate,\n measureBaseDims,\n handleDoubleClick,\n } = zoomPan;\n\n const slide = useSlideNavigation(items, index, onIndexChange, onNavigate);\n const { slideTrackRef, slideActive, slideAnimating, swipeOffset, commitSlide } = slide;\n\n const gestures = useGestureHandler(zoomPan, slide, hasPrevLinear, hasNextLinear, zoom);\n\n useEffect(() => {\n setIsTouchDevice(\"ontouchstart\" in window || navigator.maxTouchPoints > 0);\n }, []);\n\n useEffect(() => {\n const onResize = () => setViewportWidth(window.innerWidth);\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n useEffect(() => {\n const raf = requestAnimationFrame(() => setVisible(true));\n return () => cancelAnimationFrame(raf);\n }, []);\n\n const handleClose = useCallback(() => {\n setClosing(true);\n setVisible(false);\n const delay = prefersReducedMotion() ? 0 : ANIM_MS;\n setTimeout(onClose, delay);\n }, [onClose]);\n\n const navigate = useCallback(\n (dir: \"prev\" | \"next\") => {\n if (dir === \"prev\") {\n if (hasPrevLinear) commitSlide(\"prev\");\n else if (loop) {\n // Wrap jumps without a slide animation, so commitSlide's onSlideStart\n // never fires — emit it here so overlays still react.\n onNavigate?.(\"prev\");\n onIndexChange(items.length - 1);\n }\n } else {\n if (hasNextLinear) commitSlide(\"next\");\n else if (loop) {\n onNavigate?.(\"next\");\n onIndexChange(0);\n }\n }\n },\n [hasPrevLinear, hasNextLinear, loop, commitSlide, onIndexChange, onNavigate, items.length],\n );\n\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n handleClose();\n return;\n }\n if (displayScale > 1) return;\n if (e.key === \"ArrowLeft\" && hasPrev) navigate(\"prev\");\n if (e.key === \"ArrowRight\" && hasNext) navigate(\"next\");\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [handleClose, hasPrev, hasNext, displayScale, navigate]);\n\n const setContentShift = useCallback((transform: string | null, animate = true) => {\n setContentShiftState({ transform, animate });\n }, []);\n\n const ctx: ViewerContext<TData> = {\n items,\n index,\n item: item!,\n total: items.length,\n hasPrev,\n hasNext,\n goPrev: () => navigate(\"prev\"),\n goNext: () => navigate(\"next\"),\n goTo: (i: number) => {\n if (i !== index && i >= 0 && i < items.length) onIndexChange(i);\n },\n close: handleClose,\n isZoomed,\n displayScale,\n zoomIn: () => {\n const t = transformRef.current;\n const next = Math.min(MAX_SCALE, t.scale * 1.3);\n const clamped = clampTranslate(t.x, t.y, next);\n setTransform({ scale: next, ...clamped }, true);\n },\n zoomOut: () => {\n const t = transformRef.current;\n const next = Math.max(MIN_SCALE, t.scale / 1.3);\n const clamped = next <= 1 ? { x: 0, y: 0 } : clampTranslate(t.x, t.y, next);\n setTransform({ scale: next, ...clamped }, true);\n },\n resetZoom: resetTransform,\n isTouchDevice,\n topBarHeight: topBarH,\n bottomBarHeight: bottomBarH,\n setContentShift,\n };\n\n if (!item) return null;\n\n const reservedH = bottomBarH + IMG_PADDING * 2;\n const imgMaxHeight = `calc(100vh - ${reservedH}px)`;\n const imgStyle: React.CSSProperties = { maxHeight: imgMaxHeight };\n\n const totalDigits = String(items.length).length;\n const counterMinWidth = `${totalDigits * 2 * 0.6 + 1.5}em`;\n\n const prevItem = hasPrevLinear ? items[index - 1] : null;\n const nextItem = hasNextLinear ? items[index + 1] : null;\n const showAdjacent = slideActive || slideAnimating || swipeOffset !== 0;\n const adjacentOpacity = Math.min(1, Math.abs(swipeOffset) / (viewportWidth * 0.8 || 1));\n\n const showZoomControls = zoom && !isTouchDevice;\n const headerActions = renderHeaderActions?.(ctx);\n const navStart = renderNavStart?.(ctx);\n const navEnd = renderNavEnd?.(ctx);\n const hasNavGroup = hasPrev || hasNext;\n const showNavRow = !isZoomed && (hasNavGroup || navStart != null || navEnd != null);\n\n return (\n <div\n ref={containerRef}\n className={cx(\"rvl-root\", visible && !closing && \"rvl-visible\", cn(\"root\"))}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel ?? item.alt ?? \"Image viewer\"}\n tabIndex={-1}\n >\n <div\n className={cx(\"rvl-backdrop\", cn(\"backdrop\"))}\n onClick={handleClose}\n aria-hidden=\"true\"\n />\n\n <div ref={topBarRef} className={cx(\"rvl-bar\", \"rvl-top-bar\", cn(\"topBar\"))}>\n <div className={cx(\"rvl-header\", cn(\"topBar\"))}>{renderHeader?.(ctx)}</div>\n\n <div className=\"rvl-header-actions\">\n {headerActions}\n\n {showZoomControls && isZoomed && (\n <button\n type=\"button\"\n className={cx(\"rvl-btn\", \"rvl-btn-scale\", cn(\"button\"))}\n onClick={(e) => {\n e.stopPropagation();\n resetTransform();\n }}\n title=\"Reset zoom\"\n aria-label=\"Reset zoom\"\n >\n {Math.round(displayScale * 100)}%\n </button>\n )}\n\n {showZoomControls && (\n <button\n type=\"button\"\n className={cx(\"rvl-btn\", cn(\"button\"))}\n onClick={(e) => {\n e.stopPropagation();\n ctx.zoomIn();\n }}\n title=\"Zoom in\"\n aria-label=\"Zoom in\"\n >\n {mergedIcons.zoomIn}\n </button>\n )}\n\n {showZoomControls && (\n <button\n type=\"button\"\n className={cx(\"rvl-btn\", cn(\"button\"))}\n onClick={(e) => {\n e.stopPropagation();\n ctx.zoomOut();\n }}\n title=\"Zoom out\"\n aria-label=\"Zoom out\"\n >\n {mergedIcons.zoomOut}\n </button>\n )}\n\n <button\n type=\"button\"\n className={cx(\"rvl-btn\", cn(\"button\"))}\n onClick={(e) => {\n e.stopPropagation();\n handleClose();\n }}\n title=\"Close (Esc)\"\n aria-label=\"Close\"\n >\n {mergedIcons.close}\n </button>\n </div>\n </div>\n\n <div\n className=\"rvl-stage\"\n style={{\n transform: contentShift.transform ?? \"translateY(0)\",\n // animate=false snaps with no transition (overrides the CSS transition)\n transition: contentShift.animate ? undefined : \"none\",\n }}\n >\n <div\n ref={slideTrackRef}\n className={cx(\"rvl-track\", visible && !closing && \"rvl-track-visible\")}\n >\n {showAdjacent && prevItem && (\n <div\n className=\"rvl-adjacent\"\n style={{ transform: `translateX(-${viewportWidth}px)`, opacity: adjacentOpacity }}\n >\n <img\n src={prevItem.src}\n alt=\"\"\n className={cx(\"rvl-img\", cn(\"image\"))}\n style={imgStyle}\n draggable={false}\n />\n </div>\n )}\n\n <div\n ref={imgWrapperRef}\n className=\"rvl-img-wrapper\"\n onClick={(e) => e.stopPropagation()}\n onDoubleClick={handleDoubleClick}\n onPointerDown={gestures.handlePointerDown}\n onPointerMove={gestures.handlePointerMove}\n onPointerUp={gestures.handlePointerUp}\n onPointerLeave={gestures.handlePointerUp}\n onTouchStart={gestures.handleTouchStart}\n onTouchMove={gestures.handleTouchMove}\n onTouchEnd={gestures.handleTouchEnd}\n >\n <img\n ref={imgRef}\n src={item.src}\n alt={item.alt ?? \"\"}\n className={cx(\"rvl-img\", cn(\"image\"))}\n style={imgStyle}\n draggable={false}\n onLoad={measureBaseDims}\n />\n </div>\n\n {showAdjacent && nextItem && (\n <div\n className=\"rvl-adjacent\"\n style={{ transform: `translateX(${viewportWidth}px)`, opacity: adjacentOpacity }}\n >\n <img\n src={nextItem.src}\n alt=\"\"\n className={cx(\"rvl-img\", cn(\"image\"))}\n style={imgStyle}\n draggable={false}\n />\n </div>\n )}\n </div>\n </div>\n\n <div ref={bottomBarRef} className={cx(\"rvl-bar\", \"rvl-bottom-bar\", cn(\"bottomBar\"))}>\n {showNavRow && (\n <div className=\"rvl-nav-row\">\n <div className=\"rvl-nav-inner\">\n {navStart != null && (\n <div className={cx(\"rvl-nav-start\", cn(\"navStart\"))}>{navStart}</div>\n )}\n {hasNavGroup && (\n <div className=\"rvl-nav-group\">\n <NavButton\n direction=\"prev\"\n enabled={hasPrev}\n onClick={() => navigate(\"prev\")}\n icon={mergedIcons.prev}\n className={cn(\"navButton\")}\n />\n {showCounter && (\n <span\n className={cx(\"rvl-counter\", cn(\"counter\"))}\n style={{ minWidth: counterMinWidth }}\n >\n {index + 1} / {items.length}\n </span>\n )}\n <NavButton\n direction=\"next\"\n enabled={hasNext}\n onClick={() => navigate(\"next\")}\n icon={mergedIcons.next}\n className={cn(\"navButton\")}\n />\n </div>\n )}\n {navEnd != null && <div className={cx(\"rvl-nav-end\", cn(\"navEnd\"))}>{navEnd}</div>}\n </div>\n </div>\n )}\n\n {renderFooter && <div className=\"rvl-footer\">{renderFooter(ctx)}</div>}\n </div>\n\n {renderOverlay && (\n <div className={cx(\"rvl-overlay\", cn(\"overlay\"))}>{renderOverlay(ctx)}</div>\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/hooks/math.ts","../src/hooks/useImageZoomPan.ts","../src/hooks/useSlideNavigation.ts","../src/hooks/useGestureHandler.ts","../src/hooks/useBarMeasure.ts","../src/hooks/useBodyScrollLock.ts","../src/hooks/useFocusTrap.ts","../src/components/icons.tsx","../src/components/cx.ts","../src/components/NavButton.tsx","../src/components/ImageViewer.tsx"],"names":["clampTranslate","useRef","useState","useCallback","useLayoutEffect","useEffect","sg","jsx","jsxs"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Pure geometry/threshold helpers shared by the interaction hooks. Kept free of\n * React and DOM globals so they can be unit-tested in isolation.\n */\n\nexport interface Dims {\n width: number;\n height: number;\n}\n\n/**\n * Clamp a pan translation so the scaled image edge can't move past the\n * viewport edge. Returns `{ x: 0, y: 0 }` when not zoomed or when base\n * dimensions are unknown.\n */\nexport function clampTranslate(\n x: number,\n y: number,\n scale: number,\n baseDims: Dims,\n viewport: Dims,\n): { x: number; y: number } {\n if (scale <= 1) return { x: 0, y: 0 };\n const { width: baseW, height: baseH } = baseDims;\n if (baseW === 0 || baseH === 0) return { x: 0, y: 0 };\n\n const scaledHalfW = (baseW * scale) / 2;\n const scaledHalfH = (baseH * scale) / 2;\n const vpHalfW = viewport.width / 2;\n const vpHalfH = viewport.height / 2;\n\n const maxX = Math.max(0, scaledHalfW - vpHalfW);\n const maxY = Math.max(0, scaledHalfH - vpHalfH);\n\n return {\n x: Math.max(-maxX, Math.min(maxX, x)),\n y: Math.max(-maxY, Math.min(maxY, y)),\n };\n}\n\n/**\n * Compute the pan translation that keeps the content under a focal point\n * (cursor or pinch midpoint) anchored as the scale changes from `prevScale`\n * to `nextScale`.\n *\n * The viewer scales the wrapper about the viewport center, so the on-screen\n * position of a content point is `center + scale * (point - center) + t`.\n * Solving \"the content at `focal` before the zoom is still at `focal` after\"\n * for the new translate gives the closed form below. Pass `focal` in viewport\n * coordinates (e.g. `clientX`/`clientY`). The result is unclamped — feed it\n * through {@link clampTranslate} before applying.\n */\nexport function zoomToPoint(\n prevScale: number,\n nextScale: number,\n prev: { x: number; y: number },\n focal: { x: number; y: number },\n viewport: Dims,\n): { x: number; y: number } {\n const relX = focal.x - viewport.width / 2;\n const relY = focal.y - viewport.height / 2;\n const k = nextScale / prevScale;\n return {\n x: relX * (1 - k) + k * prev.x,\n y: relY * (1 - k) + k * prev.y,\n };\n}\n\nexport type SlideAction = \"prev\" | \"next\" | \"snap\";\n\nexport interface ResolveSlideArgs {\n /** Current horizontal swipe offset in px (positive = dragged right). */\n offset: number;\n /** Elapsed time of the gesture in ms (used for fling velocity). */\n elapsedMs: number;\n viewportWidth: number;\n hasPrev: boolean;\n hasNext: boolean;\n /** Fraction of viewport width past which a drag commits. Default 0.25. */\n distanceThreshold?: number;\n /** px/ms past which a fast fling commits regardless of distance. Default 0.4. */\n velocityThreshold?: number;\n}\n\n/**\n * Decide whether a released swipe should navigate `prev`/`next` or `snap` back,\n * based on distance and fling velocity.\n */\nexport function resolveSlideDirection({\n offset,\n elapsedMs,\n viewportWidth,\n hasPrev,\n hasNext,\n distanceThreshold = 0.25,\n velocityThreshold = 0.4,\n}: ResolveSlideArgs): SlideAction {\n const velocity = Math.abs(offset) / Math.max(elapsedMs, 1);\n const threshold = viewportWidth * distanceThreshold;\n const committed = Math.abs(offset) > threshold || velocity > velocityThreshold;\n\n if (offset > 0 && hasPrev && committed) return \"prev\";\n if (offset < 0 && hasNext && committed) return \"next\";\n return \"snap\";\n}\n","import { useCallback, useEffect, useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport { clampTranslate as clampTranslatePure, zoomToPoint } from \"./math\";\n\nconst MIN_SCALE = 1;\nconst MAX_SCALE = 5;\n\nexport interface ImageTransform {\n scale: number;\n x: number;\n y: number;\n}\n\nexport interface ImageZoomPanState {\n imgRef: RefObject<HTMLImageElement | null>;\n displayScale: number;\n isZoomed: boolean;\n transformRef: React.MutableRefObject<ImageTransform>;\n\n /** Base (unscaled) image dimensions for clamp calculations */\n baseDimsRef: React.MutableRefObject<{ width: number; height: number }>;\n\n resetTransform: () => void;\n setTransform: (t: ImageTransform, animate?: boolean) => void;\n applyTransform: (t: ImageTransform, animate?: boolean) => void;\n clampTranslate: (x: number, y: number, scale: number) => { x: number; y: number };\n measureBaseDims: () => void;\n handleDoubleClick: (e: React.MouseEvent) => void;\n}\n\n/**\n * Manages zoom/pan state for an image viewer.\n *\n * Applies scale + translate transforms to the **wrapper** element rather\n * than the image itself. This avoids an iOS Safari compositing bug where\n * CSS scale() on an element clips its painted output to the element's\n * original layout bounds.\n *\n * When zoomed, the wrapper is positioned absolute inset-0 (full viewport),\n * so its layout bounds already match the viewport and scaling it won't clip.\n * The image stays at its natural constrained size, centered via flexbox.\n */\nexport function useImageZoomPan(\n imgWrapperRef: RefObject<HTMLDivElement | null>,\n currentIndex: number,\n /** When false, wheel-zoom and double-click-zoom are disabled. Default true. */\n enabled = true,\n /**\n * When true (default), wheel-zoom anchors on the cursor. When false, it zooms\n * about the viewport center.\n */\n zoomToCursor = true,\n): ImageZoomPanState {\n const imgRef = useRef<HTMLImageElement>(null);\n const [displayScale, setDisplayScale] = useState(1);\n const transformRef = useRef<ImageTransform>({ scale: 1, x: 0, y: 0 });\n const baseDimsRef = useRef<{ width: number; height: number }>({ width: 0, height: 0 });\n\n // Core helpers\n\n const applyTransform = useCallback(\n (t: ImageTransform, animate = false) => {\n const wrapper = imgWrapperRef.current;\n if (!wrapper) return;\n wrapper.style.transition = animate ? \"transform 0.2s ease-out\" : \"none\";\n\n if (t.scale <= 1) {\n wrapper.style.transform = \"none\";\n wrapper.style.position = \"\";\n wrapper.style.inset = \"\";\n wrapper.style.zIndex = \"\";\n wrapper.style.backgroundColor = \"\";\n wrapper.style.cursor = \"\";\n } else {\n wrapper.style.transform = `scale(${t.scale}) translate(${t.x / t.scale}px, ${t.y / t.scale}px)`;\n wrapper.style.position = \"absolute\";\n wrapper.style.inset = \"0\";\n wrapper.style.zIndex = \"30\";\n wrapper.style.backgroundColor = \"black\";\n wrapper.style.cursor = \"grab\";\n }\n\n // Keep React state in sync so isZoomed reflects reality\n setDisplayScale(t.scale);\n },\n [imgWrapperRef],\n );\n\n const setTransform = useCallback(\n (t: ImageTransform, animate = false) => {\n transformRef.current = t;\n applyTransform(t, animate);\n setDisplayScale(t.scale);\n },\n [applyTransform],\n );\n\n const resetTransform = useCallback(() => {\n setTransform({ scale: 1, x: 0, y: 0 }, true);\n }, [setTransform]);\n\n const measureBaseDims = useCallback(() => {\n const img = imgRef.current;\n if (!img) return;\n baseDimsRef.current = { width: img.offsetWidth, height: img.offsetHeight };\n }, []);\n\n /**\n * Clamp so the image edge can't pan past the viewport edge.\n */\n const clampTranslate = useCallback(\n (x: number, y: number, scale: number): { x: number; y: number } =>\n clampTranslatePure(x, y, scale, baseDimsRef.current, {\n width: window.innerWidth,\n height: window.innerHeight,\n }),\n [],\n );\n\n // Reset on navigation\n\n useLayoutEffect(() => {\n const wrapper = imgWrapperRef.current;\n if (wrapper) {\n wrapper.style.transition = \"none\";\n wrapper.style.transform = \"none\";\n wrapper.style.position = \"\";\n wrapper.style.inset = \"\";\n wrapper.style.zIndex = \"\";\n wrapper.style.backgroundColor = \"\";\n wrapper.style.cursor = \"\";\n }\n transformRef.current = { scale: 1, x: 0, y: 0 };\n }, [currentIndex, imgWrapperRef]);\n\n useEffect(() => {\n setDisplayScale(1);\n }, [currentIndex]);\n\n // Wheel zoom (desktop)\n\n useEffect(() => {\n if (!enabled) return;\n const wrapper = imgWrapperRef.current;\n if (!wrapper) return;\n\n const handleWheel = (e: WheelEvent) => {\n e.preventDefault();\n\n // Ensure base dims\n if (baseDimsRef.current.width === 0) {\n const img = imgRef.current;\n if (img) baseDimsRef.current = { width: img.offsetWidth, height: img.offsetHeight };\n }\n\n const t = transformRef.current;\n\n let dy = e.deltaY;\n if (e.deltaMode === 1) dy *= 16;\n if (e.deltaMode === 2) dy *= 100;\n\n const normalized = Math.max(-100, Math.min(100, dy));\n const step = -(normalized / 100) * 0.05;\n const factor = 1 + step;\n\n const nextScale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, t.scale * factor));\n let clamped: { x: number; y: number };\n if (nextScale <= 1) {\n clamped = { x: 0, y: 0 };\n } else if (zoomToCursor) {\n const focal = zoomToPoint(\n t.scale,\n nextScale,\n { x: t.x, y: t.y },\n { x: e.clientX, y: e.clientY },\n { width: window.innerWidth, height: window.innerHeight },\n );\n clamped = clampTranslate(focal.x, focal.y, nextScale);\n } else {\n clamped = clampTranslate(t.x, t.y, nextScale);\n }\n setTransform({ scale: nextScale, ...clamped });\n };\n\n wrapper.addEventListener(\"wheel\", handleWheel, { passive: false });\n return () => wrapper.removeEventListener(\"wheel\", handleWheel);\n }, [imgWrapperRef, setTransform, clampTranslate, enabled, zoomToCursor]);\n\n // Double-click toggle\n\n const handleDoubleClick = useCallback(\n (e: React.MouseEvent) => {\n if (!enabled) return;\n e.stopPropagation();\n\n // Ensure base dims\n if (baseDimsRef.current.width === 0) {\n const img = imgRef.current;\n if (img) baseDimsRef.current = { width: img.offsetWidth, height: img.offsetHeight };\n }\n\n if (transformRef.current.scale > 1) {\n resetTransform();\n } else {\n setTransform({ scale: 1.8, x: 0, y: 0 }, true);\n }\n },\n [resetTransform, setTransform, enabled],\n );\n\n return {\n imgRef,\n displayScale,\n isZoomed: displayScale > 1,\n transformRef,\n baseDimsRef,\n resetTransform,\n setTransform,\n applyTransform,\n clampTranslate,\n measureBaseDims,\n handleDoubleClick,\n };\n}\n\nexport { MIN_SCALE, MAX_SCALE };\n","import { useCallback, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport type { ViewerItem } from \"../types\";\nimport { resolveSlideDirection } from \"./math\";\n\nexport interface SlideNavigationState {\n slideTrackRef: React.RefObject<HTMLDivElement | null>;\n slideActive: boolean;\n slideAnimating: boolean;\n swipeOffset: number;\n swipeOffsetRef: React.MutableRefObject<number>;\n commitLockRef: React.MutableRefObject<boolean>;\n\n applySlideOffset: (offset: number, animate?: boolean) => void;\n commitSlide: (direction: \"prev\" | \"next\") => void;\n snapBack: () => void;\n resolveSlide: (gestureStartTime: number) => void;\n setSlideActive: React.Dispatch<React.SetStateAction<boolean>>;\n}\n\n/**\n * Manages the three-slot slide carousel: swipe offset tracking, animated\n * commit/snap-back, and DOM resets on navigation.\n *\n * `items[i].src` is treated as a final, ready-to-load url — the next image is\n * preloaded/decoded before navigation commits so the swipe lands on a painted\n * frame.\n */\nexport function useSlideNavigation(\n items: ViewerItem[],\n currentIndex: number,\n onNavigate: (index: number) => void,\n onSlideStart?: (direction: \"prev\" | \"next\") => void,\n /** When true, navigation wraps around the ends instead of stopping. */\n loop = false,\n): SlideNavigationState {\n const slideTrackRef = useRef<HTMLDivElement>(null);\n const swipeOffsetRef = useRef(0);\n const [swipeOffset, setSwipeOffset] = useState(0);\n const [slideAnimating, setSlideAnimating] = useState(false);\n const [slideActive, setSlideActive] = useState(false);\n const commitLockRef = useRef(false);\n\n // With loop on, every interior position has a neighbor in both directions as\n // long as there's more than one item to wrap to.\n const hasPrev = loop ? items.length > 1 : currentIndex > 0;\n const hasNext = loop ? items.length > 1 : currentIndex < items.length - 1;\n\n const applySlideOffset = useCallback((offset: number, animate = false) => {\n swipeOffsetRef.current = offset;\n const track = slideTrackRef.current;\n if (track) {\n track.style.transition = animate ? \"transform 0.28s cubic-bezier(0.2, 0, 0, 1)\" : \"none\";\n track.style.transform = `translateX(${offset}px)`;\n }\n setSwipeOffset(offset);\n }, []);\n\n const snapBack = useCallback(() => {\n setSlideAnimating(true);\n applySlideOffset(0, true);\n\n const track = slideTrackRef.current;\n let done = false;\n const onEnd = () => {\n if (done) return;\n done = true;\n track?.removeEventListener(\"transitionend\", onEnd);\n setSlideAnimating(false);\n setSlideActive(false);\n };\n if (track) {\n track.addEventListener(\"transitionend\", onEnd, { once: true });\n setTimeout(onEnd, 350);\n }\n }, [applySlideOffset]);\n\n const readyRef = useRef(true);\n\n const commitSlide = useCallback(\n (direction: \"prev\" | \"next\") => {\n if (commitLockRef.current || !readyRef.current) return;\n commitLockRef.current = true;\n readyRef.current = false;\n\n const vw = window.innerWidth;\n const targetOffset = direction === \"prev\" ? vw : -vw;\n setSlideActive(true);\n setSlideAnimating(true);\n // Fire at the START of the slide so overlays (info drawers) can animate\n // out in sync with the image — onNavigate only fires once it completes.\n onSlideStart?.(direction);\n\n requestAnimationFrame(() => {\n applySlideOffset(targetOffset, true);\n\n const track = slideTrackRef.current;\n let cleaned = false;\n\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n track?.removeEventListener(\"transitionend\", onTransitionEnd);\n\n let newIndex = direction === \"prev\" ? currentIndex - 1 : currentIndex + 1;\n // Wrap the index when looping so the slide that just played lands on\n // the far end (e.g. last → first) instead of bailing out of bounds.\n if (loop) newIndex = (newIndex + items.length) % items.length;\n if (newIndex < 0 || newIndex >= items.length) {\n commitLockRef.current = false;\n return;\n }\n\n const newItem = items[newIndex];\n const preload = new Image();\n preload.src = newItem.src;\n\n const doNavigate = () => onNavigate(newIndex);\n\n // Add a timeout so a stalled decode can't block navigation forever\n const timeout = setTimeout(doNavigate, 300);\n preload\n .decode()\n .then(() => {\n clearTimeout(timeout);\n doNavigate();\n })\n .catch(() => {\n clearTimeout(timeout);\n doNavigate();\n });\n };\n\n const onTransitionEnd = () => cleanup();\n if (track) {\n track.addEventListener(\"transitionend\", onTransitionEnd, { once: true });\n setTimeout(cleanup, 400);\n }\n });\n },\n [applySlideOffset, currentIndex, items, onNavigate, onSlideStart, loop],\n );\n\n const resolveSlide = useCallback(\n (gestureStartTime: number) => {\n const action = resolveSlideDirection({\n offset: swipeOffsetRef.current,\n elapsedMs: Date.now() - gestureStartTime,\n viewportWidth: window.innerWidth,\n hasPrev,\n hasNext,\n });\n\n if (action === \"prev\") commitSlide(\"prev\");\n else if (action === \"next\") commitSlide(\"next\");\n else snapBack();\n },\n [hasPrev, hasNext, commitSlide, snapBack],\n );\n\n // DOM resets on navigation (pre-paint)\n\n useLayoutEffect(() => {\n const track = slideTrackRef.current;\n if (track) {\n track.style.transition = \"none\";\n track.offsetHeight;\n track.style.transform = \"translateX(0px)\";\n }\n swipeOffsetRef.current = 0;\n commitLockRef.current = false;\n }, [currentIndex]);\n\n // React state cleanup — runs after paint\n useEffect(() => {\n setSwipeOffset(0);\n setSlideAnimating(false);\n setSlideActive(false);\n // Allow next commit only after React has painted the new panel\n readyRef.current = true;\n }, [currentIndex]);\n\n return {\n slideTrackRef,\n slideActive,\n slideAnimating,\n swipeOffset,\n swipeOffsetRef,\n commitLockRef,\n applySlideOffset,\n commitSlide,\n snapBack,\n resolveSlide,\n setSlideActive,\n };\n}\n","import { useCallback, useRef } from \"react\";\nimport { zoomToPoint } from \"./math\";\nimport type { ImageZoomPanState } from \"./useImageZoomPan\";\nimport type { SlideNavigationState } from \"./useSlideNavigation\";\n\ninterface GestureHandlers {\n handlePointerDown: (e: React.PointerEvent) => void;\n handlePointerMove: (e: React.PointerEvent) => void;\n handlePointerUp: (e: React.PointerEvent) => void;\n handleTouchStart: (e: React.TouchEvent) => void;\n handleTouchMove: (e: React.TouchEvent) => void;\n handleTouchEnd: (e: React.TouchEvent) => void;\n}\n\ninterface PanGesture {\n isDragging: boolean;\n pointerStart: { x: number; y: number };\n translateStart: { x: number; y: number };\n pinchStartDist: number | null;\n pinchStartScale: number;\n pinchMidpoint: { x: number; y: number } | null;\n lastTouchPos: { x: number; y: number } | null;\n}\n\ninterface SlideGesture {\n active: boolean;\n startX: number;\n startY: number;\n startTime: number;\n locked: boolean;\n rejected: boolean;\n}\n\n/**\n * Coordinates zoom/pan and slide gestures, routing pointer and touch events\n * to the appropriate behavior based on current zoom state.\n *\n * When zoomed (scale > 1): pointer/touch drags are pans.\n * When unzoomed (scale === 1): pointer/touch drags are slide-to-navigate.\n * Two-finger touch is always a pinch-zoom.\n */\nexport function useGestureHandler(\n zoomPan: ImageZoomPanState,\n slide: SlideNavigationState,\n hasPrev: boolean,\n hasNext: boolean,\n /** When false, pinch-zoom and double-tap-zoom are disabled. Default true. */\n zoomEnabled = true,\n /**\n * When true (default), pinch-zoom anchors on the gesture midpoint. When\n * false, it zooms about the viewport center.\n */\n zoomToCursor = true,\n): GestureHandlers {\n const { transformRef, clampTranslate, setTransform, applyTransform, resetTransform } = zoomPan;\n const { applySlideOffset, resolveSlide, snapBack, setSlideActive, swipeOffsetRef } = slide;\n\n const panRef = useRef<PanGesture>({\n isDragging: false,\n pointerStart: { x: 0, y: 0 },\n translateStart: { x: 0, y: 0 },\n pinchStartDist: null,\n pinchStartScale: 1,\n pinchMidpoint: null,\n lastTouchPos: null,\n });\n\n const slideRef = useRef<SlideGesture>({\n active: false,\n startX: 0,\n startY: 0,\n startTime: 0,\n locked: false,\n rejected: false,\n });\n\n // Double-tap detection for touch\n const lastTapRef = useRef<{ time: number; x: number; y: number }>({\n time: 0,\n x: 0,\n y: 0,\n });\n\n // Shared slide start helper\n\n const beginSlide = useCallback(\n (x: number, y: number) => {\n setSlideActive(true);\n const sg = slideRef.current;\n sg.active = true;\n sg.startX = x;\n sg.startY = y;\n sg.startTime = Date.now();\n sg.locked = false;\n sg.rejected = false;\n },\n [setSlideActive],\n );\n\n const updateSlide = useCallback(\n (clientX: number, clientY: number, lockThreshold: number, angleBias: number) => {\n const sg = slideRef.current;\n if (!sg.active || sg.rejected) return;\n\n const dx = clientX - sg.startX;\n const dy = clientY - sg.startY;\n\n if (!sg.locked) {\n const absDx = Math.abs(dx);\n const absDy = Math.abs(dy);\n if (absDx < lockThreshold && absDy < lockThreshold) return;\n if (absDy > absDx * angleBias) {\n sg.rejected = true;\n return;\n }\n sg.locked = true;\n }\n\n let offset = dx;\n if ((offset > 0 && !hasPrev) || (offset < 0 && !hasNext)) {\n offset *= 0.2; // rubber-band resistance at edges\n }\n applySlideOffset(offset);\n },\n [hasPrev, hasNext, applySlideOffset],\n );\n\n const endSlide = useCallback(\n (allowResolve: boolean) => {\n const sg = slideRef.current;\n if (sg.active && sg.locked && !sg.rejected && allowResolve) {\n const startTime = sg.startTime;\n sg.active = false;\n resolveSlide(startTime);\n } else {\n sg.active = false;\n if (swipeOffsetRef.current === 0) setSlideActive(false);\n }\n },\n [resolveSlide, setSlideActive, swipeOffsetRef],\n );\n\n // Pointer (mouse) handlers\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (e.pointerType === \"touch\") return;\n\n if (transformRef.current.scale > 1) {\n e.preventDefault();\n const p = panRef.current;\n p.isDragging = true;\n p.pointerStart = { x: e.clientX, y: e.clientY };\n p.translateStart = { x: transformRef.current.x, y: transformRef.current.y };\n } else {\n beginSlide(e.clientX, e.clientY);\n }\n },\n [transformRef, beginSlide],\n );\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent) => {\n if (e.pointerType === \"touch\") return;\n\n const p = panRef.current;\n if (p.isDragging && transformRef.current.scale > 1) {\n const dx = e.clientX - p.pointerStart.x;\n const dy = e.clientY - p.pointerStart.y;\n const t = transformRef.current;\n const clamped = clampTranslate(p.translateStart.x + dx, p.translateStart.y + dy, t.scale);\n setTransform({ scale: t.scale, ...clamped });\n return;\n }\n\n // Mouse slide: lockThreshold=4, angleBias=1 (45° cutoff)\n updateSlide(e.clientX, e.clientY, 4, 1);\n },\n [transformRef, clampTranslate, setTransform, updateSlide],\n );\n\n const handlePointerUp = useCallback(\n (e: React.PointerEvent) => {\n if (e.pointerType === \"touch\") return;\n panRef.current.isDragging = false;\n endSlide(true);\n },\n [endSlide],\n );\n\n // Touch handlers\n\n const handleTouchStart = useCallback(\n (e: React.TouchEvent) => {\n const p = panRef.current;\n\n if (e.touches.length === 2 && zoomEnabled) {\n // Pinch start\n const dx = e.touches[0].clientX - e.touches[1].clientX;\n const dy = e.touches[0].clientY - e.touches[1].clientY;\n p.pinchStartDist = Math.hypot(dx, dy);\n p.pinchStartScale = transformRef.current.scale;\n p.pinchMidpoint = {\n x: (e.touches[0].clientX + e.touches[1].clientX) / 2,\n y: (e.touches[0].clientY + e.touches[1].clientY) / 2,\n };\n p.lastTouchPos = null;\n\n // Cancel any slide in progress\n if (slideRef.current.active) {\n slideRef.current.active = false;\n snapBack();\n }\n } else if (e.touches.length === 1) {\n if (transformRef.current.scale > 1) {\n p.lastTouchPos = {\n x: e.touches[0].clientX,\n y: e.touches[0].clientY,\n };\n } else {\n beginSlide(e.touches[0].clientX, e.touches[0].clientY);\n }\n }\n },\n [transformRef, snapBack, beginSlide, zoomEnabled],\n );\n\n const handleTouchMove = useCallback(\n (e: React.TouchEvent) => {\n const p = panRef.current;\n\n if (e.touches.length === 2 && p.pinchStartDist !== null) {\n // Pinch zoom\n const dx = e.touches[0].clientX - e.touches[1].clientX;\n const dy = e.touches[0].clientY - e.touches[1].clientY;\n const dist = Math.hypot(dx, dy);\n const ratio = dist / p.pinchStartDist;\n const nextScale = Math.min(5, Math.max(1, p.pinchStartScale * ratio));\n const t = transformRef.current;\n let clamped: { x: number; y: number };\n if (nextScale <= 1) {\n clamped = { x: 0, y: 0 };\n } else if (zoomToCursor) {\n const midX = (e.touches[0].clientX + e.touches[1].clientX) / 2;\n const midY = (e.touches[0].clientY + e.touches[1].clientY) / 2;\n const focal = zoomToPoint(\n t.scale,\n nextScale,\n { x: t.x, y: t.y },\n { x: midX, y: midY },\n { width: window.innerWidth, height: window.innerHeight },\n );\n clamped = clampTranslate(focal.x, focal.y, nextScale);\n } else {\n clamped = clampTranslate(t.x, t.y, nextScale);\n }\n\n const next = { scale: nextScale, ...clamped };\n transformRef.current = next;\n applyTransform(next);\n // Sync display state for UI\n // (We set displayScale indirectly through setTransform would cause extra work,\n // so we just write to transformRef + applyTransform, and let touchEnd sync.)\n } else if (e.touches.length === 1 && p.lastTouchPos && transformRef.current.scale > 1) {\n // Zoomed pan\n const touch = e.touches[0];\n const dx = touch.clientX - p.lastTouchPos.x;\n const dy = touch.clientY - p.lastTouchPos.y;\n p.lastTouchPos = { x: touch.clientX, y: touch.clientY };\n\n const t = transformRef.current;\n const clamped = clampTranslate(t.x + dx, t.y + dy, t.scale);\n const next = { scale: t.scale, ...clamped };\n transformRef.current = next;\n applyTransform(next);\n } else if (e.touches.length === 1) {\n // Touch slide: lockThreshold=6, angleBias=0.8\n const touch = e.touches[0];\n updateSlide(touch.clientX, touch.clientY, 6, 0.8);\n }\n },\n [transformRef, clampTranslate, applyTransform, updateSlide, zoomToCursor],\n );\n\n const handleTouchEnd = useCallback(\n (e: React.TouchEvent) => {\n const p = panRef.current;\n const wasPinch = p.pinchStartDist !== null;\n p.pinchStartDist = null;\n p.pinchMidpoint = null;\n\n if (e.touches.length === 0 && transformRef.current.scale <= 1) {\n // Resolve slide if active\n const sg = slideRef.current;\n if (sg.active && sg.locked && !sg.rejected) {\n const startTime = sg.startTime;\n sg.active = false;\n resolveSlide(startTime);\n transformRef.current = { scale: 1, x: 0, y: 0 };\n return;\n }\n sg.active = false;\n resetTransform();\n }\n\n // One finger remaining after pinch → start pan from that finger\n if (e.touches.length === 1 && transformRef.current.scale > 1) {\n p.lastTouchPos = {\n x: e.touches[0].clientX,\n y: e.touches[0].clientY,\n };\n } else {\n p.lastTouchPos = null;\n }\n\n // Double-tap detection (single finger, not after pinch, not after slide)\n const sg = slideRef.current;\n if (\n zoomEnabled &&\n e.touches.length === 0 &&\n e.changedTouches.length === 1 &&\n !wasPinch &&\n !sg.locked\n ) {\n const touch = e.changedTouches[0];\n const now = Date.now();\n const last = lastTapRef.current;\n const timeDelta = now - last.time;\n const distDelta = Math.hypot(touch.clientX - last.x, touch.clientY - last.y);\n\n if (timeDelta < 300 && distDelta < 30) {\n lastTapRef.current = { time: 0, x: 0, y: 0 };\n if (transformRef.current.scale > 1) {\n resetTransform();\n } else {\n setTransform({ scale: 2.5, x: 0, y: 0 }, true);\n }\n } else {\n lastTapRef.current = { time: now, x: touch.clientX, y: touch.clientY };\n }\n }\n\n // Cleanup slide if released without committing\n if (e.touches.length === 0 && sg.active && !sg.locked) {\n sg.active = false;\n if (swipeOffsetRef.current === 0) setSlideActive(false);\n }\n },\n [\n transformRef,\n resetTransform,\n setTransform,\n resolveSlide,\n setSlideActive,\n swipeOffsetRef,\n zoomEnabled,\n ],\n );\n\n return {\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n handleTouchStart,\n handleTouchMove,\n handleTouchEnd,\n };\n}\n","import { useLayoutEffect, useState, type RefObject } from \"react\";\n\n/**\n * Measures the height of the top and bottom bars so the image area\n * can be constrained to fit between them.\n */\nexport function useBarMeasure(\n topBarRef: RefObject<HTMLDivElement | null>,\n bottomBarRef: RefObject<HTMLDivElement | null>,\n /** Re-measure whenever this key changes (e.g. currentIndex) */\n measureKey: unknown,\n) {\n const [topBarH, setTopBarH] = useState(0);\n const [bottomBarH, setBottomBarH] = useState(0);\n\n // Measured before paint so the image is constrained to its final height on the\n // very first frame — otherwise it lays out tall (bottomBarH = 0), then visibly\n // shrinks once the bar is measured, which shows up as a flutter on open.\n useLayoutEffect(() => {\n const measure = () => {\n if (topBarRef.current) setTopBarH(topBarRef.current.offsetHeight);\n if (bottomBarRef.current) setBottomBarH(bottomBarRef.current.offsetHeight);\n };\n measure();\n\n const ro = new ResizeObserver(measure);\n if (topBarRef.current) ro.observe(topBarRef.current);\n if (bottomBarRef.current) ro.observe(bottomBarRef.current);\n return () => ro.disconnect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [measureKey]);\n\n return { topBarH, bottomBarH };\n}\n","import { useEffect } from \"react\";\n\n/**\n * Locks scrolling on the document body while `isLocked` is true (e.g. while the\n * lightbox is open), so content behind the overlay can't be scrolled. To\n * prevent the content from shifting when the scrollbar disappears, the width\n * the scrollbar occupied is added back as right padding while locked. Restores\n * the previous overflow/padding values on unlock/unmount, and reference-counts\n * concurrent locks so closing one overlay doesn't release a lock held by\n * another.\n *\n * SSR-safe: the effect only runs in the browser, so importing this on the\n * server is a no-op.\n */\nlet lockCount = 0;\nlet previousOverflow = \"\";\nlet previousPaddingRight = \"\";\n\nexport function useBodyScrollLock(isLocked: boolean): void {\n useEffect(() => {\n if (!isLocked) return;\n if (typeof document === \"undefined\") return;\n\n if (lockCount === 0) {\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;\n\n previousOverflow = document.body.style.overflow;\n previousPaddingRight = document.body.style.paddingRight;\n\n document.body.style.overflow = \"hidden\";\n if (scrollbarWidth > 0) {\n const currentPaddingRight =\n parseFloat(window.getComputedStyle(document.body).paddingRight) || 0;\n document.body.style.paddingRight = `${currentPaddingRight + scrollbarWidth}px`;\n }\n }\n lockCount += 1;\n\n return () => {\n lockCount -= 1;\n if (lockCount === 0) {\n document.body.style.overflow = previousOverflow;\n document.body.style.paddingRight = previousPaddingRight;\n }\n };\n }, [isLocked]);\n}\n","import { useEffect, type RefObject } from \"react\";\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Traps Tab focus within `containerRef` while `active`, and restores focus to\n * the previously-focused element on deactivate/unmount. SSR-safe (effect only\n * runs in the browser).\n */\nexport function useFocusTrap(containerRef: RefObject<HTMLElement | null>, active: boolean): void {\n useEffect(() => {\n if (!active) return;\n if (typeof document === \"undefined\") return;\n\n const previouslyFocused = document.activeElement as HTMLElement | null;\n const container = containerRef.current;\n\n // Move focus into the dialog so screen readers/keyboard land inside it.\n container?.focus();\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\" || !container) return;\n const focusable = Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => el.offsetParent !== null || el === document.activeElement,\n );\n if (focusable.length === 0) {\n e.preventDefault();\n container.focus();\n return;\n }\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeEl = document.activeElement;\n\n if (e.shiftKey && (activeEl === first || activeEl === container)) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && activeEl === last) {\n e.preventDefault();\n first.focus();\n }\n };\n\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n previouslyFocused?.focus?.();\n };\n }, [containerRef, active]);\n}\n","import type { SVGProps } from \"react\";\nimport type { ViewerIcons } from \"../types\";\n\n// Inline default icons so the package has no runtime icon dependency (e.g.\n// lucide-react). Each is a 24x24 stroked glyph that inherits `currentColor`.\n// Consumers can override any of them via the `icons` prop.\n\nfunction base(props: SVGProps<SVGSVGElement>) {\n return {\n width: 18,\n height: 18,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.75,\n strokeLinecap: \"round\" as const,\n strokeLinejoin: \"round\" as const,\n \"aria-hidden\": true,\n focusable: false,\n ...props,\n };\n}\n\nexport function CloseIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg {...base(props)}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nexport function ZoomInIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg {...base(props)}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n <path d=\"M11 8v6\" />\n <path d=\"M8 11h6\" />\n </svg>\n );\n}\n\nexport function ZoomOutIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg {...base(props)}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n <path d=\"M8 11h6\" />\n </svg>\n );\n}\n\nexport function ChevronLeftIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg {...base({ width: 36, height: 36, strokeWidth: 1.5, ...props })}>\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n );\n}\n\nexport function ChevronRightIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg {...base({ width: 36, height: 36, strokeWidth: 1.5, ...props })}>\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n );\n}\n\n/** The full default icon set, merged with any consumer overrides. */\nexport const defaultIcons: ViewerIcons = {\n close: <CloseIcon />,\n zoomIn: <ZoomInIcon />,\n zoomOut: <ZoomOutIcon />,\n prev: <ChevronLeftIcon />,\n next: <ChevronRightIcon />,\n};\n","/** Tiny className joiner: drops falsy values and joins with a space. */\nexport function cx(...parts: Array<string | false | null | undefined>): string {\n return parts.filter(Boolean).join(\" \");\n}\n","import type { ReactNode } from \"react\";\nimport { cx } from \"./cx\";\n\ninterface NavButtonProps {\n direction: \"prev\" | \"next\";\n enabled: boolean;\n onClick: () => void;\n icon: ReactNode;\n className?: string;\n}\n\nexport function NavButton({ direction, enabled, onClick, icon, className }: NavButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n if (enabled) onClick();\n }}\n disabled={!enabled}\n className={cx(\"rvl-nav-btn\", className)}\n aria-label={direction === \"prev\" ? \"Previous image\" : \"Next image\"}\n >\n {icon}\n </button>\n );\n}\n","import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport type { ImageViewerProps, ViewerContext, ViewerRect } from \"../types\";\nimport { useImageZoomPan, MIN_SCALE, MAX_SCALE } from \"../hooks/useImageZoomPan\";\nimport { useSlideNavigation } from \"../hooks/useSlideNavigation\";\nimport { useGestureHandler } from \"../hooks/useGestureHandler\";\nimport { useBarMeasure } from \"../hooks/useBarMeasure\";\nimport { useBodyScrollLock } from \"../hooks/useBodyScrollLock\";\nimport { useFocusTrap } from \"../hooks/useFocusTrap\";\nimport { defaultIcons } from \"./icons\";\nimport { NavButton } from \"./NavButton\";\nimport { cx } from \"./cx\";\n\nconst ANIM_MS = 250;\nconst IMG_PADDING = 44;\n// Decelerating ease for the shared-element zoom so it settles softly.\nconst ZOOM_EASE = \"cubic-bezier(0.22, 1, 0.36, 1)\";\n\nfunction prefersReducedMotion(): boolean {\n if (typeof window === \"undefined\" || !window.matchMedia) return false;\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/**\n * CSS transform that maps `from` (the element's current rect) onto `to`,\n * assuming a `top left` transform-origin. Used for the FLIP-style thumbnail\n * zoom: place the full image where the thumbnail is, then animate the transform\n * away so it glides into its real position.\n */\nfunction flipTransform(from: ViewerRect, to: ViewerRect): string {\n const sx = to.width / from.width;\n const sy = to.height / from.height;\n const dx = to.left - from.left;\n const dy = to.top - from.top;\n return `translate(${dx}px, ${dy}px) scale(${sx}, ${sy})`;\n}\n\n/**\n * True when the Web Animations API is usable on `el`. jsdom (tests) and very old\n * browsers lack `Element.prototype.animate`, so callers fall back to no anim.\n */\nfunction canAnimate(el: HTMLElement | null): el is HTMLElement {\n return !!el && typeof el.animate === \"function\";\n}\n\n/**\n * True when `rect` overlaps the current viewport at all. A thumbnail scrolled\n * out of view returns its (offscreen) rect just the same, so collapsing into it\n * would fly the image off to nowhere — callers fall back to a plain fade in that\n * case.\n */\nfunction isRectInViewport(rect: ViewerRect): boolean {\n if (typeof window === \"undefined\") return true;\n return (\n rect.top < window.innerHeight &&\n rect.top + rect.height > 0 &&\n rect.left < window.innerWidth &&\n rect.left + rect.width > 0\n );\n}\n\n/**\n * Batteries-included fullscreen image viewer: zoom, pan, pinch, and swipe\n * navigation with themeable chrome and render slots. Controlled via `index` /\n * `onIndexChange`; mount it when open and it runs its own enter/exit animation,\n * calling `onClose` after the exit completes.\n */\nexport function ImageViewer<TData = unknown>({\n items,\n index,\n onIndexChange,\n onNavigate,\n onClose,\n getOriginRect,\n zoom = true,\n zoomToCursor = true,\n showCounter = true,\n loop = false,\n closeOnBackdropClick = false,\n renderHeader,\n renderHeaderActions,\n renderNavStart,\n renderNavEnd,\n renderFooter,\n renderOverlay,\n classNames,\n icons,\n ariaLabel,\n}: ImageViewerProps<TData>) {\n const [visible, setVisible] = useState(false);\n const [closing, setClosing] = useState(false);\n // True only while a thumbnail FLIP collapse is animating the image back into\n // its source. Keeps the track opaque for that flight; a close without a\n // collapse (zoomed, reduced motion, no origin rect) leaves it false so the\n // track fades out instead of vanishing on unmount.\n const [collapsing, setCollapsing] = useState(false);\n const [isTouchDevice, setIsTouchDevice] = useState(false);\n const [contentShift, setContentShiftState] = useState<{\n transform: string | null;\n animate: boolean;\n }>({ transform: null, animate: true });\n\n const containerRef = useRef<HTMLDivElement>(null);\n const imgWrapperRef = useRef<HTMLDivElement>(null);\n const topBarRef = useRef<HTMLDivElement>(null);\n const bottomBarRef = useRef<HTMLDivElement>(null);\n\n const [viewportWidth, setViewportWidth] = useState(() =>\n typeof window === \"undefined\" ? 0 : window.innerWidth,\n );\n\n const item = items[index];\n\n const hasPrevLinear = index > 0;\n const hasNextLinear = index < items.length - 1;\n const hasPrev = loop ? items.length > 1 : hasPrevLinear;\n const hasNext = loop ? items.length > 1 : hasNextLinear;\n\n const mergedIcons = useMemo(() => ({ ...defaultIcons, ...icons }), [icons]);\n const cn = (slot: keyof NonNullable<ImageViewerProps[\"classNames\"]>) => classNames?.[slot];\n\n useBodyScrollLock(true);\n useFocusTrap(containerRef, visible && !closing);\n const { topBarH, bottomBarH } = useBarMeasure(topBarRef, bottomBarRef, index);\n\n const zoomPan = useImageZoomPan(imgWrapperRef, index, zoom, zoomToCursor);\n const {\n imgRef,\n displayScale,\n isZoomed,\n transformRef,\n resetTransform,\n setTransform,\n clampTranslate,\n measureBaseDims,\n handleDoubleClick,\n } = zoomPan;\n\n const slide = useSlideNavigation(items, index, onIndexChange, onNavigate, loop);\n const { slideTrackRef, slideActive, slideAnimating, swipeOffset, commitSlide } = slide;\n\n const gestures = useGestureHandler(zoomPan, slide, hasPrev, hasNext, zoom, zoomToCursor);\n\n useEffect(() => {\n setIsTouchDevice(\"ontouchstart\" in window || navigator.maxTouchPoints > 0);\n }, []);\n\n useEffect(() => {\n const onResize = () => setViewportWidth(window.innerWidth);\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n useEffect(() => {\n const raf = requestAnimationFrame(() => setVisible(true));\n return () => cancelAnimationFrame(raf);\n }, []);\n\n // --- Shared-element thumbnail zoom ---------------------------------------\n // When `getOriginRect` is supplied the image expands out of its source\n // thumbnail on open and collapses back into it on close. Driven by the Web\n // Animations API on the <img> itself (zoom/pan owns the wrapper): WAAPI plays\n // from an explicit start keyframe and owns the transform for the animation's\n // duration, so React re-renders / the zoom-reset layout effect / frame timing\n // can't clobber it mid-flight (the failure mode of a raw inline transition).\n // The FLIP only ever scales down to ≤ 1, sidestepping the iOS upscale-clip bug\n // noted in useImageZoomPan.\n const zoomTransition = !!getOriginRect;\n const reduceMotion = prefersReducedMotion();\n // For a thumbnail zoom, hold the image hidden until its full-size source has\n // decoded, then play the zoom from the thumbnail. Animating before the bytes\n // are ready lets the browser paint a full-size frame first, which reads as the\n // image \"expanding twice\" on the first (uncached) open.\n const gateEntry = zoomTransition && !reduceMotion;\n\n // Whether the opening image has finished loading + decoding.\n const [fullLoaded, setFullLoaded] = useState(false);\n // Set true only if the load runs long, so quick opens never flash a spinner.\n const [showSpinner, setShowSpinner] = useState(false);\n\n const entryStartedRef = useRef(false);\n // Tears down the in-flight entry zoom (clears the inline transform, restores\n // the wrapper clip, cancels the animation). Set while the zoom is playing so\n // a close mid-flight can settle the image before measuring its collapse.\n const entryCleanupRef = useRef<(() => void) | null>(null);\n\n // Plays the shared-element zoom once, from the source thumbnail to the resting\n // image box. Only ever invoked after the full image has decoded (see below),\n // so the picture is paint-ready and the zoom can't flash a full-size frame.\n const runZoomEntry = useCallback(() => {\n if (entryStartedRef.current) return;\n if (!getOriginRect || prefersReducedMotion()) return;\n const img = imgRef.current;\n const thumb = getOriginRect(index);\n if (!thumb || !canAnimate(img)) return;\n\n // Pin the image to its final constrained height before measuring. The bottom\n // bar is measured in a post-paint effect, so on the opening frame `bottomBarH`\n // is still 0 and the React-driven maxHeight is too tall; locking it here (read\n // straight from the bar's DOM) keeps a late bottomBarH measurement from\n // resizing the image mid-flight, which is what makes the open animation\n // visibly jump / re-expand. Held for the whole flight, then matched to React's\n // now-settled value on finish.\n const bottomH = bottomBarRef.current?.offsetHeight ?? 0;\n const lockedMaxHeight = `calc(100vh - ${bottomH + IMG_PADDING * 2}px)`;\n img.style.maxHeight = lockedMaxHeight;\n\n const imgRect = img.getBoundingClientRect();\n if (imgRect.width === 0 || imgRect.height === 0) {\n img.style.maxHeight = \"\";\n return;\n }\n entryStartedRef.current = true;\n\n const startTransform = flipTransform(imgRect, thumb);\n\n // Pin the image to the thumbnail pose *synchronously*, before the browser\n // can paint. On a first (uncached) open this handler fires the instant the\n // full image decodes; a WAAPI animation only composites its first frame on\n // the next frame, so without this inline transform the browser paints one\n // full-size frame first — the image flashes out to full size, then zooms in\n // again (\"expands twice\"). It only shows on the uncached load because the\n // cached path starts the zoom before the first paint. React never writes\n // `transform`, so it won't clobber this.\n img.style.transformOrigin = \"top left\";\n img.style.transform = startTransform;\n\n // The wrapper clips to its own (centered) box; while the image is translated\n // out to the thumbnail it would otherwise be sliced off. Lift the clip for\n // the flight, then restore it so zoom/pan clipping still works afterwards.\n const wrapper = imgWrapperRef.current;\n if (wrapper) wrapper.style.overflow = \"visible\";\n\n // Play from the thumbnail's box to the resting box. `fill: \"forwards\"` holds\n // the resting pose at the end so the inline start transform can't flash back\n // before cleanup swaps it out.\n const anim = img.animate(\n [\n { transformOrigin: \"top left\", transform: startTransform },\n { transformOrigin: \"top left\", transform: \"none\" },\n ],\n { duration: ANIM_MS, easing: ZOOM_EASE, fill: \"forwards\" },\n );\n const cleanup = () => {\n // Match the inline base to the held resting pose, then release the fill:\n // computed style stays \"none\" across the swap, so there's no flicker, and\n // the image is handed cleanly back to zoom/pan.\n img.style.transform = \"\";\n img.style.transformOrigin = \"\";\n if (wrapper) wrapper.style.overflow = \"\";\n // Keep the height pinned to the (by now settled) final value; releasing to\n // \"\" with no following render could briefly drop the constraint entirely.\n img.style.maxHeight = lockedMaxHeight;\n anim.cancel();\n entryCleanupRef.current = null;\n };\n entryCleanupRef.current = cleanup;\n anim.onfinish = cleanup;\n }, [getOriginRect, index, imgRef, imgWrapperRef, bottomBarRef]);\n\n // Mark the opening image ready once it has both loaded and decoded. `decode()`\n // forces the decode up front so revealing the image can't flash; fall back to\n // a plain reveal where it's unsupported or rejects (e.g. the src changed).\n const markFullLoaded = useCallback(() => {\n measureBaseDims();\n const img = imgRef.current;\n if (img && typeof img.decode === \"function\") {\n img.decode().then(\n () => setFullLoaded(true),\n () => setFullLoaded(true),\n );\n } else {\n setFullLoaded(true);\n }\n }, [measureBaseDims, imgRef]);\n\n // A cached image can already be `complete` before React wires up onLoad; pick\n // it up on mount so the open isn't stuck waiting for an event that won't fire.\n useLayoutEffect(() => {\n const img = imgRef.current;\n if (img && img.complete && img.naturalWidth > 0) markFullLoaded();\n // Mount-only: the opening image.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Once the image is decoded, play the entry zoom (a no-op for non-zoom opens,\n // reduced motion, or a repeat call — all guarded inside runZoomEntry).\n useLayoutEffect(() => {\n if (fullLoaded) runZoomEntry();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fullLoaded]);\n\n // Reveal the spinner only after the wait crosses 500ms, then clear it the\n // moment the image is ready (or the gate no longer applies).\n useEffect(() => {\n if (!gateEntry || fullLoaded) {\n setShowSpinner(false);\n return;\n }\n const t = setTimeout(() => setShowSpinner(true), 500);\n return () => clearTimeout(t);\n }, [gateEntry, fullLoaded]);\n\n const handleClose = useCallback(() => {\n const reduce = prefersReducedMotion();\n // Collapse back into the source thumbnail when one exists, is still on\n // screen, and the image isn't zoomed (a zoomed image's box no longer\n // matches the thumbnail; an off-screen thumbnail would fly to nowhere, so\n // fall back to the plain fade).\n const origin = !reduce && !isZoomed ? (getOriginRect?.(index) ?? null) : null;\n const thumb = origin && isRectInViewport(origin) ? origin : null;\n const img = imgRef.current;\n\n // If the open zoom is still playing, settle the image to its resting pose\n // first so the collapse measures the real box, not a mid-flight transform.\n entryCleanupRef.current?.();\n\n setClosing(true);\n setVisible(false);\n\n if (thumb && canAnimate(img)) {\n const imgRect = img.getBoundingClientRect();\n // Lift the wrapper clip so the image isn't sliced as it flies back to the\n // thumbnail; the component unmounts at onClose, so no restore is needed.\n const wrapper = imgWrapperRef.current;\n if (wrapper) wrapper.style.overflow = \"visible\";\n setCollapsing(true);\n // fill \"forwards\" holds the collapsed pose until the component unmounts.\n img.animate(\n [\n { transformOrigin: \"top left\", transform: \"none\" },\n { transformOrigin: \"top left\", transform: flipTransform(imgRect, thumb) },\n ],\n { duration: ANIM_MS, easing: ZOOM_EASE, fill: \"forwards\" },\n );\n }\n // Otherwise the backdrop/bars/track simply fade out (default close).\n\n setTimeout(onClose, reduce ? 0 : ANIM_MS);\n }, [onClose, getOriginRect, index, isZoomed, imgRef, imgWrapperRef]);\n\n const navigate = useCallback(\n (dir: \"prev\" | \"next\") => {\n // commitSlide plays the three-slot slide and wraps the index itself when\n // looping, so boundary wraps animate in exactly like an interior move.\n if (dir === \"prev\") {\n if (hasPrev) commitSlide(\"prev\");\n } else {\n if (hasNext) commitSlide(\"next\");\n }\n },\n [hasPrev, hasNext, commitSlide],\n );\n\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n handleClose();\n return;\n }\n if (displayScale > 1) return;\n if (e.key === \"ArrowLeft\" && hasPrev) navigate(\"prev\");\n if (e.key === \"ArrowRight\" && hasNext) navigate(\"next\");\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [handleClose, hasPrev, hasNext, displayScale, navigate]);\n\n const setContentShift = useCallback((transform: string | null, animate = true) => {\n setContentShiftState({ transform, animate });\n }, []);\n\n const ctx: ViewerContext<TData> = {\n items,\n index,\n item: item!,\n total: items.length,\n hasPrev,\n hasNext,\n goPrev: () => navigate(\"prev\"),\n goNext: () => navigate(\"next\"),\n goTo: (i: number) => {\n if (i !== index && i >= 0 && i < items.length) onIndexChange(i);\n },\n close: handleClose,\n isZoomed,\n displayScale,\n zoomIn: () => {\n const t = transformRef.current;\n const next = Math.min(MAX_SCALE, t.scale * 1.3);\n const clamped = clampTranslate(t.x, t.y, next);\n setTransform({ scale: next, ...clamped }, true);\n },\n zoomOut: () => {\n const t = transformRef.current;\n const next = Math.max(MIN_SCALE, t.scale / 1.3);\n const clamped = next <= 1 ? { x: 0, y: 0 } : clampTranslate(t.x, t.y, next);\n setTransform({ scale: next, ...clamped }, true);\n },\n resetZoom: resetTransform,\n isTouchDevice,\n topBarHeight: topBarH,\n bottomBarHeight: bottomBarH,\n setContentShift,\n };\n\n if (!item) return null;\n\n const reservedH = bottomBarH + IMG_PADDING * 2;\n const imgMaxHeight = `calc(100vh - ${reservedH}px)`;\n const imgStyle: React.CSSProperties = { maxHeight: imgMaxHeight };\n // Keep the image hidden (but laid out, so the zoom can still measure its box)\n // until the full source has decoded, so the entry plays from the thumbnail\n // with no full-size flash. opacity, not display, to preserve the layout box.\n if (gateEntry && !fullLoaded) imgStyle.opacity = 0;\n\n const totalDigits = String(items.length).length;\n const counterMinWidth = `${totalDigits * 2 * 0.6 + 1.5}em`;\n\n // Three-slot carousel neighbors. When looping, the slots at the ends point at\n // the wrap-around items (last ↔ first) so the wrapping slide has a real image\n // to reveal instead of an empty panel.\n const prevIndex = hasPrevLinear ? index - 1 : hasPrev ? items.length - 1 : -1;\n const nextIndex = hasNextLinear ? index + 1 : hasNext ? 0 : -1;\n const prevItem = prevIndex >= 0 ? items[prevIndex] : null;\n const nextItem = nextIndex >= 0 ? items[nextIndex] : null;\n const showAdjacent = slideActive || slideAnimating || swipeOffset !== 0;\n const adjacentOpacity = Math.min(1, Math.abs(swipeOffset) / (viewportWidth * 0.8 || 1));\n\n const showZoomControls = zoom && !isTouchDevice;\n const headerActions = renderHeaderActions?.(ctx);\n const navStart = renderNavStart?.(ctx);\n const navEnd = renderNavEnd?.(ctx);\n const hasNavGroup = hasPrev || hasNext;\n const showNavRow = !isZoomed && (hasNavGroup || navStart != null || navEnd != null);\n\n return (\n <div\n ref={containerRef}\n className={cx(\"rvl-root\", visible && !closing && \"rvl-visible\", cn(\"root\"))}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel ?? item.alt ?? \"Image viewer\"}\n tabIndex={-1}\n >\n <div\n className={cx(\"rvl-backdrop\", cn(\"backdrop\"))}\n onClick={closeOnBackdropClick ? handleClose : undefined}\n aria-hidden=\"true\"\n />\n\n <div ref={topBarRef} className={cx(\"rvl-bar\", \"rvl-top-bar\", cn(\"topBar\"))}>\n <div className={cx(\"rvl-header\", cn(\"topBar\"))}>{renderHeader?.(ctx)}</div>\n\n <div className=\"rvl-header-actions\">\n {headerActions}\n\n {showZoomControls && isZoomed && (\n <button\n type=\"button\"\n className={cx(\"rvl-btn\", \"rvl-btn-scale\", cn(\"button\"))}\n onClick={(e) => {\n e.stopPropagation();\n resetTransform();\n }}\n title=\"Reset zoom\"\n aria-label=\"Reset zoom\"\n >\n {Math.round(displayScale * 100)}%\n </button>\n )}\n\n {showZoomControls && (\n <button\n type=\"button\"\n className={cx(\"rvl-btn\", cn(\"button\"))}\n onClick={(e) => {\n e.stopPropagation();\n ctx.zoomIn();\n }}\n title=\"Zoom in\"\n aria-label=\"Zoom in\"\n >\n {mergedIcons.zoomIn}\n </button>\n )}\n\n {showZoomControls && (\n <button\n type=\"button\"\n className={cx(\"rvl-btn\", cn(\"button\"))}\n onClick={(e) => {\n e.stopPropagation();\n ctx.zoomOut();\n }}\n title=\"Zoom out\"\n aria-label=\"Zoom out\"\n >\n {mergedIcons.zoomOut}\n </button>\n )}\n\n <button\n type=\"button\"\n className={cx(\"rvl-btn\", cn(\"button\"))}\n onClick={(e) => {\n e.stopPropagation();\n handleClose();\n }}\n title=\"Close (Esc)\"\n aria-label=\"Close\"\n >\n {mergedIcons.close}\n </button>\n </div>\n </div>\n\n <div\n className=\"rvl-stage\"\n // The stage (z-index 10) sits over the backdrop (z-index 0) and captures\n // its clicks, so the backdrop's own handler can't fire. Close from here\n // when the click lands on the stage itself — the image wrapper stops\n // propagation and the track/adjacent layers are pointer-events:none, so\n // only genuine background clicks reach this guard.\n onClick={\n closeOnBackdropClick\n ? (e) => {\n if (e.target === e.currentTarget) handleClose();\n }\n : undefined\n }\n style={{\n transform: contentShift.transform ?? \"translateY(0)\",\n // animate=false snaps with no transition (overrides the CSS transition)\n transition: contentShift.animate ? undefined : \"none\",\n }}\n >\n <div\n ref={slideTrackRef}\n className={cx(\n \"rvl-track\",\n // During a thumbnail zoom the track is opaque from the first frame\n // (the image itself is hidden until the zoom starts), so the picture\n // flies in crisply instead of cross-fading. On close it only stays\n // opaque while a FLIP collapse is animating the image back; otherwise\n // it fades out (so a zoomed close still animates instead of vanishing).\n (closing ? collapsing : zoomTransition || visible) && \"rvl-track-visible\",\n )}\n >\n {showAdjacent && prevItem && (\n <div\n className=\"rvl-adjacent\"\n style={{ transform: `translateX(-${viewportWidth}px)`, opacity: adjacentOpacity }}\n >\n <img\n src={prevItem.src}\n alt=\"\"\n className={cx(\"rvl-img\", cn(\"image\"))}\n style={imgStyle}\n draggable={false}\n />\n </div>\n )}\n\n <div\n ref={imgWrapperRef}\n className=\"rvl-img-wrapper\"\n onClick={(e) => e.stopPropagation()}\n onDoubleClick={handleDoubleClick}\n onPointerDown={gestures.handlePointerDown}\n onPointerMove={gestures.handlePointerMove}\n onPointerUp={gestures.handlePointerUp}\n onPointerLeave={gestures.handlePointerUp}\n onTouchStart={gestures.handleTouchStart}\n onTouchMove={gestures.handleTouchMove}\n onTouchEnd={gestures.handleTouchEnd}\n >\n <img\n ref={imgRef}\n src={item.src}\n alt={item.alt ?? \"\"}\n className={cx(\"rvl-img\", cn(\"image\"))}\n style={imgStyle}\n draggable={false}\n onLoad={markFullLoaded}\n // Don't strand the open on a broken image: reveal it (skipping the\n // zoom) so the spinner clears and the viewer stays usable.\n onError={() => setFullLoaded(true)}\n />\n </div>\n\n {gateEntry && showSpinner && !fullLoaded && (\n <div className={cx(\"rvl-spinner\", cn(\"spinner\"))} role=\"status\" aria-label=\"Loading\">\n <span className=\"rvl-spinner-ring\" aria-hidden=\"true\" />\n </div>\n )}\n\n {showAdjacent && nextItem && (\n <div\n className=\"rvl-adjacent\"\n style={{ transform: `translateX(${viewportWidth}px)`, opacity: adjacentOpacity }}\n >\n <img\n src={nextItem.src}\n alt=\"\"\n className={cx(\"rvl-img\", cn(\"image\"))}\n style={imgStyle}\n draggable={false}\n />\n </div>\n )}\n </div>\n </div>\n\n <div ref={bottomBarRef} className={cx(\"rvl-bar\", \"rvl-bottom-bar\", cn(\"bottomBar\"))}>\n {showNavRow && (\n <div className=\"rvl-nav-row\">\n <div className=\"rvl-nav-inner\">\n {navStart != null && (\n <div className={cx(\"rvl-nav-start\", cn(\"navStart\"))}>{navStart}</div>\n )}\n {hasNavGroup && (\n <div className=\"rvl-nav-group\">\n <NavButton\n direction=\"prev\"\n enabled={hasPrev}\n onClick={() => navigate(\"prev\")}\n icon={mergedIcons.prev}\n className={cn(\"navButton\")}\n />\n {showCounter && (\n <span\n className={cx(\"rvl-counter\", cn(\"counter\"))}\n style={{ minWidth: counterMinWidth }}\n >\n {index + 1} / {items.length}\n </span>\n )}\n <NavButton\n direction=\"next\"\n enabled={hasNext}\n onClick={() => navigate(\"next\")}\n icon={mergedIcons.next}\n className={cn(\"navButton\")}\n />\n </div>\n )}\n {navEnd != null && <div className={cx(\"rvl-nav-end\", cn(\"navEnd\"))}>{navEnd}</div>}\n </div>\n </div>\n )}\n\n {renderFooter && <div className=\"rvl-footer\">{renderFooter(ctx)}</div>}\n </div>\n\n {renderOverlay && (\n <div className={cx(\"rvl-overlay\", cn(\"overlay\"))}>{renderOverlay(ctx)}</div>\n )}\n </div>\n );\n}\n"]}
|
package/dist/styles.css
CHANGED
|
@@ -183,6 +183,14 @@
|
|
|
183
183
|
.rvl-root.rvl-visible .rvl-track {
|
|
184
184
|
opacity: 1;
|
|
185
185
|
}
|
|
186
|
+
/* Opaque from the first frame. During a thumbnail zoom this is applied at mount
|
|
187
|
+
(before `rvl-visible`), so the image flies in crisply on the FLIP instead of
|
|
188
|
+
the opacity ramp cross-fading over the top of the expand — which otherwise
|
|
189
|
+
reads as the picture expanding twice. On a plain (non-zoom) open the class is
|
|
190
|
+
only added once `visible` flips, so it still fades in from the base opacity:0. */
|
|
191
|
+
.rvl-track-visible {
|
|
192
|
+
opacity: 1;
|
|
193
|
+
}
|
|
186
194
|
|
|
187
195
|
.rvl-adjacent {
|
|
188
196
|
position: absolute;
|
|
@@ -216,6 +224,31 @@
|
|
|
216
224
|
will-change: transform;
|
|
217
225
|
}
|
|
218
226
|
|
|
227
|
+
/* Loading spinner: shown only when the opening image is slow to load. Centered
|
|
228
|
+
over the stage; the image itself is held hidden until it has decoded. */
|
|
229
|
+
.rvl-spinner {
|
|
230
|
+
position: absolute;
|
|
231
|
+
top: 50%;
|
|
232
|
+
left: 50%;
|
|
233
|
+
transform: translate(-50%, -50%);
|
|
234
|
+
z-index: 11;
|
|
235
|
+
pointer-events: none;
|
|
236
|
+
}
|
|
237
|
+
.rvl-spinner-ring {
|
|
238
|
+
display: block;
|
|
239
|
+
width: 2.25rem;
|
|
240
|
+
height: 2.25rem;
|
|
241
|
+
border-radius: 50%;
|
|
242
|
+
border: 3px solid rgba(255, 255, 255, 0.25);
|
|
243
|
+
border-top-color: rgba(255, 255, 255, 0.9);
|
|
244
|
+
animation: rvl-spin 0.7s linear infinite;
|
|
245
|
+
}
|
|
246
|
+
@keyframes rvl-spin {
|
|
247
|
+
to {
|
|
248
|
+
transform: rotate(360deg);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
219
252
|
/* Bottom nav row ------------------------------------------------------------ */
|
|
220
253
|
|
|
221
254
|
.rvl-nav-row {
|
package/package.json
CHANGED