@jekrch/react-viewport-lightbox 0.3.0 → 0.3.1

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/dist/index.cjs CHANGED
@@ -741,6 +741,7 @@ function NavButton({ direction, enabled, onClick, icon, className }) {
741
741
  }
742
742
  var ANIM_MS = 250;
743
743
  var IMG_PADDING = 44;
744
+ var GHOST_CLICK_MS = 700;
744
745
  var ZOOM_EASE = "cubic-bezier(0.22, 1, 0.36, 1)";
745
746
  function prefersReducedMotion() {
746
747
  if (typeof window === "undefined" || !window.matchMedia) return false;
@@ -794,6 +795,11 @@ function ImageViewer({
794
795
  const [collapsing, setCollapsing] = react.useState(false);
795
796
  const [isTouchDevice, setIsTouchDevice] = react.useState(false);
796
797
  const [contentShift, setContentShiftState] = react.useState({ transform: null, animate: true });
798
+ const openedAtRef = react.useRef(Date.now());
799
+ const isGhostMouseEvent = react.useCallback(
800
+ () => Date.now() - openedAtRef.current < GHOST_CLICK_MS,
801
+ []
802
+ );
797
803
  const containerRef = react.useRef(null);
798
804
  const imgWrapperRef = react.useRef(null);
799
805
  const topBarRef = react.useRef(null);
@@ -941,6 +947,33 @@ function ImageViewer({
941
947
  }
942
948
  setTimeout(onClose, reduce ? 0 : ANIM_MS);
943
949
  }, [onClose, getOriginRect, index, isZoomed, imgRef, imgWrapperRef]);
950
+ const handleBackdropTouchEnd = react.useCallback(
951
+ (e) => {
952
+ if (e.target !== e.currentTarget) return;
953
+ e.preventDefault();
954
+ handleClose();
955
+ },
956
+ [handleClose]
957
+ );
958
+ const handleDoubleClickGuarded = react.useCallback(
959
+ (e) => {
960
+ if (isGhostMouseEvent()) return;
961
+ handleDoubleClick(e);
962
+ },
963
+ [handleDoubleClick, isGhostMouseEvent]
964
+ );
965
+ const handleBackdropClick = react.useCallback(() => {
966
+ if (isGhostMouseEvent()) return;
967
+ handleClose();
968
+ }, [handleClose, isGhostMouseEvent]);
969
+ const handleStageClick = react.useCallback(
970
+ (e) => {
971
+ if (e.target !== e.currentTarget) return;
972
+ if (isGhostMouseEvent()) return;
973
+ handleClose();
974
+ },
975
+ [handleClose, isGhostMouseEvent]
976
+ );
944
977
  const navigate = react.useCallback(
945
978
  (dir) => {
946
979
  if (dir === "prev") {
@@ -1042,7 +1075,8 @@ function ImageViewer({
1042
1075
  "div",
1043
1076
  {
1044
1077
  className: cx("rvl-backdrop", cn("backdrop")),
1045
- onClick: closeOnBackdropClick ? handleClose : void 0,
1078
+ onClick: closeOnBackdropClick ? handleBackdropClick : void 0,
1079
+ onTouchEnd: closeOnBackdropClick ? handleBackdropTouchEnd : void 0,
1046
1080
  "aria-hidden": "true"
1047
1081
  }
1048
1082
  ),
@@ -1115,9 +1149,8 @@ function ImageViewer({
1115
1149
  "div",
1116
1150
  {
1117
1151
  className: "rvl-stage",
1118
- onClick: closeOnBackdropClick ? (e) => {
1119
- if (e.target === e.currentTarget) handleClose();
1120
- } : void 0,
1152
+ onClick: closeOnBackdropClick ? handleStageClick : void 0,
1153
+ onTouchEnd: closeOnBackdropClick ? handleBackdropTouchEnd : void 0,
1121
1154
  style: {
1122
1155
  transform: contentShift.transform ?? "translateY(0)",
1123
1156
  // animate=false snaps with no transition (overrides the CSS transition)
@@ -1160,7 +1193,7 @@ function ImageViewer({
1160
1193
  ref: imgWrapperRef,
1161
1194
  className: "rvl-img-wrapper",
1162
1195
  onClick: (e) => e.stopPropagation(),
1163
- onDoubleClick: handleDoubleClick,
1196
+ onDoubleClick: handleDoubleClickGuarded,
1164
1197
  onPointerDown: gestures.handlePointerDown,
1165
1198
  onPointerMove: gestures.handlePointerMove,
1166
1199
  onPointerUp: gestures.handlePointerUp,