UNPKG

sonner-native

Version:

An opinionated toast component for React Native. A port of @emilkowalski's sonner.

173 lines (172 loc) 6.49 kB
"use strict"; import * as React from 'react'; import { Platform } from 'react-native'; import { FullWindowOverlay } from 'react-native-screens'; import { toastDefaultValues } from "./constants.js"; import { DynamicToastContext, ToastContext } from "./context.js"; import { getOrderedToastIds } from "./position-utils.js"; import { Positioner } from "./positioner.js"; import { Toast } from "./toast.js"; import { toastStore } from "./toast-store.js"; import { jsx as _jsx } from "react/jsx-runtime"; import { createElement as _createElement } from "react"; const allPositions = ['top-center', 'bottom-center', 'center']; const EMPTY_TOAST_OPTIONS = {}; const EMPTY_ICONS = {}; const EMPTY_ANIMATION = {}; function orderToastsFromPosition(currentToasts, position) { return position === 'top-center' ? currentToasts.slice().reverse() : currentToasts; } export const Toaster = ({ ToasterOverlayWrapper, ...toasterProps }) => { const storeState = React.useSyncExternalStore(toastStore.subscribe, toastStore.getSnapshot, toastStore.getSnapshot); const { toasts, shouldShowOverlay, toastHeights, isExpanded, toastHeightsVersion } = storeState; const uiProps = { ...toasterProps, toasts, toastHeights, isExpanded, toastHeightsVersion }; if (!shouldShowOverlay) { return /*#__PURE__*/_jsx(ToasterUI, { ...uiProps }); } if (ToasterOverlayWrapper) { return /*#__PURE__*/_jsx(ToasterOverlayWrapper, { children: /*#__PURE__*/_jsx(ToasterUI, { ...uiProps }) }); } if (Platform.OS === 'ios') { return /*#__PURE__*/_jsx(FullWindowOverlay, { children: /*#__PURE__*/_jsx(ToasterUI, { ...uiProps }) }); } return /*#__PURE__*/_jsx(ToasterUI, { ...uiProps }); }; const ToasterUI = ({ toasts, toastHeights, isExpanded, toastHeightsVersion, duration = toastDefaultValues.duration, position = toastDefaultValues.position, offset = toastDefaultValues.offset, visibleToasts = toastDefaultValues.visibleToasts, swipeToDismissDirection = toastDefaultValues.swipeToDismissDirection, closeButton, invert, allowFontScaling, maxFontSizeMultiplier, toastOptions = EMPTY_TOAST_OPTIONS, icons, pauseWhenPageIsHidden, gap, theme, autoWiggleOnUpdate, richColors, enableStacking = toastDefaultValues.enableStacking, animation, ToastWrapper, positionerStyle, ...props }) => { React.useEffect(() => { toastStore.setConfig({ autoWiggleOnUpdate, visibleToasts, duration, pauseWhenPageIsHidden }); }, [autoWiggleOnUpdate, visibleToasts, duration, pauseWhenPageIsHidden]); const value = React.useMemo(() => ({ duration: duration ?? toastDefaultValues.duration, position: position ?? toastDefaultValues.position, offset: offset ?? toastDefaultValues.offset, swipeToDismissDirection: swipeToDismissDirection ?? toastDefaultValues.swipeToDismissDirection, closeButton: closeButton ?? toastDefaultValues.closeButton, unstyled: toastOptions.unstyled ?? toastDefaultValues.unstyled, addToast: toastStore.addToast, invert: invert ?? toastDefaultValues.invert, allowFontScaling: allowFontScaling ?? toastDefaultValues.allowFontScaling, maxFontSizeMultiplier, icons: icons ?? EMPTY_ICONS, pauseWhenPageIsHidden: pauseWhenPageIsHidden ?? toastDefaultValues.pauseWhenPageIsHidden, gap: gap ?? toastDefaultValues.gap, theme: theme ?? toastDefaultValues.theme, toastOptions, autoWiggleOnUpdate: autoWiggleOnUpdate ?? toastDefaultValues.autoWiggleOnUpdate, richColors: richColors ?? toastDefaultValues.richColors, enableStacking: enableStacking ?? toastDefaultValues.enableStacking, visibleToasts: visibleToasts ?? toastDefaultValues.visibleToasts, animation: animation ?? EMPTY_ANIMATION }), [duration, position, offset, swipeToDismissDirection, closeButton, toastOptions, invert, allowFontScaling, maxFontSizeMultiplier, icons, pauseWhenPageIsHidden, gap, theme, autoWiggleOnUpdate, richColors, enableStacking, visibleToasts, animation]); const dynamicValue = React.useMemo(() => ({ toastHeights, toastHeightsVersion, isExpanded, expand: toastStore.expand, collapse: toastStore.collapse, toggleExpand: toastStore.toggleExpand }), [toastHeights, toastHeightsVersion, isExpanded]); const orderedToasts = React.useMemo(() => orderToastsFromPosition(toasts, position), [toasts, position]); const onDismiss = React.useCallback(id => { toastStore.dismissToast(id, 'onDismiss'); }, []); const onAutoClose = React.useCallback(id => { toastStore.dismissToast(id, 'onAutoClose'); }, []); const possiblePositions = React.useMemo(() => allPositions.filter(possiblePosition => toasts.find(positionedToast => positionedToast.position === possiblePosition) || position === possiblePosition), [toasts, position]); return /*#__PURE__*/_jsx(ToastContext.Provider, { value: value, children: /*#__PURE__*/_jsx(DynamicToastContext.Provider, { value: dynamicValue, children: possiblePositions.map((currentPosition, positionIndex) => { const toastsForPosition = orderedToasts.filter(possibleToast => !possibleToast.position && positionIndex === 0 || possibleToast.position === currentPosition); const orderedToastIds = getOrderedToastIds(toastsForPosition, currentPosition, enableStacking); return /*#__PURE__*/_jsx(Positioner, { style: positionerStyle, position: currentPosition, children: toastsForPosition.map((toastToRender, index) => { const ToastToRender = /*#__PURE__*/_createElement(Toast, { ...props, ...toastToRender, parentStyle: props.style, parentStyles: props.styles, onDismiss: onDismiss, onAutoClose: onAutoClose, index: index, ref: toastStore.getToastRef(toastToRender.id), key: toastToRender.id, numberOfToasts: toastsForPosition.length, orderedToastIds: orderedToastIds }); if (ToastWrapper) { return /*#__PURE__*/_jsx(ToastWrapper, { toastId: toastToRender.id, children: ToastToRender }, toastToRender.id); } return ToastToRender; }) }, currentPosition); }) }) }); }; //# sourceMappingURL=toaster.js.map