@tamagui/toast 1.88.13 → 1.89.0-1706308641099

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,126 @@
1
+ import { styled, useEvent } from "@tamagui/core";
2
+ import { composeEventHandlers, withStaticProperties } from "@tamagui/helpers";
3
+ import { ThemeableStack } from "@tamagui/stacks";
4
+ import { SizableText } from "@tamagui/text";
5
+ import { useControllableState } from "@tamagui/use-controllable-state";
6
+ import * as React from "react";
7
+ import { TOAST_NAME } from "./constants.mjs";
8
+ import { ToastAnnounceExclude } from "./ToastAnnounce.mjs";
9
+ import { useToast, useToastController, useToastState } from "./ToastImperative.mjs";
10
+ import { ToastImpl, ToastImplFrame, useToastInteractiveContext } from "./ToastImpl.mjs";
11
+ import { ToastProvider } from "./ToastProvider.mjs";
12
+ import { ToastViewport } from "./ToastViewport.mjs";
13
+ import { jsx } from "react/jsx-runtime";
14
+ const TITLE_NAME = "ToastTitle",
15
+ ToastTitle = styled(SizableText, {
16
+ name: TITLE_NAME,
17
+ variants: {
18
+ unstyled: {
19
+ false: {
20
+ color: "$color",
21
+ size: "$4"
22
+ }
23
+ }
24
+ },
25
+ defaultVariants: {
26
+ unstyled: process.env.TAMAGUI_HEADLESS === "1"
27
+ }
28
+ });
29
+ ToastTitle.displayName = TITLE_NAME;
30
+ const DESCRIPTION_NAME = "ToastDescription",
31
+ ToastDescription = styled(SizableText, {
32
+ name: DESCRIPTION_NAME,
33
+ variants: {
34
+ unstyled: {
35
+ false: {
36
+ color: "$color11",
37
+ size: "$1"
38
+ }
39
+ }
40
+ },
41
+ defaultVariants: {
42
+ unstyled: process.env.TAMAGUI_HEADLESS === "1"
43
+ }
44
+ });
45
+ ToastDescription.displayName = DESCRIPTION_NAME;
46
+ const ACTION_NAME = "ToastAction",
47
+ ToastAction = React.forwardRef((props, forwardedRef) => {
48
+ const {
49
+ altText,
50
+ ...actionProps
51
+ } = props;
52
+ return altText ? /* @__PURE__ */jsx(ToastAnnounceExclude, {
53
+ altText,
54
+ asChild: !0,
55
+ children: /* @__PURE__ */jsx(ToastClose, {
56
+ ...actionProps,
57
+ ref: forwardedRef
58
+ })
59
+ }) : null;
60
+ });
61
+ ToastAction.propTypes = {
62
+ altText(props) {
63
+ return props.altText ? null : new Error(`Missing prop \`altText\` expected on \`${ACTION_NAME}\``);
64
+ }
65
+ };
66
+ ToastAction.displayName = ACTION_NAME;
67
+ const CLOSE_NAME = "ToastClose",
68
+ ToastCloseFrame = styled(ThemeableStack, {
69
+ name: CLOSE_NAME,
70
+ tag: "button"
71
+ }),
72
+ ToastClose = React.forwardRef((props, forwardedRef) => {
73
+ const {
74
+ __scopeToast,
75
+ ...closeProps
76
+ } = props,
77
+ interactiveContext = useToastInteractiveContext(__scopeToast);
78
+ return /* @__PURE__ */jsx(ToastAnnounceExclude, {
79
+ asChild: !0,
80
+ children: /* @__PURE__ */jsx(ToastCloseFrame, {
81
+ accessibilityLabel: "Dialog Close",
82
+ ...closeProps,
83
+ ref: forwardedRef,
84
+ onPress: composeEventHandlers(props.onPress, interactiveContext.onClose)
85
+ })
86
+ });
87
+ });
88
+ ToastClose.displayName = CLOSE_NAME;
89
+ const ToastComponent = ToastImplFrame.styleable((props, forwardedRef) => {
90
+ const {
91
+ forceMount,
92
+ open: openProp,
93
+ defaultOpen,
94
+ onOpenChange,
95
+ ...toastProps
96
+ } = props,
97
+ [open, setOpen] = useControllableState({
98
+ prop: openProp,
99
+ defaultProp: defaultOpen ?? !0,
100
+ onChange: onOpenChange,
101
+ strategy: "most-recent-wins"
102
+ }),
103
+ id = React.useId(),
104
+ onPause = useEvent(props.onPause),
105
+ onResume = useEvent(props.onResume);
106
+ return forceMount || open ? /* @__PURE__ */jsx(ToastImpl, {
107
+ id,
108
+ open,
109
+ ...toastProps,
110
+ ref: forwardedRef,
111
+ onClose: () => setOpen(!1),
112
+ onPause,
113
+ onResume,
114
+ onSwipeEnd: composeEventHandlers(props.onSwipeEnd, event => {
115
+ setOpen(!1);
116
+ })
117
+ }) : null;
118
+ });
119
+ ToastComponent.displayName = TOAST_NAME;
120
+ const Toast = withStaticProperties(ToastComponent, {
121
+ Title: ToastTitle,
122
+ Description: ToastDescription,
123
+ Action: ToastAction,
124
+ Close: ToastClose
125
+ });
126
+ export { Toast, ToastProvider, ToastViewport, useToast, useToastController, useToastState };
@@ -0,0 +1,57 @@
1
+ import { useIsomorphicLayoutEffect } from "@tamagui/constants";
2
+ import { Stack, Text, styled, useEvent } from "@tamagui/core";
3
+ import { Portal } from "@tamagui/portal";
4
+ import { VisuallyHidden } from "@tamagui/visually-hidden";
5
+ import * as React from "react";
6
+ import { useToastProviderContext } from "./ToastProvider.mjs";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ const ToastAnnounceExcludeFrame = styled(Stack, {
9
+ name: "ToastAnnounceExclude"
10
+ }),
11
+ ToastAnnounceExclude = React.forwardRef((props, forwardedRef) => {
12
+ const {
13
+ altText,
14
+ ...announceExcludeProps
15
+ } = props;
16
+ return /* @__PURE__ */jsx(ToastAnnounceExcludeFrame, {
17
+ "data-toast-announce-exclude": "",
18
+ "data-toast-announce-alt": altText || void 0,
19
+ ...announceExcludeProps,
20
+ ref: forwardedRef
21
+ });
22
+ }),
23
+ ToastAnnounce = props => {
24
+ const {
25
+ __scopeToast,
26
+ children,
27
+ ...announceProps
28
+ } = props,
29
+ context = useToastProviderContext(__scopeToast),
30
+ [renderAnnounceText, setRenderAnnounceText] = React.useState(!1),
31
+ [isAnnounced, setIsAnnounced] = React.useState(!1);
32
+ return useNextFrame(() => setRenderAnnounceText(!0)), React.useEffect(() => {
33
+ const timer = setTimeout(() => setIsAnnounced(!0), 1e3);
34
+ return () => clearTimeout(timer);
35
+ }, []), isAnnounced ? null : /* @__PURE__ */jsx(Portal, {
36
+ asChild: !0,
37
+ children: /* @__PURE__ */jsx(VisuallyHidden, {
38
+ ...announceProps,
39
+ children: renderAnnounceText && /* @__PURE__ */jsxs(Text, {
40
+ children: [context.label, " ", children]
41
+ })
42
+ })
43
+ });
44
+ };
45
+ function useNextFrame(callback = () => {}) {
46
+ const fn = useEvent(callback);
47
+ useIsomorphicLayoutEffect(() => {
48
+ let raf1 = 0,
49
+ raf2 = 0;
50
+ return raf1 = requestAnimationFrame(() => {
51
+ raf2 = requestAnimationFrame(fn);
52
+ }), () => {
53
+ cancelAnimationFrame(raf1), cancelAnimationFrame(raf2);
54
+ };
55
+ }, [fn]);
56
+ }
57
+ export { ToastAnnounce, ToastAnnounceExclude };
@@ -0,0 +1,58 @@
1
+ import { isWeb } from "@tamagui/core";
2
+ import React, { createContext, useContext, useMemo, useRef } from "react";
3
+ import { Platform } from "react-native-web";
4
+ import { createNativeToast } from "./createNativeToast.mjs";
5
+ import { jsx } from "react/jsx-runtime";
6
+ const ToastContext = createContext({}),
7
+ ToastCurrentContext = createContext(null),
8
+ useToastController = () => useContext(ToastContext),
9
+ useToastState = () => useContext(ToastCurrentContext),
10
+ useToast = () => ({
11
+ ...useToastController(),
12
+ currentToast: useToastState()
13
+ }),
14
+ ToastImperativeProvider = ({
15
+ children,
16
+ options
17
+ }) => {
18
+ const counterRef = useRef(0),
19
+ [toast, setToast] = React.useState(null),
20
+ [lastNativeToastRef, setLastNativeToastRef] = React.useState(null),
21
+ show = React.useCallback((title, showOptions) => {
22
+ const native = showOptions?.native ?? options.native,
23
+ isWebNative = Array.isArray(native) ? native.includes("web") : native === "web",
24
+ isMobileNative = Array.isArray(native) ? native.includes("mobile") : native === "mobile",
25
+ isAndroidNative = isMobileNative || (Array.isArray(native) ? native.includes("android") : native === "android"),
26
+ isIosNative = isMobileNative || (Array.isArray(native) ? native.includes("ios") : native === "ios"),
27
+ isHandledNatively = native === !0 || isWeb && isWebNative || !isWeb && isMobileNative || Platform.OS === "android" && isAndroidNative || Platform.OS === "ios" && isIosNative;
28
+ if (isHandledNatively) {
29
+ const nativeToastResult = createNativeToast(title, showOptions ?? {});
30
+ typeof nativeToastResult == "object" && nativeToastResult.nativeToastRef && setLastNativeToastRef(nativeToastResult.nativeToastRef);
31
+ }
32
+ return counterRef.current++, setToast({
33
+ ...showOptions?.customData,
34
+ ...showOptions,
35
+ viewportName: showOptions?.viewportName ?? "default",
36
+ title,
37
+ id: counterRef.current.toString(),
38
+ isHandledNatively
39
+ }), !0;
40
+ }, [setToast, options.native]),
41
+ hide = React.useCallback(() => {
42
+ lastNativeToastRef?.close(), setToast(null);
43
+ }, [setToast, lastNativeToastRef]),
44
+ contextValue = useMemo(() => ({
45
+ show,
46
+ hide,
47
+ nativeToast: lastNativeToastRef,
48
+ options
49
+ }), [show, hide, lastNativeToastRef, JSON.stringify(options || null)]);
50
+ return /* @__PURE__ */jsx(ToastContext.Provider, {
51
+ value: contextValue,
52
+ children: /* @__PURE__ */jsx(ToastCurrentContext.Provider, {
53
+ value: toast,
54
+ children
55
+ })
56
+ });
57
+ };
58
+ export { ToastImperativeProvider, useToast, useToastController, useToastState };
@@ -0,0 +1,251 @@
1
+ import { useIsPresent } from "@tamagui/animate-presence";
2
+ import { useComposedRefs } from "@tamagui/compose-refs";
3
+ import { isWeb } from "@tamagui/constants";
4
+ import { Stack, Theme, createStyledContext, styled, useConfiguration, useEvent, useThemeName } from "@tamagui/core";
5
+ import { Dismissable } from "@tamagui/dismissable";
6
+ import { composeEventHandlers } from "@tamagui/helpers";
7
+ import { PortalItem } from "@tamagui/portal";
8
+ import { ThemeableStack } from "@tamagui/stacks";
9
+ import * as React from "react";
10
+ import { PanResponder } from "react-native-web";
11
+ import { TOAST_CONTEXT, TOAST_NAME } from "./constants.mjs";
12
+ import { ToastAnnounce } from "./ToastAnnounce.mjs";
13
+ import { Collection, useToastProviderContext } from "./ToastProvider.mjs";
14
+ import { VIEWPORT_PAUSE, VIEWPORT_RESUME } from "./ToastViewport.mjs";
15
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
16
+ const ToastImplFrame = styled(ThemeableStack, {
17
+ name: "ToastImpl",
18
+ focusable: !0,
19
+ variants: {
20
+ unstyled: {
21
+ false: {
22
+ focusStyle: {
23
+ outlineStyle: "solid",
24
+ outlineWidth: 2,
25
+ outlineColor: "$outlineColor"
26
+ },
27
+ backgroundColor: "$color6",
28
+ borderRadius: "$10",
29
+ paddingHorizontal: "$5",
30
+ paddingVertical: "$2",
31
+ marginHorizontal: "auto",
32
+ marginVertical: "$1"
33
+ }
34
+ }
35
+ },
36
+ defaultVariants: {
37
+ unstyled: process.env.TAMAGUI_HEADLESS === "1"
38
+ }
39
+ }),
40
+ {
41
+ Provider: ToastInteractiveProvider,
42
+ useStyledContext: useToastInteractiveContext
43
+ } = createStyledContext({
44
+ onClose() {}
45
+ }),
46
+ ToastImpl = React.forwardRef((props, forwardedRef) => {
47
+ const {
48
+ __scopeToast,
49
+ type = "foreground",
50
+ duration: durationProp,
51
+ open,
52
+ onClose,
53
+ onEscapeKeyDown,
54
+ onPause,
55
+ onResume,
56
+ onSwipeStart,
57
+ onSwipeMove,
58
+ onSwipeCancel,
59
+ onSwipeEnd,
60
+ viewportName = "default",
61
+ ...toastProps
62
+ } = props,
63
+ isPresent = useIsPresent(),
64
+ context = useToastProviderContext(__scopeToast),
65
+ [node, setNode] = React.useState(null),
66
+ composedRefs = useComposedRefs(forwardedRef, node2 => setNode(node2)),
67
+ duration = durationProp || context.duration,
68
+ closeTimerStartTimeRef = React.useRef(0),
69
+ closeTimerRemainingTimeRef = React.useRef(duration),
70
+ closeTimerRef = React.useRef(0),
71
+ {
72
+ onToastAdd,
73
+ onToastRemove
74
+ } = context,
75
+ viewport = React.useMemo(() => context.viewports[viewportName], [context.viewports, viewportName]),
76
+ handleClose = useEvent(() => {
77
+ isPresent && (isWeb && node?.contains(document.activeElement) && viewport?.focus(), onClose());
78
+ }),
79
+ startTimer = React.useCallback(duration2 => {
80
+ !duration2 || duration2 === 1 / 0 || (clearTimeout(closeTimerRef.current), closeTimerStartTimeRef.current = /* @__PURE__ */new Date().getTime(), closeTimerRef.current = setTimeout(handleClose, duration2));
81
+ }, [handleClose]),
82
+ handleResume = React.useCallback(() => {
83
+ startTimer(closeTimerRemainingTimeRef.current), onResume?.();
84
+ }, [onResume, startTimer]),
85
+ handlePause = React.useCallback(() => {
86
+ const elapsedTime = /* @__PURE__ */new Date().getTime() - closeTimerStartTimeRef.current;
87
+ closeTimerRemainingTimeRef.current = closeTimerRemainingTimeRef.current - elapsedTime, window.clearTimeout(closeTimerRef.current), onPause?.();
88
+ }, [onPause]);
89
+ React.useEffect(() => {
90
+ if (isWeb && viewport) return viewport.addEventListener(VIEWPORT_PAUSE, handlePause), viewport.addEventListener(VIEWPORT_RESUME, handleResume), () => {
91
+ viewport.removeEventListener(VIEWPORT_PAUSE, handlePause), viewport.removeEventListener(VIEWPORT_RESUME, handleResume);
92
+ };
93
+ }, [viewport, duration, onPause, onResume, startTimer]), React.useEffect(() => {
94
+ open && !context.isClosePausedRef.current && startTimer(duration);
95
+ }, [open, duration, context.isClosePausedRef, startTimer]), React.useEffect(() => (onToastAdd(), () => onToastRemove()), [onToastAdd, onToastRemove]);
96
+ const announceTextContent = React.useMemo(() => isWeb && node ? getAnnounceTextContent(node) : null, [node]),
97
+ isHorizontalSwipe = ["left", "right", "horizontal"].includes(context.swipeDirection),
98
+ {
99
+ animationDriver
100
+ } = useConfiguration();
101
+ if (!animationDriver) throw new Error("Must set animations in tamagui.config.ts");
102
+ const {
103
+ useAnimatedNumber,
104
+ useAnimatedNumberStyle
105
+ } = animationDriver,
106
+ animatedNumber = useAnimatedNumber(0),
107
+ AnimatedView = animationDriver.NumberView ?? animationDriver.View ?? Stack,
108
+ animatedStyles = useAnimatedNumberStyle(animatedNumber, val => {
109
+ "worklet";
110
+
111
+ return {
112
+ transform: [isHorizontalSwipe ? {
113
+ translateX: val
114
+ } : {
115
+ translateY: val
116
+ }]
117
+ };
118
+ }),
119
+ panResponder = React.useMemo(() => PanResponder.create({
120
+ onMoveShouldSetPanResponder: (e, gesture) => shouldGrantGestureMove(context.swipeDirection, gesture) ? (onSwipeStart?.(e), !0) : !1,
121
+ onPanResponderGrant: e => {
122
+ isWeb || handlePause?.();
123
+ },
124
+ onPanResponderMove: (e, gesture) => {
125
+ const {
126
+ x,
127
+ y
128
+ } = getGestureDistance(context.swipeDirection, gesture),
129
+ delta = {
130
+ x,
131
+ y
132
+ };
133
+ animatedNumber.setValue(isHorizontalSwipe ? x : y, {
134
+ type: "direct"
135
+ }), isDeltaInDirection(delta, context.swipeDirection, context.swipeThreshold) && onSwipeEnd?.(e), onSwipeMove?.(e);
136
+ },
137
+ onPanResponderEnd: (e, {
138
+ dx,
139
+ dy
140
+ }) => {
141
+ isDeltaInDirection({
142
+ x: dx,
143
+ y: dy
144
+ }, context.swipeDirection, context.swipeThreshold) || (isWeb || handleResume?.(), onSwipeCancel?.(e), animatedNumber.setValue(0, {
145
+ type: "spring"
146
+ }));
147
+ }
148
+ }), [handlePause, handleResume]),
149
+ themeName = useThemeName();
150
+ return /* @__PURE__ */jsxs(Fragment, {
151
+ children: [announceTextContent && /* @__PURE__ */jsx(ToastAnnounce, {
152
+ __scopeToast,
153
+ role: "status",
154
+ "aria-live": type === "foreground" ? "assertive" : "polite",
155
+ "aria-atomic": !0,
156
+ children: announceTextContent
157
+ }), /* @__PURE__ */jsx(PortalItem, {
158
+ hostName: viewportName ?? "default",
159
+ children: /* @__PURE__ */jsx(ToastInteractiveProvider, {
160
+ scope: __scopeToast,
161
+ onClose: () => {
162
+ handleClose();
163
+ },
164
+ children: /* @__PURE__ */jsx(Dismissable, {
165
+ onEscapeKeyDown: composeEventHandlers(onEscapeKeyDown, () => {
166
+ context.isFocusedToastEscapeKeyDownRef.current || handleClose(), context.isFocusedToastEscapeKeyDownRef.current = !1;
167
+ }),
168
+ children: /* @__PURE__ */jsx(Theme, {
169
+ forceClassName: !0,
170
+ name: themeName,
171
+ children: /* @__PURE__ */jsx(AnimatedView, {
172
+ ...panResponder?.panHandlers,
173
+ style: [{
174
+ margin: "auto"
175
+ }, animatedStyles],
176
+ children: /* @__PURE__ */jsx(Collection.ItemSlot, {
177
+ __scopeCollection: __scopeToast || TOAST_CONTEXT,
178
+ children: /* @__PURE__ */jsx(ToastImplFrame, {
179
+ role: "status",
180
+ "aria-live": "off",
181
+ "aria-atomic": !0,
182
+ "data-state": open ? "open" : "closed",
183
+ "data-swipe-direction": context.swipeDirection,
184
+ pointerEvents: "auto",
185
+ touchAction: "none",
186
+ userSelect: "none",
187
+ ...toastProps,
188
+ ref: composedRefs,
189
+ ...(isWeb && {
190
+ onKeyDown: composeEventHandlers(props.onKeyDown, event => {
191
+ event.key === "Escape" && (onEscapeKeyDown?.(event), onEscapeKeyDown?.(event), event.defaultPrevented || (context.isFocusedToastEscapeKeyDownRef.current = !0, handleClose()));
192
+ })
193
+ })
194
+ })
195
+ })
196
+ })
197
+ })
198
+ })
199
+ }, props.id)
200
+ })]
201
+ });
202
+ });
203
+ ToastImpl.propTypes = {
204
+ type(props) {
205
+ if (props.type && !["foreground", "background"].includes(props.type)) {
206
+ const error = `Invalid prop \`type\` supplied to \`${TOAST_NAME}\`. Expected \`foreground | background\`.`;
207
+ return new Error(error);
208
+ }
209
+ return null;
210
+ }
211
+ };
212
+ const isDeltaInDirection = (delta, direction, threshold = 0) => {
213
+ const deltaX = Math.abs(delta.x),
214
+ deltaY = Math.abs(delta.y),
215
+ isDeltaX = deltaX > deltaY;
216
+ return direction === "left" || direction === "right" || direction === "horizontal" ? isDeltaX && deltaX > threshold : !isDeltaX && deltaY > threshold;
217
+ };
218
+ function getAnnounceTextContent(container) {
219
+ if (!isWeb) return "";
220
+ const textContent = [];
221
+ return Array.from(container.childNodes).forEach(node => {
222
+ if (node.nodeType === node.TEXT_NODE && node.textContent && textContent.push(node.textContent), isHTMLElement(node)) {
223
+ const isHidden = node.ariaHidden || node.hidden || node.style.display === "none",
224
+ isExcluded = node.dataset.toastAnnounceExclude === "";
225
+ if (!isHidden) if (isExcluded) {
226
+ const altText = node.dataset.toastAnnounceAlt;
227
+ altText && textContent.push(altText);
228
+ } else textContent.push(...getAnnounceTextContent(node));
229
+ }
230
+ }), textContent;
231
+ }
232
+ function isHTMLElement(node) {
233
+ return node.nodeType === node.ELEMENT_NODE;
234
+ }
235
+ const GESTURE_GRANT_THRESHOLD = 10,
236
+ shouldGrantGestureMove = (dir, {
237
+ dx,
238
+ dy
239
+ }) => (dir === "horizontal" || dir === "left") && dx < -GESTURE_GRANT_THRESHOLD || (dir === "horizontal" || dir === "right") && dx > GESTURE_GRANT_THRESHOLD || (dir === "vertical" || dir === "up") && dy > -GESTURE_GRANT_THRESHOLD || (dir === "vertical" || dir === "down") && dy < GESTURE_GRANT_THRESHOLD,
240
+ getGestureDistance = (dir, {
241
+ dx,
242
+ dy
243
+ }) => {
244
+ let y = 0,
245
+ x = 0;
246
+ return dir === "horizontal" ? x = dx : dir === "left" ? x = Math.min(0, dx) : dir === "right" ? x = Math.max(0, dx) : dir === "vertical" ? y = dy : dir === "up" ? y = Math.min(0, dy) : dir === "down" && (y = Math.max(0, dy)), {
247
+ x,
248
+ y
249
+ };
250
+ };
251
+ export { ToastImpl, ToastImplFrame, useToastInteractiveContext };
@@ -0,0 +1,18 @@
1
+ import { Portal } from "@tamagui/portal";
2
+ import { Platform } from "react-native-web";
3
+ import { ReprogapateToastProvider, useToastProviderContext } from "./ToastProvider.mjs";
4
+ import { jsx } from "react/jsx-runtime";
5
+ function ToastPortal({
6
+ children,
7
+ zIndex
8
+ }) {
9
+ let content = children;
10
+ return Platform.OS === "android" && (content = /* @__PURE__ */jsx(ReprogapateToastProvider, {
11
+ context: useToastProviderContext(),
12
+ children
13
+ })), /* @__PURE__ */jsx(Portal, {
14
+ zIndex: zIndex || 1e9,
15
+ children: content
16
+ });
17
+ }
18
+ export { ToastPortal };
@@ -0,0 +1,98 @@
1
+ import { createCollection } from "@tamagui/collection";
2
+ import { createStyledContext } from "@tamagui/core";
3
+ import * as React from "react";
4
+ import { TOAST_CONTEXT } from "./constants.mjs";
5
+ import { ToastImperativeProvider } from "./ToastImperative.mjs";
6
+ import { jsx } from "react/jsx-runtime";
7
+ const PROVIDER_NAME = "ToastProvider",
8
+ [Collection, useCollection] = createCollection("Toast"),
9
+ {
10
+ Provider: ToastProviderProvider,
11
+ useStyledContext: useToastProviderContext
12
+ } = createStyledContext(),
13
+ ToastProvider = props => {
14
+ const {
15
+ __scopeToast,
16
+ id: providedId,
17
+ burntOptions,
18
+ native,
19
+ notificationOptions,
20
+ label = "Notification",
21
+ duration = 5e3,
22
+ swipeDirection = "right",
23
+ swipeThreshold = 50,
24
+ children
25
+ } = props,
26
+ backupId = React.useId(),
27
+ id = providedId ?? backupId,
28
+ [viewports, setViewports] = React.useState({}),
29
+ [toastCount, setToastCount] = React.useState(0),
30
+ isFocusedToastEscapeKeyDownRef = React.useRef(!1),
31
+ isClosePausedRef = React.useRef(!1),
32
+ handleViewportChange = React.useCallback((name, viewport) => {
33
+ setViewports(prev => ({
34
+ ...prev,
35
+ [name]: viewport
36
+ }));
37
+ }, []),
38
+ options = React.useMemo(() => ({
39
+ duration,
40
+ burntOptions,
41
+ native,
42
+ notificationOptions
43
+ }), [JSON.stringify([duration, burntOptions, native, notificationOptions])]);
44
+ return /* @__PURE__ */jsx(Collection.Provider, {
45
+ __scopeCollection: __scopeToast || TOAST_CONTEXT,
46
+ children: /* @__PURE__ */jsx(ToastProviderProvider, {
47
+ scope: __scopeToast,
48
+ id,
49
+ label,
50
+ duration,
51
+ swipeDirection,
52
+ swipeThreshold,
53
+ toastCount,
54
+ viewports,
55
+ onViewportChange: handleViewportChange,
56
+ onToastAdd: React.useCallback(() => {
57
+ setToastCount(prevCount => prevCount + 1);
58
+ }, []),
59
+ onToastRemove: React.useCallback(() => {
60
+ setToastCount(prevCount => prevCount - 1);
61
+ }, []),
62
+ isFocusedToastEscapeKeyDownRef,
63
+ isClosePausedRef,
64
+ options,
65
+ children: /* @__PURE__ */jsx(ToastImperativeProvider, {
66
+ options,
67
+ children
68
+ })
69
+ })
70
+ });
71
+ };
72
+ function ReprogapateToastProvider(props) {
73
+ const {
74
+ children,
75
+ context
76
+ } = props;
77
+ return /* @__PURE__ */jsx(Collection.Provider, {
78
+ __scopeCollection: TOAST_CONTEXT,
79
+ children: /* @__PURE__ */jsx(ToastProviderProvider, {
80
+ ...context,
81
+ children: /* @__PURE__ */jsx(ToastImperativeProvider, {
82
+ options: context.options,
83
+ children
84
+ })
85
+ })
86
+ });
87
+ }
88
+ ToastProvider.propTypes = {
89
+ label(props) {
90
+ if (props.label && typeof props.label == "string" && !props.label.trim()) {
91
+ const error = `Invalid prop \`label\` supplied to \`${PROVIDER_NAME}\`. Expected non-empty \`string\`.`;
92
+ return new Error(error);
93
+ }
94
+ return null;
95
+ }
96
+ };
97
+ ToastProvider.displayName = PROVIDER_NAME;
98
+ export { Collection, ReprogapateToastProvider, ToastProvider, useCollection, useToastProviderContext };