UNPKG

react-images-extended-2

Version:

A simple, responsive lightbox component for displaying an array of images with React.js with extended features

293 lines (292 loc) 13.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useLightboxDrag = exports.useLightboxDisplay = exports.useLightboxImageState = exports.useLightboxImages = exports.useCallbackMethods = exports.useCurrentImage = exports.useLightboxState = exports.useSetupState = exports.LightboxProvider = exports.LightboxDisplayMode = exports.ActionType = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const log_1 = require("./utils/log"); const manipulation_1 = require("./utils/manipulation"); var ActionType; (function (ActionType) { ActionType["CLOSE"] = "CLOSE"; ActionType["NEXT"] = "NEXT"; ActionType["PREVIOUS"] = "PREVIOUS"; ActionType["ZOOM_IN"] = "ZOOM_IN"; ActionType["ZOOM_OUT"] = "ZOOM_OUT"; ActionType["ROTATE_LEFT"] = "ROTATE_LEFT"; ActionType["ROTATE_RIGHT"] = "ROTATE_RIGHT"; ActionType["FLIP_VERTICAL"] = "FLIP_VERTICAL"; ActionType["FLIP_HORIZONTAL"] = "FLIP_HORIZONTAL"; ActionType["RESET_IMAGE"] = "RESET_IMAGE"; ActionType["SAVE"] = "SAVE"; ActionType["TOGGLE_PIP"] = "TOGGLE_PIP"; ActionType["TOGGLE_FULLSCREEN"] = "TOGGLE_FULLSCREEN"; })(ActionType || (exports.ActionType = ActionType = {})); var LightboxDisplayMode; (function (LightboxDisplayMode) { LightboxDisplayMode["FULLSCREEN"] = "fullscreen"; LightboxDisplayMode["COMPONENT"] = "component"; LightboxDisplayMode["PIP"] = "pip"; })(LightboxDisplayMode || (exports.LightboxDisplayMode = LightboxDisplayMode = {})); // Default state const defaultState = { images: [], currentImage: 0, imageState: { imageLoaded: false, error: null, left: 0, top: 15, width: 0, height: 0, rotate: 0, imageWidth: 0, imageHeight: 0, scaleX: 1, scaleY: 1, }, pipPosition: { left: 0, top: 0 }, displayMode: LightboxDisplayMode.FULLSCREEN, showThumbnails: false, isLoading: false, isDraggingImage: false, }; // Reducer function for state mutations function lightboxReducer(state, action) { switch (action.type) { case "ZOOM_IN": (0, log_1.debuginfo)("Handling zoom in"); const stateOnZoomIn = (0, manipulation_1.zoomManipulation)(false, state.imageState); return Object.assign(Object.assign({}, state), { imageState: Object.assign(Object.assign({}, state.imageState), stateOnZoomIn) }); case "ZOOM_OUT": (0, log_1.debuginfo)("Handling zoom out"); const stateOnZoomOut = (0, manipulation_1.zoomManipulation)(true, state.imageState); return Object.assign(Object.assign({}, state), { imageState: Object.assign(Object.assign({}, state.imageState), stateOnZoomOut) }); case "ROTATE_LEFT": (0, log_1.debuginfo)("Handling rotate left"); const stateOnRotateLeft = (0, manipulation_1.rotateManipulation)(state.imageState, false); return Object.assign(Object.assign({}, state), { imageState: Object.assign(Object.assign({}, state.imageState), stateOnRotateLeft) }); case "ROTATE_RIGHT": (0, log_1.debuginfo)("Handling rotate right"); const stateOnRotateRight = (0, manipulation_1.rotateManipulation)(state.imageState, true); return Object.assign(Object.assign({}, state), { imageState: Object.assign(Object.assign({}, state.imageState), stateOnRotateRight) }); case "FLIP_HORIZONTAL": (0, log_1.debuginfo)("Handling flip horizontal"); const stateOnFlipHorisontal = (0, manipulation_1.flipManipulation)(state.imageState, true); return Object.assign(Object.assign({}, state), { imageState: Object.assign(Object.assign({}, state.imageState), stateOnFlipHorisontal) }); case "FLIP_VERTICAL": (0, log_1.debuginfo)("Handling flip vertical"); const stateOnFlipVertical = (0, manipulation_1.flipManipulation)(state.imageState, false); return Object.assign(Object.assign({}, state), { imageState: Object.assign(Object.assign({}, state.imageState), stateOnFlipVertical) }); case "SET_PIP_POSITION": return Object.assign(Object.assign({}, state), { pipPosition: { left: action.payload.left, top: action.payload.top, } }); case "SET_STATE": return Object.assign(Object.assign({}, state), action.payload); case "SET_IMAGES": return Object.assign(Object.assign({}, state), { images: action.payload }); case "SET_CURRENT_IMAGE": return Object.assign(Object.assign({}, state), { currentImage: Math.max(0, Math.min(action.payload, state.images.length - 1)) }); case "UPDATE_IMAGE_STATE": return Object.assign(Object.assign({}, state), { imageState: Object.assign(Object.assign({}, state.imageState), action.payload) }); case "UPDATE_IMAGE_STATE_LOADED": return Object.assign(Object.assign({}, state), { imageState: Object.assign(Object.assign({}, state.imageState), { imageLoaded: action.payload.imageLoaded }) }); case "SET_DISPLAY_MODE_PIP": (0, log_1.debuginfo)("Setting display mode to PIP"); return Object.assign(Object.assign({}, state), { displayMode: action.payload, imageState: Object.assign(Object.assign({}, state.imageState), { left: 0, top: 0 }) }); case "SET_DISPLAY_MODE_FS": return Object.assign(Object.assign({}, state), { displayMode: action.payload }); case "SET_SHOW_THUMBNAILS": return Object.assign(Object.assign({}, state), { showThumbnails: action.payload }); case "SET_LOADING": return Object.assign(Object.assign({}, state), { isLoading: action.payload }); case "SET_DRAGGING": return Object.assign(Object.assign({}, state), { isDraggingImage: action.payload }); case "RESET_IMAGE_STATE": (0, log_1.debuginfo)("Resetting image state"); const stateOnImageReset = (0, manipulation_1.handleReset)(action.payload.widthRef, action.payload.heightRef, state.imageState.imageWidth, state.imageState.imageHeight); return Object.assign(Object.assign({}, state), { isDraggingImage: false, imageState: Object.assign(Object.assign({}, state.imageState), stateOnImageReset) }); case "RESET_ALL": return defaultState; default: return state; } } // Create context const LightboxContext = (0, react_1.createContext)(undefined); const LightboxProvider = ({ children, initialState = {}, }) => { const [state, dispatch] = (0, react_1.useReducer)(lightboxReducer, Object.assign(Object.assign({}, defaultState), initialState)); const setPiPPosition = (0, react_1.useCallback)((left, top) => { dispatch({ type: "SET_PIP_POSITION", payload: { left, top } }); }, []); const setState = (0, react_1.useCallback)((newState) => { dispatch({ type: "SET_STATE", payload: newState }); }, []); const setImageLoaded = (0, react_1.useCallback)((imageLoaded) => { dispatch({ type: "UPDATE_IMAGE_STATE_LOADED", payload: { imageLoaded } }); }, []); // Convenience methods const setImages = (0, react_1.useCallback)((images) => { dispatch({ type: "SET_IMAGES", payload: images }); }, []); const setCurrentImage = (0, react_1.useCallback)((index) => { dispatch({ type: "SET_CURRENT_IMAGE", payload: index }); }, []); const updateImageState = (0, react_1.useCallback)((updates) => { dispatch({ type: "UPDATE_IMAGE_STATE", payload: updates }); }, []); const zoomIn = (0, react_1.useCallback)(() => { (0, log_1.debuginfo)("Zoom in callback triggered"); dispatch({ type: "ZOOM_IN", payload: null }); }, []); const zoomOut = (0, react_1.useCallback)(() => { (0, log_1.debuginfo)("Zoom out callback triggered"); dispatch({ type: "ZOOM_OUT", payload: null }); }, []); const rotateLeft = (0, react_1.useCallback)(() => { (0, log_1.debuginfo)("Rotate left callback triggered"); dispatch({ type: "ROTATE_LEFT", payload: null }); }, []); const flipVertical = (0, react_1.useCallback)(() => { (0, log_1.debuginfo)("Flip vertical callback triggered"); dispatch({ type: "FLIP_VERTICAL", payload: null }); }, []); const flipHorisontal = (0, react_1.useCallback)(() => { (0, log_1.debuginfo)("Flip horisontal callback triggered"); dispatch({ type: "FLIP_HORIZONTAL", payload: null }); }, []); const rotateRight = (0, react_1.useCallback)(() => { (0, log_1.debuginfo)("Rotate right callback triggered"); dispatch({ type: "ROTATE_RIGHT", payload: null }); }, []); const setDisplayMode = (0, react_1.useCallback)((mode) => { if (mode === LightboxDisplayMode.PIP) dispatch({ type: "SET_DISPLAY_MODE_PIP", payload: mode }); else dispatch({ type: "SET_DISPLAY_MODE_FS", payload: mode }); }, []); const setDraggingImage = (0, react_1.useCallback)((isDragging) => { dispatch({ type: "SET_DRAGGING", payload: isDragging }); }, []); const resetImageState = (0, react_1.useCallback)((widthRef, heightRef) => { dispatch({ type: "RESET_IMAGE_STATE", payload: { widthRef, heightRef } }); }, []); const resetAll = (0, react_1.useCallback)(() => { dispatch({ type: "RESET_ALL" }); }, []); const contextValue = { state, dispatch, setPiPPosition, setState, setImages, setCurrentImage, zoomIn, zoomOut, flipVertical, flipHorisontal, rotateLeft, rotateRight, updateImageState, setImageLoaded, setDisplayMode, setDraggingImage, resetImageState, resetAll, }; return ((0, jsx_runtime_1.jsx)(LightboxContext.Provider, { value: contextValue, children: children })); }; exports.LightboxProvider = LightboxProvider; const useSetupState = (initialState) => { const context = (0, react_1.useContext)(LightboxContext); if (!context) { throw new Error("useInitialiseState must be used within a LightboxProvider"); } // Only initialize once when the component mounts (0, react_1.useEffect)(() => { context.setState(initialState); }, []); // Empty dependency array ensures this only runs once }; exports.useSetupState = useSetupState; // Custom hook to use the lightbox context const useLightboxState = () => { const context = (0, react_1.useContext)(LightboxContext); if (context === undefined) { throw new Error("useLightboxState must be used within a LightboxProvider"); } return context; }; exports.useLightboxState = useLightboxState; // Custom hooks for specific state slices const useCurrentImage = () => { const { state } = (0, exports.useLightboxState)(); const { images, currentImage } = state; return images[currentImage]; }; exports.useCurrentImage = useCurrentImage; const useCallbackMethods = () => { const { state } = (0, exports.useLightboxState)(); const { onClickImage, onClickNext, onClickPrev, onClose, onRotateLeft, onRotateRight, onZoomIn, onZoomOut, onSave, onClickThumbnail, } = state; return { onClickImage, onClickNext, onClickPrev, onClose, onRotateLeft, onRotateRight, onZoomIn, onZoomOut, onSave, onClickThumbnail, }; }; exports.useCallbackMethods = useCallbackMethods; // Custom hooks for specific state slices const useLightboxImages = () => { const { state, setImages, setCurrentImage } = (0, exports.useLightboxState)(); return { images: state.images, currentImage: state.currentImage, currentImageData: state.images[state.currentImage], setImages, setCurrentImage, nextImage: () => setCurrentImage(state.currentImage + 1), prevImage: () => setCurrentImage(state.currentImage - 1), toImage: (index) => setCurrentImage(index), hasNext: state.currentImage < state.images.length - 1, hasPrev: state.currentImage > 0, }; }; exports.useLightboxImages = useLightboxImages; const useLightboxImageState = () => { const { state, updateImageState, resetImageState } = (0, exports.useLightboxState)(); return { imageState: state.imageState, updateImageState, resetImageState, isLoaded: state.imageState.imageLoaded, hasError: !!state.imageState.error, }; }; exports.useLightboxImageState = useLightboxImageState; const useLightboxDisplay = () => { const { state, setDisplayMode } = (0, exports.useLightboxState)(); return { displayMode: state.displayMode, setDisplayMode, isFullscreen: state.displayMode === LightboxDisplayMode.FULLSCREEN, isPiP: state.displayMode === LightboxDisplayMode.PIP, isComponent: state.displayMode === LightboxDisplayMode.COMPONENT, }; }; exports.useLightboxDisplay = useLightboxDisplay; const useLightboxDrag = () => { const { state, setDraggingImage } = (0, exports.useLightboxState)(); return { isDragging: state.isDraggingImage, setDraggingImage, isAnyDragging: state.isDraggingImage, }; }; exports.useLightboxDrag = useLightboxDrag;