UNPKG

@backpackapp-io/react-native-toast

Version:

A toasting library for React Native. Built in features such as swipe to dismiss, multiple toasts, & no context power this library.

165 lines (163 loc) 4.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useStore = exports.reducer = exports.dispatch = exports.ActionType = void 0; var _react = require("react"); const TOAST_LIMIT = 20; let ActionType = exports.ActionType = /*#__PURE__*/function (ActionType) { ActionType[ActionType["ADD_TOAST"] = 0] = "ADD_TOAST"; ActionType[ActionType["UPDATE_TOAST"] = 1] = "UPDATE_TOAST"; ActionType[ActionType["UPSERT_TOAST"] = 2] = "UPSERT_TOAST"; ActionType[ActionType["DISMISS_TOAST"] = 3] = "DISMISS_TOAST"; ActionType[ActionType["REMOVE_TOAST"] = 4] = "REMOVE_TOAST"; ActionType[ActionType["START_PAUSE"] = 5] = "START_PAUSE"; ActionType[ActionType["END_PAUSE"] = 6] = "END_PAUSE"; return ActionType; }({}); const toastTimeouts = new Map(); const addToRemoveQueue = (toastId, reason) => { if (toastTimeouts.has(toastId)) { return; } const timeout = setTimeout(() => { toastTimeouts.delete(toastId); dispatch({ type: ActionType.REMOVE_TOAST, toastId: toastId, reason }); }, 1000); toastTimeouts.set(toastId, timeout); }; const clearFromRemoveQueue = toastId => { const timeout = toastTimeouts.get(toastId); if (timeout) { clearTimeout(timeout); } }; const reducer = (state, action) => { switch (action.type) { case ActionType.ADD_TOAST: return { ...state, toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT) }; case ActionType.UPDATE_TOAST: // ! Side effects ! if (action.toast.id) { clearFromRemoveQueue(action.toast.id); } return { ...state, toasts: state.toasts.map(t => t.id === action.toast.id ? { ...t, ...action.toast } : t) }; case ActionType.UPSERT_TOAST: const { toast } = action; return state.toasts.find(t => t.id === toast.id) ? reducer(state, { type: ActionType.UPDATE_TOAST, toast }) : reducer(state, { type: ActionType.ADD_TOAST, toast }); case ActionType.DISMISS_TOAST: const { toastId, reason } = action; // ! Side effects ! - This could be execrated into a dismissToast() action, but I'll keep it here for simplicity if (toastId) { addToRemoveQueue(toastId, reason); } else { state.toasts.forEach(toast => { addToRemoveQueue(toast.id, reason); }); } return { ...state, toasts: state.toasts.map(t => t.id === toastId || toastId === undefined ? { ...t, visible: false, dismissReason: reason } : t) }; case ActionType.REMOVE_TOAST: if (action.toastId === undefined) { return { ...state, toasts: [] }; } return { ...state, toasts: state.toasts.filter(t => t.id !== action.toastId) }; case ActionType.START_PAUSE: return { ...state, pausedAt: action.time }; case ActionType.END_PAUSE: const diff = action.time - (state.pausedAt || 0); return { ...state, pausedAt: undefined, toasts: state.toasts.map(t => ({ ...t, pauseDuration: t.pauseDuration + diff })) }; } }; exports.reducer = reducer; const listeners = []; let memoryState = { toasts: [], pausedAt: undefined }; const dispatch = action => { memoryState = reducer(memoryState, action); listeners.forEach(listener => { listener(memoryState); }); }; exports.dispatch = dispatch; const defaultTimeouts = { blank: 4000, error: 4000, success: 2000, loading: Infinity }; const useStore = (toastOptions = {}) => { const [state, setState] = (0, _react.useState)(memoryState); (0, _react.useEffect)(() => { listeners.push(setState); return () => { const index = listeners.indexOf(setState); if (index > -1) { listeners.splice(index, 1); } }; }, [state]); const mergedToasts = state.toasts.filter(t => toastOptions?.providerKey === undefined || t.providerKey === toastOptions?.providerKey || t.providerKey === 'PERSISTS').map(t => ({ ...toastOptions, ...toastOptions[t.type], ...t, duration: t.duration || toastOptions[t.type]?.duration || toastOptions?.duration || defaultTimeouts[t.type], styles: { ...(t?.styles ?? {}) } })); return { ...state, toasts: mergedToasts }; }; exports.useStore = useStore; //# sourceMappingURL=store.js.map