@tamagui/toast 1.7.11 → 1.8.0

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