UNPKG

react-pdf-flipbook-viewer

Version:

A customizable React component to render PDF documents in a flipbook-style viewer — perfect for brochures, magazines, and interactive documents. ## Features

131 lines (130 loc) 3.83 kB
import { useEffect, useState } from "react"; // Inspired by react-hot-toast library const TOAST_LIMIT = 1; const TOAST_REMOVE_DELAY = 1000000; var actionTypes; (function (actionTypes) { actionTypes["ADD_TOAST"] = "ADD_TOAST"; actionTypes["UPDATE_TOAST"] = "UPDATE_TOAST"; actionTypes["DISMISS_TOAST"] = "DISMISS_TOAST"; actionTypes["REMOVE_TOAST"] = "REMOVE_TOAST"; })(actionTypes || (actionTypes = {})); let count = 0; function genId() { count = (count + 1) % Number.MAX_SAFE_INTEGER; return count.toString(); } const toastTimeouts = new Map(); const addToRemoveQueue = (toastId) => { if (toastTimeouts.has(toastId)) { return; } const timeout = setTimeout(() => { toastTimeouts.delete(toastId); dispatch({ type: actionTypes.REMOVE_TOAST, toastId: toastId, }); }, TOAST_REMOVE_DELAY); toastTimeouts.set(toastId, timeout); }; export const reducer = (state, action) => { switch (action.type) { case actionTypes.ADD_TOAST: return { ...state, toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), }; case actionTypes.UPDATE_TOAST: return { ...state, toasts: state.toasts.map((t) => t.id === action.toast?.id ? { ...t, ...action.toast } : t), }; case actionTypes.DISMISS_TOAST: { const { toastId } = action; // ! Side effects ! - This could be extracted into a dismissToast() action, // but I'll keep it here for simplicity if (toastId) { addToRemoveQueue(toastId); } else { state.toasts.forEach((toast) => { addToRemoveQueue(toast.id); }); } return { ...state, toasts: state.toasts.map((t) => t.id === toastId || toastId === undefined ? { ...t, open: false, } : t), }; } case actionTypes.REMOVE_TOAST: if (action.toastId === undefined) { return { ...state, toasts: [], }; } return { ...state, toasts: state.toasts.filter((t) => t.id !== action.toastId), }; default: return state; } }; const listeners = []; let memoryState = { toasts: [] }; function dispatch(action) { memoryState = reducer(memoryState, action); listeners.forEach((listener) => { listener(memoryState); }); } function toast({ ...props }) { const id = genId(); const update = (props) => dispatch({ type: actionTypes.UPDATE_TOAST, toast: { ...props, id }, }); const dismiss = () => dispatch({ type: actionTypes.DISMISS_TOAST, toastId: id }); dispatch({ type: actionTypes.ADD_TOAST, toast: { ...props, id, open: true, onOpenChange: (open) => { if (!open) dismiss(); }, }, }); return { id, dismiss, update, }; } function useToast() { const [state, setState] = useState(memoryState); useEffect(() => { listeners.push(setState); return () => { const index = listeners.indexOf(setState); if (index > -1) { listeners.splice(index, 1); } }; }, [state]); return { ...state, toast, dismiss: (toastId) => dispatch({ type: actionTypes.DISMISS_TOAST, toastId }), }; } export { useToast, toast };