@gluestack-ui/core
Version:
Universal UI components for React Native, Expo, and Next.js
108 lines • 4.16 kB
JSX
import React, { useMemo, useState } from 'react';
import { View } from 'react-native';
import { ToastContext } from './ToastContext';
import { ToastList } from './ToastList';
export const ToastProvider = ({ children }) => {
const [toastInfo, setToastInfo] = useState({});
const [visibleToasts, setVisibleToasts] = useState({});
const AnimationWrapper = React.useRef(View);
const AnimatePresence = React.useRef(View);
const toastIndex = React.useRef(1);
const hideAll = React.useCallback(() => {
setVisibleToasts({});
}, [setVisibleToasts]);
const hideToast = React.useCallback((id) => {
setVisibleToasts((prevVisibleToasts) => (Object.assign(Object.assign({}, prevVisibleToasts), { [id]: false })));
}, [setVisibleToasts]);
const isActive = React.useCallback((id) => {
for (const toastPosition of Object.keys(toastInfo)) {
const positionArray = toastInfo[toastPosition];
if (positionArray.findIndex((toastData) => toastData.id === id) > -1) {
return true;
}
}
return false;
}, [toastInfo]);
const removeToast = React.useCallback((id) => {
setToastInfo((prev) => {
for (const toastPosition of Object.keys(prev)) {
const positionArray = prev[toastPosition];
const isToastPresent = positionArray.findIndex((toastData) => toastData.id === id) > -1;
if (isToastPresent) {
const newPositionArray = positionArray.filter((item) => item.id !== id);
const temp = {};
temp[toastPosition] = newPositionArray;
const newToastInfo = Object.assign(Object.assign({}, prev), temp);
return newToastInfo;
}
}
return prev;
});
}, [setToastInfo]);
const setToast = React.useCallback((props) => {
const { placement = 'bottom', render, id = `${toastIndex.current++}`, duration = 5000, } = props;
if (render) {
const component = render({ id });
setToastInfo((prev) => {
return Object.assign(Object.assign({}, prev), { [placement]: [
...(prev[placement] ? prev[placement] : []).filter((t) => t.id !== id),
{ component, id, config: props },
] });
});
setVisibleToasts((toasts) => {
return Object.assign(Object.assign({}, Object.fromEntries(Object.entries(toasts).filter(([key]) => key !== id))), { [id]: true });
});
if (duration !== null) {
setTimeout(function () {
hideToast(id);
}, duration);
}
}
return id;
}, [hideToast]);
const contextValue = React.useMemo(() => {
return {
toastInfo,
setToastInfo,
setToast,
removeToast,
hideAll,
isActive,
visibleToasts,
setVisibleToasts,
hideToast,
AnimationWrapper,
AnimatePresence,
};
}, [
toastInfo,
setToastInfo,
setToast,
removeToast,
hideAll,
isActive,
visibleToasts,
setVisibleToasts,
hideToast,
]);
return (<ToastContext.Provider value={contextValue}>
{children}
<ToastList />
</ToastContext.Provider>);
};
export const getToastHook = (StyledAnimationWrapper, StyledAnimatePresence) => {
const useToast = () => {
const { AnimationWrapper, AnimatePresence, setToast, hideAll, isActive, hideToast, } = React.useContext(ToastContext);
AnimatePresence.current = StyledAnimatePresence;
AnimationWrapper.current = StyledAnimationWrapper;
const toast = useMemo(() => ({
show: setToast,
close: hideToast,
closeAll: hideAll,
isActive,
}), [setToast, hideAll, isActive, hideToast]);
return toast;
};
return useToast;
};
//# sourceMappingURL=Toast.jsx.map