@tamagui/toast 1.2.8 → 1.2.10

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,562 @@
1
+ import { useComposedRefs } from "@tamagui/compose-refs";
2
+ import {
3
+ composeEventHandlers,
4
+ isWeb,
5
+ useEvent,
6
+ useIsomorphicLayoutEffect
7
+ } from "@tamagui/core";
8
+ import { Portal } from "@tamagui/portal";
9
+ import { YStack } from "@tamagui/stacks";
10
+ import { useControllableState } from "@tamagui/use-controllable-state";
11
+ import { VisuallyHidden } from "@tamagui/visually-hidden";
12
+ import * as React from "react";
13
+ import * as ReactDOM from "react-dom";
14
+ const PROVIDER_NAME = "ToastProvider";
15
+ const [ToastProviderProvider, useToastProviderContext] = [];
16
+ const ToastProvider = (props) => {
17
+ const {
18
+ __scopeToast,
19
+ label = "Notification",
20
+ duration = 5e3,
21
+ swipeDirection = "right",
22
+ swipeThreshold = 50,
23
+ children
24
+ } = props;
25
+ const [viewport, setViewport] = React.useState(null);
26
+ const [toastCount, setToastCount] = React.useState(0);
27
+ const isFocusedToastEscapeKeyDownRef = React.useRef(false);
28
+ const isClosePausedRef = React.useRef(false);
29
+ return (
30
+ // <Collection.Provider scope={__scopeToast}>
31
+ <ToastProviderProvider
32
+ scope={__scopeToast}
33
+ label={label}
34
+ duration={duration}
35
+ swipeDirection={swipeDirection}
36
+ swipeThreshold={swipeThreshold}
37
+ toastCount={toastCount}
38
+ viewport={viewport}
39
+ onViewportChange={setViewport}
40
+ onToastAdd={React.useCallback(
41
+ () => setToastCount((prevCount) => prevCount + 1),
42
+ []
43
+ )}
44
+ onToastRemove={React.useCallback(
45
+ () => setToastCount((prevCount) => prevCount - 1),
46
+ []
47
+ )}
48
+ isFocusedToastEscapeKeyDownRef={isFocusedToastEscapeKeyDownRef}
49
+ isClosePausedRef={isClosePausedRef}
50
+ >{children}</ToastProviderProvider>
51
+ );
52
+ };
53
+ ToastProvider.propTypes = {
54
+ label(props) {
55
+ if (props.label && typeof props.label === "string" && !props.label.trim()) {
56
+ const error = `Invalid prop \`label\` supplied to \`${PROVIDER_NAME}\`. Expected non-empty \`string\`.`;
57
+ return new Error(error);
58
+ }
59
+ return null;
60
+ }
61
+ };
62
+ ToastProvider.displayName = PROVIDER_NAME;
63
+ const VIEWPORT_NAME = "ToastViewport";
64
+ const VIEWPORT_DEFAULT_HOTKEY = ["F8"];
65
+ const VIEWPORT_PAUSE = "toast.viewportPause";
66
+ const VIEWPORT_RESUME = "toast.viewportResume";
67
+ const ToastViewport = React.forwardRef(
68
+ (props, forwardedRef) => {
69
+ const {
70
+ __scopeToast,
71
+ hotkey = VIEWPORT_DEFAULT_HOTKEY,
72
+ label = "Notifications ({hotkey})",
73
+ ...viewportProps
74
+ } = props;
75
+ const context = useToastProviderContext(VIEWPORT_NAME, __scopeToast);
76
+ const wrapperRef = React.useRef(null);
77
+ const headFocusProxyRef = React.useRef(null);
78
+ const tailFocusProxyRef = React.useRef(null);
79
+ const ref = React.useRef(null);
80
+ const composedRefs = useComposedRefs(forwardedRef, ref, context.onViewportChange);
81
+ const hotkeyLabel = hotkey.join("+").replace(/Key/g, "").replace(/Digit/g, "");
82
+ const hasToasts = context.toastCount > 0;
83
+ React.useEffect(() => {
84
+ const handleKeyDown = (event) => {
85
+ const isHotkeyPressed = hotkey.every(
86
+ (key) => event[key] || event.code === key
87
+ );
88
+ if (isHotkeyPressed)
89
+ ref.current?.focus();
90
+ };
91
+ document.addEventListener("keydown", handleKeyDown);
92
+ return () => document.removeEventListener("keydown", handleKeyDown);
93
+ }, [hotkey]);
94
+ React.useEffect(() => {
95
+ const wrapper = wrapperRef.current;
96
+ const viewport = ref.current;
97
+ if (wrapper && viewport) {
98
+ const handlePause = () => {
99
+ const pauseEvent = new CustomEvent(VIEWPORT_PAUSE);
100
+ context.isClosePausedRef.current = true;
101
+ };
102
+ const handleResume = () => {
103
+ const resumeEvent = new CustomEvent(VIEWPORT_RESUME);
104
+ context.isClosePausedRef.current = false;
105
+ };
106
+ wrapper.addEventListener("focusin", handlePause);
107
+ wrapper.addEventListener("focusout", handleResume);
108
+ wrapper.addEventListener("pointerenter", handlePause);
109
+ wrapper.addEventListener("pointerleave", handleResume);
110
+ window.addEventListener("blur", handlePause);
111
+ window.addEventListener("focus", handleResume);
112
+ return () => {
113
+ wrapper.removeEventListener("focusin", handlePause);
114
+ wrapper.removeEventListener("focusout", handleResume);
115
+ wrapper.removeEventListener("pointerenter", handlePause);
116
+ wrapper.removeEventListener("pointerleave", handleResume);
117
+ window.removeEventListener("blur", handlePause);
118
+ window.removeEventListener("focus", handleResume);
119
+ };
120
+ }
121
+ }, [context.isClosePausedRef]);
122
+ React.useEffect(
123
+ () => {
124
+ const viewport = ref.current;
125
+ if (viewport) {
126
+ const handleKeyDown = (event) => {
127
+ const isMetaKey = event.altKey || event.ctrlKey || event.metaKey;
128
+ const isTabKey = event.key === "Tab" && !isMetaKey;
129
+ if (isTabKey) {
130
+ const focusedElement = document.activeElement;
131
+ const isTabbingBackwards = event.shiftKey;
132
+ const targetIsViewport = event.target === viewport;
133
+ if (targetIsViewport && isTabbingBackwards) {
134
+ headFocusProxyRef.current?.focus();
135
+ return;
136
+ }
137
+ const tabbingDirection = isTabbingBackwards ? "backwards" : "forwards";
138
+ }
139
+ };
140
+ return () => {
141
+ };
142
+ }
143
+ },
144
+ [
145
+ // getItems, getSortedTabbableCandidates
146
+ ]
147
+ );
148
+ return null;
149
+ }
150
+ );
151
+ ToastViewport.displayName = VIEWPORT_NAME;
152
+ const FOCUS_PROXY_NAME = "ToastFocusProxy";
153
+ const FocusProxy = React.forwardRef(
154
+ (props, forwardedRef) => {
155
+ const { __scopeToast, onFocusFromOutsideViewport, ...proxyProps } = props;
156
+ const context = useToastProviderContext(FOCUS_PROXY_NAME, __scopeToast);
157
+ return <VisuallyHidden
158
+ aria-hidden
159
+ tabIndex={0}
160
+ {...proxyProps}
161
+ ref={forwardedRef}
162
+ position={isWeb ? "fixed" : "absolute"}
163
+ onFocus={(event) => {
164
+ const prevFocusedElement = event.relatedTarget;
165
+ const isFocusFromOutsideViewport = !context.viewport?.contains(prevFocusedElement);
166
+ if (isFocusFromOutsideViewport)
167
+ onFocusFromOutsideViewport();
168
+ }}
169
+ />;
170
+ }
171
+ );
172
+ FocusProxy.displayName = FOCUS_PROXY_NAME;
173
+ const TOAST_NAME = "Toast";
174
+ const TOAST_SWIPE_START = "toast.swipeStart";
175
+ const TOAST_SWIPE_MOVE = "toast.swipeMove";
176
+ const TOAST_SWIPE_CANCEL = "toast.swipeCancel";
177
+ const TOAST_SWIPE_END = "toast.swipeEnd";
178
+ const Toast = React.forwardRef(
179
+ (props, forwardedRef) => {
180
+ const {
181
+ forceMount,
182
+ open: openProp,
183
+ defaultOpen,
184
+ onOpenChange,
185
+ ...toastProps
186
+ } = props;
187
+ const [open, setOpen] = useControllableState({
188
+ prop: openProp,
189
+ defaultProp: true,
190
+ onChange: onOpenChange,
191
+ transition: true
192
+ });
193
+ return (
194
+ // <Presence present={forceMount || open}>
195
+ <ToastImpl
196
+ open={open}
197
+ {...toastProps}
198
+ ref={forwardedRef}
199
+ onClose={() => setOpen(false)}
200
+ />
201
+ );
202
+ }
203
+ );
204
+ Toast.displayName = TOAST_NAME;
205
+ const [ToastInteractiveProvider, useToastInteractiveContext] = {};
206
+ const ToastImpl = React.forwardRef(
207
+ (props, forwardedRef) => {
208
+ const {
209
+ __scopeToast,
210
+ type = "foreground",
211
+ duration: durationProp,
212
+ open,
213
+ onClose,
214
+ onEscapeKeyDown,
215
+ onSwipeStart,
216
+ onSwipeMove,
217
+ onSwipeCancel,
218
+ onSwipeEnd,
219
+ ...toastProps
220
+ } = props;
221
+ const context = useToastProviderContext(TOAST_NAME, __scopeToast);
222
+ const ref = React.useRef(null);
223
+ const composedRefs = useComposedRefs(forwardedRef, ref);
224
+ const pointerStartRef = React.useRef(null);
225
+ const swipeDeltaRef = React.useRef(null);
226
+ const duration = durationProp || context.duration;
227
+ const closeTimerStartTimeRef = React.useRef(0);
228
+ const closeTimerRemainingTimeRef = React.useRef(duration);
229
+ const closeTimerRef = React.useRef(0);
230
+ const { onToastAdd, onToastRemove } = context;
231
+ const handleClose = useEvent(() => {
232
+ onClose();
233
+ });
234
+ const startTimer = React.useCallback(
235
+ (duration2) => {
236
+ if (!duration2 || duration2 === Infinity)
237
+ return;
238
+ window.clearTimeout(closeTimerRef.current);
239
+ closeTimerStartTimeRef.current = (/* @__PURE__ */ new Date()).getTime();
240
+ closeTimerRef.current = window.setTimeout(handleClose, duration2);
241
+ },
242
+ [handleClose]
243
+ );
244
+ React.useEffect(() => {
245
+ const viewport = context.viewport;
246
+ if (viewport) {
247
+ const handleResume = () => {
248
+ startTimer(closeTimerRemainingTimeRef.current);
249
+ };
250
+ const handlePause = () => {
251
+ const elapsedTime = (/* @__PURE__ */ new Date()).getTime() - closeTimerStartTimeRef.current;
252
+ closeTimerRemainingTimeRef.current = closeTimerRemainingTimeRef.current - elapsedTime;
253
+ window.clearTimeout(closeTimerRef.current);
254
+ };
255
+ viewport.addEventListener(VIEWPORT_PAUSE, handlePause);
256
+ viewport.addEventListener(VIEWPORT_RESUME, handleResume);
257
+ return () => {
258
+ viewport.removeEventListener(VIEWPORT_PAUSE, handlePause);
259
+ viewport.removeEventListener(VIEWPORT_RESUME, handleResume);
260
+ };
261
+ }
262
+ }, [context.viewport, duration, startTimer]);
263
+ React.useEffect(() => {
264
+ if (open && !context.isClosePausedRef.current)
265
+ startTimer(duration);
266
+ }, [open, duration, context.isClosePausedRef, startTimer]);
267
+ React.useEffect(() => {
268
+ onToastAdd();
269
+ return () => onToastRemove();
270
+ }, [onToastAdd, onToastRemove]);
271
+ if (!context.viewport)
272
+ return null;
273
+ return <>
274
+ <ToastAnnounce
275
+ __scopeToast={__scopeToast}
276
+ role="status"
277
+ aria-live={type === "foreground" ? "assertive" : "polite"}
278
+ aria-atomic
279
+ >{props.children}</ToastAnnounce>
280
+ <ToastInteractiveProvider
281
+ scope={__scopeToast}
282
+ isInteractive
283
+ onClose={handleClose}
284
+ >{ReactDOM.createPortal(
285
+ <div />,
286
+ // <Collection.ItemSlot scope={__scopeToast}>
287
+ // <DismissableLayer.Root
288
+ // asChild
289
+ // onEscapeKeyDown={composeEventHandlers(onEscapeKeyDown, () => {
290
+ // if (!context.isFocusedToastEscapeKeyDownRef.current) handleClose()
291
+ // context.isFocusedToastEscapeKeyDownRef.current = false
292
+ // })}
293
+ // >
294
+ // <Primitive.li
295
+ // // Ensure toasts are announced as status list or status when focused
296
+ // role="status"
297
+ // aria-live="off"
298
+ // aria-atomic
299
+ // tabIndex={0}
300
+ // data-state={open ? 'open' : 'closed'}
301
+ // data-swipe-direction={context.swipeDirection}
302
+ // {...toastProps}
303
+ // ref={composedRefs}
304
+ // style={{ userSelect: 'none', touchAction: 'none', ...props.style }}
305
+ // onKeyDown={composeEventHandlers(props.onKeyDown, (event) => {
306
+ // if (event.key !== 'Escape') return
307
+ // onEscapeKeyDown?.(event.nativeEvent)
308
+ // if (!event.nativeEvent.defaultPrevented) {
309
+ // context.isFocusedToastEscapeKeyDownRef.current = true
310
+ // handleClose()
311
+ // }
312
+ // })}
313
+ // onPointerDown={composeEventHandlers(props.onPointerDown, (event) => {
314
+ // if (event.button !== 0) return
315
+ // pointerStartRef.current = { x: event.clientX, y: event.clientY }
316
+ // })}
317
+ // onPointerMove={composeEventHandlers(props.onPointerMove, (event) => {
318
+ // if (!pointerStartRef.current) return
319
+ // const x = event.clientX - pointerStartRef.current.x
320
+ // const y = event.clientY - pointerStartRef.current.y
321
+ // const hasSwipeMoveStarted = Boolean(swipeDeltaRef.current)
322
+ // const isHorizontalSwipe = ['left', 'right'].includes(context.swipeDirection)
323
+ // const clamp = ['left', 'up'].includes(context.swipeDirection)
324
+ // ? Math.min
325
+ // : Math.max
326
+ // const clampedX = isHorizontalSwipe ? clamp(0, x) : 0
327
+ // const clampedY = !isHorizontalSwipe ? clamp(0, y) : 0
328
+ // const moveStartBuffer = event.pointerType === 'touch' ? 10 : 2
329
+ // const delta = { x: clampedX, y: clampedY }
330
+ // const eventDetail = { originalEvent: event, delta }
331
+ // if (hasSwipeMoveStarted) {
332
+ // swipeDeltaRef.current = delta
333
+ // handleAndDispatchCustomEvent(TOAST_SWIPE_MOVE, onSwipeMove, eventDetail, {
334
+ // discrete: false,
335
+ // })
336
+ // } else if (isDeltaInDirection(delta, context.swipeDirection, moveStartBuffer)) {
337
+ // swipeDeltaRef.current = delta
338
+ // handleAndDispatchCustomEvent(TOAST_SWIPE_START, onSwipeStart, eventDetail, {
339
+ // discrete: false,
340
+ // })
341
+ // ;(event.target as HTMLElement).setPointerCapture(event.pointerId)
342
+ // } else if (Math.abs(x) > moveStartBuffer || Math.abs(y) > moveStartBuffer) {
343
+ // // User is swiping in wrong direction so we disable swipe gesture
344
+ // // for the current pointer down interaction
345
+ // pointerStartRef.current = null
346
+ // }
347
+ // })}
348
+ // onPointerUp={composeEventHandlers(props.onPointerUp, (event) => {
349
+ // const delta = swipeDeltaRef.current
350
+ // ;(event.target as HTMLElement).releasePointerCapture(event.pointerId)
351
+ // swipeDeltaRef.current = null
352
+ // pointerStartRef.current = null
353
+ // if (delta) {
354
+ // const toast = event.currentTarget
355
+ // const eventDetail = { originalEvent: event, delta }
356
+ // if (isDeltaInDirection(delta, context.swipeDirection, context.swipeThreshold)) {
357
+ // handleAndDispatchCustomEvent(TOAST_SWIPE_END, onSwipeEnd, eventDetail, {
358
+ // discrete: true,
359
+ // })
360
+ // } else {
361
+ // handleAndDispatchCustomEvent(TOAST_SWIPE_CANCEL, onSwipeCancel, eventDetail, {
362
+ // discrete: true,
363
+ // })
364
+ // }
365
+ // // Prevent click event from triggering on items within the toast when
366
+ // // pointer up is part of a swipe gesture
367
+ // toast.addEventListener('click', (event) => event.preventDefault(), {
368
+ // once: true,
369
+ // })
370
+ // }
371
+ // })}
372
+ // />
373
+ // </DismissableLayer.Root>,
374
+ // </Collection.ItemSlot>,
375
+ context.viewport
376
+ )}</ToastInteractiveProvider>
377
+ </>;
378
+ }
379
+ );
380
+ ToastImpl.propTypes = {
381
+ type(props) {
382
+ if (props.type && !["foreground", "background"].includes(props.type)) {
383
+ const error = `Invalid prop \`type\` supplied to \`${TOAST_NAME}\`. Expected \`foreground | background\`.`;
384
+ return new Error(error);
385
+ }
386
+ return null;
387
+ }
388
+ };
389
+ const ToastAnnounce = (props) => {
390
+ const { __scopeToast, children, ...announceProps } = props;
391
+ const context = useToastProviderContext(TOAST_NAME, __scopeToast);
392
+ const [renderAnnounceText, setRenderAnnounceText] = React.useState(false);
393
+ const [isAnnounced, setIsAnnounced] = React.useState(false);
394
+ const [fragment, setFragment] = React.useState();
395
+ const [rootFragmentNode, setRootFragmentNode] = React.useState(null);
396
+ const announceTextContent = React.useMemo(() => {
397
+ return rootFragmentNode ? getAnnounceTextContent(rootFragmentNode) : null;
398
+ }, [rootFragmentNode]);
399
+ useIsomorphicLayoutEffect(() => {
400
+ setFragment(new DocumentFragment());
401
+ }, []);
402
+ useNextFrame(() => setRenderAnnounceText(true));
403
+ React.useEffect(() => {
404
+ const timer = window.setTimeout(() => setIsAnnounced(true), 1e3);
405
+ return () => window.clearTimeout(timer);
406
+ }, []);
407
+ return isAnnounced ? null : <>
408
+ {fragment && // @ts-ignore
409
+ <Portal container={fragment} ref={setRootFragmentNode}>
410
+ {context.label}
411
+ {" "}
412
+ {children}
413
+ </Portal>}
414
+ <Portal asChild><VisuallyHidden {...announceProps}>{renderAnnounceText && announceTextContent}</VisuallyHidden></Portal>
415
+ </>;
416
+ };
417
+ const TITLE_NAME = "ToastTitle";
418
+ const ToastTitle = React.forwardRef(
419
+ (props, forwardedRef) => {
420
+ const { __scopeToast, ...titleProps } = props;
421
+ return <YStack {...titleProps} ref={forwardedRef} />;
422
+ }
423
+ );
424
+ ToastTitle.displayName = TITLE_NAME;
425
+ const DESCRIPTION_NAME = "ToastDescription";
426
+ const ToastDescription = React.forwardRef((props, forwardedRef) => {
427
+ const { __scopeToast, ...descriptionProps } = props;
428
+ return <YStack {...descriptionProps} ref={forwardedRef} />;
429
+ });
430
+ ToastDescription.displayName = DESCRIPTION_NAME;
431
+ const ACTION_NAME = "ToastAction";
432
+ const ToastAction = React.forwardRef(
433
+ (props, forwardedRef) => {
434
+ const { altText, ...actionProps } = props;
435
+ const context = useToastInteractiveContext(ACTION_NAME, props.__scopeToast);
436
+ if (!altText)
437
+ return null;
438
+ return context.isInteractive ? <ToastClose {...actionProps} ref={forwardedRef} /> : <span>{altText}</span>;
439
+ }
440
+ );
441
+ ToastAction.propTypes = {
442
+ altText(props) {
443
+ if (!props.altText) {
444
+ return new Error(`Missing prop \`altText\` expected on \`${ACTION_NAME}\``);
445
+ }
446
+ return null;
447
+ }
448
+ };
449
+ ToastAction.displayName = ACTION_NAME;
450
+ const CLOSE_NAME = "ToastClose";
451
+ const ToastClose = React.forwardRef(
452
+ (props, forwardedRef) => {
453
+ const { __scopeToast, ...closeProps } = props;
454
+ const interactiveContext = useToastInteractiveContext(CLOSE_NAME, __scopeToast);
455
+ return interactiveContext.isInteractive ? <YStack
456
+ tag="button"
457
+ {...closeProps}
458
+ ref={forwardedRef}
459
+ onPress={composeEventHandlers(props.onPress, interactiveContext.onClose)}
460
+ /> : null;
461
+ }
462
+ );
463
+ ToastClose.displayName = CLOSE_NAME;
464
+ function handleAndDispatchCustomEvent(name, handler, detail, { discrete }) {
465
+ const currentTarget = detail.originalEvent.currentTarget;
466
+ const event = new CustomEvent(name, { bubbles: true, cancelable: true, detail });
467
+ if (handler)
468
+ currentTarget.addEventListener(name, handler, { once: true });
469
+ if (discrete) {
470
+ } else {
471
+ currentTarget.dispatchEvent(event);
472
+ }
473
+ }
474
+ const isDeltaInDirection = (delta, direction, threshold = 0) => {
475
+ const deltaX = Math.abs(delta.x);
476
+ const deltaY = Math.abs(delta.y);
477
+ const isDeltaX = deltaX > deltaY;
478
+ if (direction === "left" || direction === "right") {
479
+ return isDeltaX && deltaX > threshold;
480
+ } else {
481
+ return !isDeltaX && deltaY > threshold;
482
+ }
483
+ };
484
+ function useNextFrame(callback = () => {
485
+ }) {
486
+ const fn = useEvent(callback);
487
+ useIsomorphicLayoutEffect(() => {
488
+ let raf1 = 0;
489
+ let raf2 = 0;
490
+ raf1 = window.requestAnimationFrame(
491
+ () => raf2 = window.requestAnimationFrame(fn)
492
+ );
493
+ return () => {
494
+ window.cancelAnimationFrame(raf1);
495
+ window.cancelAnimationFrame(raf2);
496
+ };
497
+ }, [fn]);
498
+ }
499
+ function getAnnounceTextContent(container) {
500
+ const textContent = [];
501
+ const childNodes = Array.from(container.childNodes);
502
+ childNodes.forEach((node) => {
503
+ if (node.nodeType === node.TEXT_NODE && node.textContent)
504
+ textContent.push(node.textContent);
505
+ if (isHTMLElement(node)) {
506
+ const isHidden = node.ariaHidden || node.hidden || node.style.display === "none";
507
+ if (!isHidden)
508
+ textContent.push(...getAnnounceTextContent(node));
509
+ }
510
+ });
511
+ return textContent;
512
+ }
513
+ function isHTMLElement(node) {
514
+ return node.nodeType === node.ELEMENT_NODE;
515
+ }
516
+ function getTabbableCandidates(container) {
517
+ const nodes = [];
518
+ const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
519
+ acceptNode: (node) => {
520
+ const isHiddenInput = node.tagName === "INPUT" && node.type === "hidden";
521
+ if (node.disabled || node.hidden || isHiddenInput)
522
+ return NodeFilter.FILTER_SKIP;
523
+ return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
524
+ }
525
+ });
526
+ while (walker.nextNode())
527
+ nodes.push(walker.currentNode);
528
+ return nodes;
529
+ }
530
+ function focusFirst(candidates) {
531
+ const previouslyFocusedElement = document.activeElement;
532
+ return candidates.some((candidate) => {
533
+ if (candidate === previouslyFocusedElement)
534
+ return true;
535
+ candidate.focus();
536
+ return document.activeElement !== previouslyFocusedElement;
537
+ });
538
+ }
539
+ const Provider = ToastProvider;
540
+ const Viewport = ToastViewport;
541
+ const Root = Toast;
542
+ const Title = ToastTitle;
543
+ const Description = ToastDescription;
544
+ const Action = ToastAction;
545
+ const Close = ToastClose;
546
+ export {
547
+ Action,
548
+ Close,
549
+ Description,
550
+ Provider,
551
+ Root,
552
+ Title,
553
+ Toast,
554
+ ToastAction,
555
+ ToastClose,
556
+ ToastDescription,
557
+ ToastProvider,
558
+ ToastTitle,
559
+ ToastViewport,
560
+ Viewport
561
+ };
562
+ //# sourceMappingURL=Toast.mjs.map