react-images-extended-2-stable
Version:
A simple, responsive lightbox component for displaying an array of images with React.js with extended features ((stable version))
98 lines (97 loc) • 4.73 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { useCallback, useRef, useMemo, useEffect, } from "react";
import { useLightboxManipulationState, useLightboxState, } from "../ComponentState";
import { debuginfo } from "../utils/log";
import { IMAGE_Z_INDEX } from "../utils/constants";
export function Draggable({ children }) {
const dragStartRef = useRef({ x: 0, y: 0 });
const dragOffsetRef = useRef({ x: 0, y: 0 });
const lightboxState = useLightboxState();
const { isDraggingFigure } = lightboxState.state;
const { manipulationState } = useLightboxManipulationState();
const { top, left } = manipulationState;
useEffect(() => {
debuginfo(`image state left updated to ${left}`);
}, [left]);
const wrapperStyle = useMemo(() => ({
border: isDraggingFigure ? "1px solid #ccc" : "none",
width: `${manipulationState.width}px`,
minWidth: `${manipulationState.width}px`,
maxWidth: `${manipulationState.width}px`,
height: "auto",
transform: `translate(-50%, -50%) translate(${left || 0}px, ${top || 0}px) rotate(${manipulationState.rotate}deg) scaleX(${manipulationState.scaleX}) scaleY(${manipulationState.scaleY})`,
transformOrigin: "center",
willChange: "transform",
transition: isDraggingFigure ? "none" : "transform 0.5s cubic-bezier(0.25, 0.8, 0.25, 1)", // More visible smooth transitions when not dragging
backfaceVisibility: "hidden", // Prevent flashing on transform
WebkitBackfaceVisibility: "hidden",
WebkitTransform: `translate(-50%, -50%) translate(${left || 0}px, ${top || 0}px) rotate(${manipulationState.rotate}deg) scaleX(${manipulationState.scaleX}) scaleY(${manipulationState.scaleY})`,
position: "absolute",
display: "block",
zIndex: IMAGE_Z_INDEX, // Ensure image is below controls
left: "50%",
top: "50%",
cursor: isDraggingFigure ? "grabbing" : "grab",
// Additional properties to reduce flashing
imageRendering: "crisp-edges",
WebkitFontSmoothing: "antialiased",
MozOsxFontSmoothing: "grayscale",
pointerEvents: "auto", // Add this
userSelect: "none", // Add this
WebkitUserSelect: "none", // Add this
flexShrink: 0, // Prevent flexbox from shrinking the image
}), [
manipulationState.left,
manipulationState.top,
manipulationState.height,
manipulationState.width,
manipulationState.rotate,
manipulationState.scaleX,
manipulationState.scaleY,
isDraggingFigure, // Add this dependency so transition updates properly
]);
const handleMouseDown = useCallback((event) => {
event.preventDefault();
lightboxState.setDraggingFigure(true);
//debuginfo(`Mouse down position at (${event.clientX}, ${event.clientY})`);
dragStartRef.current = {
x: event.clientX,
y: event.clientY,
};
const { left, top } = manipulationState;
dragOffsetRef.current = {
x: left || 0,
y: top || 0,
};
}, [isDraggingFigure, manipulationState.left, manipulationState.top]);
const handleMouseMove = useCallback((event) => {
if (!isDraggingFigure)
return;
event.preventDefault();
//debuginfo(`Screen coordinates: (${event.clientX}, ${event.clientY})`);
const deltaX = event.clientX - dragStartRef.current.x;
const deltaY = event.clientY - dragStartRef.current.y;
const newLeft = dragOffsetRef.current.x + deltaX;
const newTop = dragOffsetRef.current.y + deltaY;
const updatedImageState = {
left: newLeft,
top: newTop,
};
lightboxState.updateFigureManipulation(updatedImageState);
}, [isDraggingFigure, dragOffsetRef, dragStartRef]);
const handleDoubleClick = useCallback((event) => {
event.preventDefault();
const clickX = event.clientX;
const clickY = event.clientY;
const deltaX = clickX - dragStartRef.current.x;
const deltaY = clickY - dragStartRef.current.y;
if (deltaX <= 1 && deltaY <= 1) {
lightboxState.zoomInToPoint({ x: clickX, y: clickY });
}
lightboxState.setDraggingFigure(false);
}, [lightboxState]);
const handleMouseUp = useCallback(() => {
lightboxState.setDraggingFigure(false);
}, [lightboxState]);
return (_jsx("div", { role: "draggable-wrapper", onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onMouseUp: handleMouseUp, onMouseLeave: handleMouseUp, onDoubleClick: handleDoubleClick, style: wrapperStyle, children: children }));
}