@tamagui/toast 2.7.7 → 3.0.0-beta.643.1

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 (303) hide show
  1. package/dist/cjs/ToastComposable.cjs +773 -882
  2. package/dist/cjs/ToastComposable.native.cjs +924 -0
  3. package/dist/cjs/ToastComposable.native.js +854 -966
  4. package/dist/cjs/ToastComposable.native.js.map +1 -1
  5. package/dist/cjs/ToastItemFrame.cjs +48 -119
  6. package/dist/cjs/ToastItemFrame.native.cjs +76 -0
  7. package/dist/cjs/ToastItemFrame.native.js +50 -120
  8. package/dist/cjs/ToastItemFrame.native.js.map +1 -1
  9. package/dist/cjs/ToastState.cjs +281 -290
  10. package/dist/cjs/ToastState.native.cjs +312 -0
  11. package/dist/cjs/ToastState.native.js +280 -290
  12. package/dist/cjs/ToastState.native.js.map +1 -1
  13. package/dist/cjs/createNativeToast.cjs +38 -44
  14. package/dist/cjs/createNativeToast.native.cjs +54 -0
  15. package/dist/cjs/createNativeToast.native.js +36 -40
  16. package/dist/cjs/createNativeToast.native.js.map +1 -1
  17. package/dist/cjs/dispatchNativeToast.cjs +32 -35
  18. package/dist/cjs/dispatchNativeToast.native.cjs +48 -0
  19. package/dist/cjs/dispatchNativeToast.native.js +34 -36
  20. package/dist/cjs/dispatchNativeToast.native.js.map +1 -1
  21. package/dist/cjs/index.cjs +25 -12
  22. package/dist/cjs/index.native.cjs +35 -0
  23. package/dist/cjs/index.native.js +26 -12
  24. package/dist/cjs/index.native.js.map +1 -1
  25. package/dist/cjs/types.cjs +10 -11
  26. package/dist/cjs/types.native.cjs +19 -0
  27. package/dist/cjs/types.native.js +10 -10
  28. package/dist/cjs/types.native.js.map +1 -1
  29. package/dist/cjs/useAnimatedDragGesture.cjs +197 -194
  30. package/dist/cjs/useAnimatedDragGesture.native.cjs +210 -0
  31. package/dist/cjs/useAnimatedDragGesture.native.js +179 -191
  32. package/dist/cjs/useAnimatedDragGesture.native.js.map +1 -1
  33. package/dist/cjs/useReducedMotion.cjs +47 -55
  34. package/dist/cjs/useReducedMotion.native.cjs +74 -0
  35. package/dist/cjs/useReducedMotion.native.js +53 -60
  36. package/dist/cjs/useReducedMotion.native.js.map +1 -1
  37. package/dist/cjs/useToastAnimations.cjs +198 -270
  38. package/dist/cjs/useToastAnimations.native.cjs +229 -0
  39. package/dist/cjs/useToastAnimations.native.js +205 -276
  40. package/dist/cjs/useToastAnimations.native.js.map +1 -1
  41. package/dist/esm/ToastComposable.mjs +752 -854
  42. package/dist/esm/ToastComposable.mjs.map +1 -1
  43. package/dist/esm/ToastComposable.native.js +834 -940
  44. package/dist/esm/ToastComposable.native.js.map +1 -1
  45. package/dist/esm/ToastItemFrame.mjs +31 -99
  46. package/dist/esm/ToastItemFrame.mjs.map +1 -1
  47. package/dist/esm/ToastItemFrame.native.js +34 -102
  48. package/dist/esm/ToastItemFrame.native.js.map +1 -1
  49. package/dist/esm/ToastState.mjs +266 -273
  50. package/dist/esm/ToastState.mjs.map +1 -1
  51. package/dist/esm/ToastState.native.js +265 -274
  52. package/dist/esm/ToastState.native.js.map +1 -1
  53. package/dist/esm/createNativeToast.mjs +22 -26
  54. package/dist/esm/createNativeToast.mjs.map +1 -1
  55. package/dist/esm/createNativeToast.native.js +21 -23
  56. package/dist/esm/createNativeToast.native.js.map +1 -1
  57. package/dist/esm/dispatchNativeToast.mjs +19 -17
  58. package/dist/esm/dispatchNativeToast.mjs.map +1 -1
  59. package/dist/esm/dispatchNativeToast.native.js +21 -19
  60. package/dist/esm/dispatchNativeToast.native.js.map +1 -1
  61. package/dist/esm/index.js +5 -2
  62. package/dist/esm/index.mjs +5 -2
  63. package/dist/esm/index.native.js +5 -2
  64. package/dist/esm/types.mjs +0 -2
  65. package/dist/esm/types.native.js +0 -2
  66. package/dist/esm/useAnimatedDragGesture.mjs +181 -168
  67. package/dist/esm/useAnimatedDragGesture.mjs.map +1 -1
  68. package/dist/esm/useAnimatedDragGesture.native.js +163 -166
  69. package/dist/esm/useAnimatedDragGesture.native.js.map +1 -1
  70. package/dist/esm/useReducedMotion.mjs +31 -29
  71. package/dist/esm/useReducedMotion.mjs.map +1 -1
  72. package/dist/esm/useReducedMotion.native.js +37 -35
  73. package/dist/esm/useReducedMotion.native.js.map +1 -1
  74. package/dist/esm/useToastAnimations.mjs +183 -245
  75. package/dist/esm/useToastAnimations.mjs.map +1 -1
  76. package/dist/esm/useToastAnimations.native.js +190 -252
  77. package/dist/esm/useToastAnimations.native.js.map +1 -1
  78. package/dist/jsx/ToastComposable.mjs +752 -854
  79. package/dist/jsx/ToastComposable.mjs.map +1 -1
  80. package/dist/jsx/ToastComposable.native.cjs +924 -0
  81. package/dist/jsx/ToastComposable.native.js +854 -966
  82. package/dist/jsx/ToastComposable.native.js.map +1 -1
  83. package/dist/jsx/ToastItemFrame.mjs +31 -99
  84. package/dist/jsx/ToastItemFrame.mjs.map +1 -1
  85. package/dist/jsx/ToastItemFrame.native.cjs +76 -0
  86. package/dist/jsx/ToastItemFrame.native.js +50 -120
  87. package/dist/jsx/ToastItemFrame.native.js.map +1 -1
  88. package/dist/jsx/ToastState.mjs +266 -273
  89. package/dist/jsx/ToastState.mjs.map +1 -1
  90. package/dist/jsx/ToastState.native.cjs +312 -0
  91. package/dist/jsx/ToastState.native.js +280 -290
  92. package/dist/jsx/ToastState.native.js.map +1 -1
  93. package/dist/jsx/createNativeToast.mjs +22 -26
  94. package/dist/jsx/createNativeToast.mjs.map +1 -1
  95. package/dist/jsx/createNativeToast.native.cjs +54 -0
  96. package/dist/jsx/createNativeToast.native.js +36 -40
  97. package/dist/jsx/createNativeToast.native.js.map +1 -1
  98. package/dist/jsx/dispatchNativeToast.mjs +19 -17
  99. package/dist/jsx/dispatchNativeToast.mjs.map +1 -1
  100. package/dist/jsx/dispatchNativeToast.native.cjs +48 -0
  101. package/dist/jsx/dispatchNativeToast.native.js +34 -36
  102. package/dist/jsx/dispatchNativeToast.native.js.map +1 -1
  103. package/dist/jsx/index.js +5 -2
  104. package/dist/jsx/index.mjs +5 -2
  105. package/dist/jsx/index.native.cjs +35 -0
  106. package/dist/jsx/index.native.js +26 -12
  107. package/dist/jsx/index.native.js.map +1 -1
  108. package/dist/jsx/types.mjs +0 -2
  109. package/dist/jsx/types.native.cjs +19 -0
  110. package/dist/jsx/types.native.js +10 -10
  111. package/dist/jsx/types.native.js.map +1 -1
  112. package/dist/jsx/useAnimatedDragGesture.mjs +181 -168
  113. package/dist/jsx/useAnimatedDragGesture.mjs.map +1 -1
  114. package/dist/jsx/useAnimatedDragGesture.native.cjs +210 -0
  115. package/dist/jsx/useAnimatedDragGesture.native.js +179 -191
  116. package/dist/jsx/useAnimatedDragGesture.native.js.map +1 -1
  117. package/dist/jsx/useReducedMotion.mjs +31 -29
  118. package/dist/jsx/useReducedMotion.mjs.map +1 -1
  119. package/dist/jsx/useReducedMotion.native.cjs +74 -0
  120. package/dist/jsx/useReducedMotion.native.js +53 -60
  121. package/dist/jsx/useReducedMotion.native.js.map +1 -1
  122. package/dist/jsx/useToastAnimations.mjs +183 -245
  123. package/dist/jsx/useToastAnimations.mjs.map +1 -1
  124. package/dist/jsx/useToastAnimations.native.cjs +229 -0
  125. package/dist/jsx/useToastAnimations.native.js +205 -276
  126. package/dist/jsx/useToastAnimations.native.js.map +1 -1
  127. package/package.json +20 -37
  128. package/src/ToastComposable.tsx +55 -97
  129. package/src/ToastItemFrame.tsx +22 -81
  130. package/src/ToastState.ts +1 -0
  131. package/src/index.ts +34 -2
  132. package/src/types.ts +11 -0
  133. package/src/useAnimatedDragGesture.native.ts +1 -1
  134. package/src/useAnimatedDragGesture.ts +1 -1
  135. package/src/useToastAnimations.ts +20 -36
  136. package/types/ToastComposable.d.ts +124 -47
  137. package/types/ToastComposable.d.ts.map +1 -1
  138. package/types/ToastItemFrame.d.ts +52 -21
  139. package/types/ToastItemFrame.d.ts.map +1 -1
  140. package/types/ToastState.d.ts +15 -11
  141. package/types/ToastState.d.ts.map +1 -1
  142. package/types/index.d.ts +6 -2
  143. package/types/index.d.ts.map +1 -1
  144. package/types/types.d.ts +1 -0
  145. package/types/types.d.ts.map +1 -1
  146. package/types/useAnimatedDragGesture.d.ts +1 -1
  147. package/types/useAnimatedDragGesture.d.ts.map +1 -1
  148. package/types/useAnimatedDragGesture.native.d.ts +1 -1
  149. package/types/useAnimatedDragGesture.native.d.ts.map +1 -1
  150. package/types/useToastAnimations.d.ts +2 -8
  151. package/types/useToastAnimations.d.ts.map +1 -1
  152. package/dist/cjs/Toast.cjs +0 -178
  153. package/dist/cjs/Toast.native.js +0 -181
  154. package/dist/cjs/Toast.native.js.map +0 -1
  155. package/dist/cjs/ToastAnnounce.cjs +0 -103
  156. package/dist/cjs/ToastAnnounce.native.js +0 -111
  157. package/dist/cjs/ToastAnnounce.native.js.map +0 -1
  158. package/dist/cjs/ToastImperative.cjs +0 -119
  159. package/dist/cjs/ToastImperative.native.js +0 -130
  160. package/dist/cjs/ToastImperative.native.js.map +0 -1
  161. package/dist/cjs/ToastImpl.cjs +0 -354
  162. package/dist/cjs/ToastImpl.native.js +0 -364
  163. package/dist/cjs/ToastImpl.native.js.map +0 -1
  164. package/dist/cjs/ToastPortal.cjs +0 -49
  165. package/dist/cjs/ToastPortal.native.js +0 -52
  166. package/dist/cjs/ToastPortal.native.js.map +0 -1
  167. package/dist/cjs/ToastProvider.cjs +0 -150
  168. package/dist/cjs/ToastProvider.native.js +0 -161
  169. package/dist/cjs/ToastProvider.native.js.map +0 -1
  170. package/dist/cjs/ToastViewport.cjs +0 -319
  171. package/dist/cjs/ToastViewport.native.js +0 -343
  172. package/dist/cjs/ToastViewport.native.js.map +0 -1
  173. package/dist/cjs/Toaster.cjs +0 -87
  174. package/dist/cjs/Toaster.native.js +0 -91
  175. package/dist/cjs/Toaster.native.js.map +0 -1
  176. package/dist/cjs/constants.cjs +0 -30
  177. package/dist/cjs/constants.native.js +0 -33
  178. package/dist/cjs/constants.native.js.map +0 -1
  179. package/dist/cjs/v2.cjs +0 -36
  180. package/dist/cjs/v2.native.js +0 -39
  181. package/dist/cjs/v2.native.js.map +0 -1
  182. package/dist/esm/Toast.mjs +0 -137
  183. package/dist/esm/Toast.mjs.map +0 -1
  184. package/dist/esm/Toast.native.js +0 -137
  185. package/dist/esm/Toast.native.js.map +0 -1
  186. package/dist/esm/ToastAnnounce.mjs +0 -66
  187. package/dist/esm/ToastAnnounce.mjs.map +0 -1
  188. package/dist/esm/ToastAnnounce.native.js +0 -71
  189. package/dist/esm/ToastAnnounce.native.js.map +0 -1
  190. package/dist/esm/ToastImperative.mjs +0 -80
  191. package/dist/esm/ToastImperative.mjs.map +0 -1
  192. package/dist/esm/ToastImperative.native.js +0 -88
  193. package/dist/esm/ToastImperative.native.js.map +0 -1
  194. package/dist/esm/ToastImpl.mjs +0 -316
  195. package/dist/esm/ToastImpl.mjs.map +0 -1
  196. package/dist/esm/ToastImpl.native.js +0 -329
  197. package/dist/esm/ToastImpl.native.js.map +0 -1
  198. package/dist/esm/ToastPortal.mjs +0 -24
  199. package/dist/esm/ToastPortal.mjs.map +0 -1
  200. package/dist/esm/ToastPortal.native.js +0 -24
  201. package/dist/esm/ToastPortal.native.js.map +0 -1
  202. package/dist/esm/ToastProvider.mjs +0 -110
  203. package/dist/esm/ToastProvider.mjs.map +0 -1
  204. package/dist/esm/ToastProvider.native.js +0 -118
  205. package/dist/esm/ToastProvider.native.js.map +0 -1
  206. package/dist/esm/ToastViewport.mjs +0 -280
  207. package/dist/esm/ToastViewport.mjs.map +0 -1
  208. package/dist/esm/ToastViewport.native.js +0 -301
  209. package/dist/esm/ToastViewport.native.js.map +0 -1
  210. package/dist/esm/Toaster.mjs +0 -51
  211. package/dist/esm/Toaster.mjs.map +0 -1
  212. package/dist/esm/Toaster.native.js +0 -52
  213. package/dist/esm/Toaster.native.js.map +0 -1
  214. package/dist/esm/constants.mjs +0 -4
  215. package/dist/esm/constants.mjs.map +0 -1
  216. package/dist/esm/constants.native.js +0 -4
  217. package/dist/esm/constants.native.js.map +0 -1
  218. package/dist/esm/index.js.map +0 -1
  219. package/dist/esm/index.mjs.map +0 -1
  220. package/dist/esm/index.native.js.map +0 -1
  221. package/dist/esm/types.mjs.map +0 -1
  222. package/dist/esm/types.native.js.map +0 -1
  223. package/dist/esm/v2.mjs +0 -6
  224. package/dist/esm/v2.mjs.map +0 -1
  225. package/dist/esm/v2.native.js +0 -6
  226. package/dist/esm/v2.native.js.map +0 -1
  227. package/dist/jsx/Toast.mjs +0 -137
  228. package/dist/jsx/Toast.mjs.map +0 -1
  229. package/dist/jsx/Toast.native.js +0 -181
  230. package/dist/jsx/Toast.native.js.map +0 -1
  231. package/dist/jsx/ToastAnnounce.mjs +0 -66
  232. package/dist/jsx/ToastAnnounce.mjs.map +0 -1
  233. package/dist/jsx/ToastAnnounce.native.js +0 -111
  234. package/dist/jsx/ToastAnnounce.native.js.map +0 -1
  235. package/dist/jsx/ToastImperative.mjs +0 -80
  236. package/dist/jsx/ToastImperative.mjs.map +0 -1
  237. package/dist/jsx/ToastImperative.native.js +0 -130
  238. package/dist/jsx/ToastImperative.native.js.map +0 -1
  239. package/dist/jsx/ToastImpl.mjs +0 -316
  240. package/dist/jsx/ToastImpl.mjs.map +0 -1
  241. package/dist/jsx/ToastImpl.native.js +0 -364
  242. package/dist/jsx/ToastImpl.native.js.map +0 -1
  243. package/dist/jsx/ToastPortal.mjs +0 -24
  244. package/dist/jsx/ToastPortal.mjs.map +0 -1
  245. package/dist/jsx/ToastPortal.native.js +0 -52
  246. package/dist/jsx/ToastPortal.native.js.map +0 -1
  247. package/dist/jsx/ToastProvider.mjs +0 -110
  248. package/dist/jsx/ToastProvider.mjs.map +0 -1
  249. package/dist/jsx/ToastProvider.native.js +0 -161
  250. package/dist/jsx/ToastProvider.native.js.map +0 -1
  251. package/dist/jsx/ToastViewport.mjs +0 -280
  252. package/dist/jsx/ToastViewport.mjs.map +0 -1
  253. package/dist/jsx/ToastViewport.native.js +0 -343
  254. package/dist/jsx/ToastViewport.native.js.map +0 -1
  255. package/dist/jsx/Toaster.mjs +0 -51
  256. package/dist/jsx/Toaster.mjs.map +0 -1
  257. package/dist/jsx/Toaster.native.js +0 -91
  258. package/dist/jsx/Toaster.native.js.map +0 -1
  259. package/dist/jsx/constants.mjs +0 -4
  260. package/dist/jsx/constants.mjs.map +0 -1
  261. package/dist/jsx/constants.native.js +0 -33
  262. package/dist/jsx/constants.native.js.map +0 -1
  263. package/dist/jsx/index.js.map +0 -1
  264. package/dist/jsx/index.mjs.map +0 -1
  265. package/dist/jsx/types.mjs.map +0 -1
  266. package/dist/jsx/v2.mjs +0 -6
  267. package/dist/jsx/v2.mjs.map +0 -1
  268. package/dist/jsx/v2.native.js +0 -39
  269. package/dist/jsx/v2.native.js.map +0 -1
  270. package/src/Toast.tsx +0 -219
  271. package/src/ToastAnnounce.tsx +0 -103
  272. package/src/ToastImperative.tsx +0 -192
  273. package/src/ToastImpl.tsx +0 -514
  274. package/src/ToastPortal.tsx +0 -19
  275. package/src/ToastProvider.tsx +0 -204
  276. package/src/ToastViewport.tsx +0 -430
  277. package/src/Toaster.tsx +0 -181
  278. package/src/constants.ts +0 -2
  279. package/src/v2.ts +0 -31
  280. package/types/Toast.d.ts +0 -84
  281. package/types/Toast.d.ts.map +0 -1
  282. package/types/ToastAnnounce.d.ts +0 -18
  283. package/types/ToastAnnounce.d.ts.map +0 -1
  284. package/types/ToastImperative.d.ts +0 -95
  285. package/types/ToastImperative.d.ts.map +0 -1
  286. package/types/ToastImpl.d.ts +0 -109
  287. package/types/ToastImpl.d.ts.map +0 -1
  288. package/types/ToastPortal.d.ts +0 -8
  289. package/types/ToastPortal.d.ts.map +0 -1
  290. package/types/ToastProvider.d.ts +0 -92
  291. package/types/ToastProvider.d.ts.map +0 -1
  292. package/types/ToastViewport.d.ts +0 -75
  293. package/types/ToastViewport.d.ts.map +0 -1
  294. package/types/Toaster.d.ts +0 -112
  295. package/types/Toaster.d.ts.map +0 -1
  296. package/types/constants.d.ts +0 -3
  297. package/types/constants.d.ts.map +0 -1
  298. package/types/v2.d.ts +0 -10
  299. package/types/v2.d.ts.map +0 -1
  300. package/v2/index.cjs +0 -2
  301. package/v2/index.js +0 -2
  302. package/v2/index.native.cjs +0 -2
  303. package/v2/index.native.js +0 -2
@@ -1,7 +1,7 @@
1
+ import { Theme, View, createRefComponent, createStyledContext, createStyledHOC, styled, useConfiguration, useEvent, useThemeName } from "@tamagui/core";
1
2
  import { AnimatePresence } from "@tamagui/animate-presence";
2
3
  import { isWeb } from "@tamagui/constants";
3
4
  import { getGestureHandler } from "@tamagui/native";
4
- import { createStyledContext, styled, Theme, useConfiguration, useEvent, useThemeName, View } from "@tamagui/core";
5
5
  import { withStaticProperties } from "@tamagui/helpers";
6
6
  import { Portal } from "@tamagui/portal";
7
7
  import { XStack, YStack } from "@tamagui/stacks";
@@ -14,6 +14,7 @@ import { useToastAnimations } from "./useToastAnimations.mjs";
14
14
  import { useReducedMotion } from "./useReducedMotion.mjs";
15
15
  import { DefaultCloseIcon, ToastActionFrame, ToastCloseFrame, ToastItemFrame, ToastPositionWrapper } from "./ToastItemFrame.mjs";
16
16
  import { jsx, jsxs } from "react/jsx-runtime";
17
+
17
18
  const VISIBLE_TOASTS_AMOUNT = 4;
18
19
  const VIEWPORT_OFFSET = 16;
19
20
  const TOAST_GAP = 14;
@@ -24,885 +25,782 @@ const DEFAULT_HOTKEY = ["altKey", "KeyT"];
24
25
  const ToastContext = createStyledContext({}, "Toast__");
25
26
  const useToastContextValue = ToastContext.useStyledContext;
26
27
  function hasToastContext(ctx) {
27
- return !!ctx && Array.isArray(ctx.toasts) && typeof ctx.setToastHeight === "function" && typeof ctx.removeToast === "function";
28
+ return !!ctx && Array.isArray(ctx.toasts) && typeof ctx.setToastHeight === "function" && typeof ctx.removeToast === "function";
28
29
  }
29
30
  function useToastContext(consumerName) {
30
- const ctx = useToastContextValue();
31
- if (!hasToastContext(ctx)) {
32
- throw new Error(`\`${consumerName}\` must be used within \`Toast\``);
33
- }
34
- return ctx;
31
+ const ctx = useToastContextValue();
32
+ if (!hasToastContext(ctx)) {
33
+ throw new Error(`\`${consumerName}\` must be used within \`Toast\``);
34
+ }
35
+ return ctx;
35
36
  }
36
37
  const ToastItemContext = React.createContext(null);
37
38
  function useToastItemContext() {
38
- const ctx = React.useContext(ToastItemContext);
39
- if (!ctx) {
40
- throw new Error("useToastItemContext must be used within Toast.Item or Toast.List");
41
- }
42
- return ctx;
39
+ const ctx = React.useContext(ToastItemContext);
40
+ if (!ctx) {
41
+ throw new Error("useToastItemContext must be used within Toast.Item or Toast.List");
42
+ }
43
+ return ctx;
43
44
  }
44
45
  function resolveSwipeDirection(direction, position) {
45
- if (direction !== "auto") return direction;
46
- const [yPosition, xPosition] = position.split("-");
47
- if (!isWeb) {
48
- return yPosition === "top" ? "up" : "down";
49
- }
50
- if (xPosition === "left") return "left";
51
- if (xPosition === "right") return "right";
52
- return "horizontal";
46
+ if (direction !== "auto") return direction;
47
+ const [yPosition, xPosition] = position.split("-");
48
+ if (!isWeb) {
49
+ return yPosition === "top" ? "up" : "down";
50
+ }
51
+ if (xPosition === "left") return "left";
52
+ if (xPosition === "right") return "right";
53
+ return "horizontal";
53
54
  }
54
- const ToastRoot = React.forwardRef(function ToastRoot2(props, _ref) {
55
- const {
56
- children,
57
- position = "bottom-right",
58
- duration = TOAST_LIFETIME,
59
- gap = TOAST_GAP,
60
- visibleToasts = VISIBLE_TOASTS_AMOUNT,
61
- swipeDirection: swipeDirectionProp = "auto",
62
- swipeThreshold = 50,
63
- toastHeight = FIXED_TOAST_HEIGHT,
64
- closeButton = false,
65
- expand = false,
66
- theme: themeProp,
67
- reducedMotion: reducedMotionProp,
68
- native = false,
69
- burntOptions,
70
- notificationOptions,
71
- icons
72
- } = props;
73
- const reducedMotion = useReducedMotion(reducedMotionProp);
74
- const [toasts, setToasts] = React.useState([]);
75
- const [heights, setHeights] = React.useState({});
76
- const [localExpanded, setExpanded] = React.useState(false);
77
- const expanded = expand || localExpanded;
78
- const [interacting, setInteracting] = React.useState(false);
79
- const heightsLockedRef = React.useRef(false);
80
- const prevExpandedRef = React.useRef(expanded);
81
- React.useLayoutEffect(() => {
82
- if (prevExpandedRef.current !== expanded) {
83
- heightsLockedRef.current = true;
84
- prevExpandedRef.current = expanded;
85
- }
86
- const timer = setTimeout(() => {
87
- heightsLockedRef.current = false;
88
- }, 350);
89
- return () => clearTimeout(timer);
90
- }, [expanded]);
91
- const setToastHeight = React.useCallback((toastId, height) => {
92
- if (heightsLockedRef.current) return;
93
- const rounded = Math.round(height);
94
- setHeights(prev => {
95
- const existing = prev[toastId];
96
- if (existing != null && Math.abs(existing - rounded) <= 2) return prev;
97
- return {
98
- ...prev,
99
- [toastId]: rounded
100
- };
101
- });
102
- }, []);
103
- const removeToastHeight = React.useCallback(toastId => {
104
- setHeights(prev => {
105
- if (!(toastId in prev)) return prev;
106
- const next = {
107
- ...prev
108
- };
109
- delete next[toastId];
110
- return next;
111
- });
112
- }, []);
113
- const dismissCooldownRef = React.useRef(false);
114
- const dismissCooldownTimerRef = React.useRef(null);
115
- const triggerDismissCooldown = React.useCallback(() => {
116
- dismissCooldownRef.current = true;
117
- if (dismissCooldownTimerRef.current) {
118
- clearTimeout(dismissCooldownTimerRef.current);
119
- }
120
- dismissCooldownTimerRef.current = setTimeout(() => {
121
- dismissCooldownRef.current = false;
122
- }, 800);
123
- }, []);
124
- const isInDismissCooldown = React.useCallback(() => dismissCooldownRef.current, []);
125
- const burntOptionsRef = React.useRef(burntOptions);
126
- const notificationOptionsRef = React.useRef(notificationOptions);
127
- React.useEffect(() => {
128
- burntOptionsRef.current = burntOptions;
129
- }, [burntOptions]);
130
- React.useEffect(() => {
131
- notificationOptionsRef.current = notificationOptions;
132
- }, [notificationOptions]);
133
- React.useEffect(() => {
134
- return ToastState.subscribe(toast => {
135
- if (toast.dismiss) {
136
- setToasts(toasts2 => toasts2.map(t => t.id === toast.id ? {
137
- ...t,
138
- delete: true
139
- } : t));
140
- return;
141
- }
142
- if (native) {
143
- const handled = dispatchNativeToast(toast, {
144
- duration,
145
- burntOptions: burntOptionsRef.current,
146
- notificationOptions: notificationOptionsRef.current
147
- });
148
- if (handled) return;
149
- }
150
- setToasts(toasts2 => {
151
- const idx = toasts2.findIndex(t => t.id === toast.id);
152
- if (idx !== -1) {
153
- return [...toasts2.slice(0, idx), {
154
- ...toasts2[idx],
155
- ...toast
156
- }, ...toasts2.slice(idx + 1)];
157
- }
158
- return [toast, ...toasts2];
159
- });
160
- });
161
- }, [native, duration]);
162
- const prevToastCountRef = React.useRef(toasts.length);
163
- React.useEffect(() => {
164
- const prevCount = prevToastCountRef.current;
165
- prevToastCountRef.current = toasts.length;
166
- if (toasts.length <= 1 && !dismissCooldownRef.current) {
167
- setExpanded(false);
168
- } else if (toasts.length > prevCount && expanded) {
169
- setExpanded(false);
170
- }
171
- }, [toasts.length, expanded]);
172
- const removeToast = React.useCallback(toastToRemove => {
173
- setToasts(toasts2 => {
174
- if (!toasts2.find(t => t.id === toastToRemove.id)?.delete) {
175
- ToastState.dismiss(toastToRemove.id);
176
- }
177
- return toasts2.filter(({
178
- id
179
- }) => id !== toastToRemove.id);
180
- });
181
- }, []);
182
- const swipeDirection = resolveSwipeDirection(swipeDirectionProp, position);
183
- const currentTheme = useThemeName();
184
- const resolvedTheme = themeProp === "system" || !themeProp ? currentTheme?.includes("dark") ? "dark" : "light" : themeProp;
185
- const contextValue = {
186
- toasts,
187
- heights,
188
- setToastHeight,
189
- removeToastHeight,
190
- expanded,
191
- setExpanded,
192
- interacting,
193
- setInteracting,
194
- triggerDismissCooldown,
195
- isInDismissCooldown,
196
- removeToast,
197
- position,
198
- duration,
199
- gap,
200
- visibleToasts,
201
- swipeDirection,
202
- swipeThreshold,
203
- toastHeight,
204
- closeButton,
205
- reducedMotion,
206
- native,
207
- burntOptions,
208
- notificationOptions,
209
- icons
210
- };
211
- return /* @__PURE__ */jsx(ToastContext.Provider, {
212
- ...contextValue,
213
- children: /* @__PURE__ */jsx(Theme, {
214
- name: resolvedTheme,
215
- children
216
- })
217
- });
55
+ const ToastRoot = createRefComponent(function ToastRoot2(props, _ref) {
56
+ const { children, toasterId, position = "bottom-right", duration = TOAST_LIFETIME, gap = TOAST_GAP, visibleToasts = VISIBLE_TOASTS_AMOUNT, swipeDirection: swipeDirectionProp = "auto", swipeThreshold = 50, toastHeight = FIXED_TOAST_HEIGHT, closeButton = false, expand = false, theme: themeProp, reducedMotion: reducedMotionProp, native = false, burntOptions, notificationOptions, icons } = props;
57
+ const reducedMotion = useReducedMotion(reducedMotionProp);
58
+ const [toasts, setToasts] = React.useState([]);
59
+ const [heights, setHeights] = React.useState({});
60
+ const [localExpanded, setExpanded] = React.useState(false);
61
+ const expanded = expand || localExpanded;
62
+ const [interacting, setInteracting] = React.useState(false);
63
+ const heightsLockedRef = React.useRef(false);
64
+ const prevExpandedRef = React.useRef(expanded);
65
+ React.useLayoutEffect(() => {
66
+ if (prevExpandedRef.current !== expanded) {
67
+ heightsLockedRef.current = true;
68
+ prevExpandedRef.current = expanded;
69
+ }
70
+ const timer = setTimeout(() => {
71
+ heightsLockedRef.current = false;
72
+ }, 350);
73
+ return () => clearTimeout(timer);
74
+ }, [expanded]);
75
+ const setToastHeight = React.useCallback((toastId, height) => {
76
+ if (heightsLockedRef.current) return;
77
+ const rounded = Math.round(height);
78
+ setHeights((prev) => {
79
+ const existing = prev[toastId];
80
+ if (existing != null && Math.abs(existing - rounded) <= 2) return prev;
81
+ return {
82
+ ...prev,
83
+ [toastId]: rounded
84
+ };
85
+ });
86
+ }, []);
87
+ const removeToastHeight = React.useCallback((toastId) => {
88
+ setHeights((prev) => {
89
+ if (!(toastId in prev)) return prev;
90
+ const next = { ...prev };
91
+ delete next[toastId];
92
+ return next;
93
+ });
94
+ }, []);
95
+ const dismissCooldownRef = React.useRef(false);
96
+ const dismissCooldownTimerRef = React.useRef(null);
97
+ const triggerDismissCooldown = React.useCallback(() => {
98
+ dismissCooldownRef.current = true;
99
+ if (dismissCooldownTimerRef.current) {
100
+ clearTimeout(dismissCooldownTimerRef.current);
101
+ }
102
+ dismissCooldownTimerRef.current = setTimeout(() => {
103
+ dismissCooldownRef.current = false;
104
+ }, 800);
105
+ }, []);
106
+ const isInDismissCooldown = React.useCallback(() => dismissCooldownRef.current, []);
107
+ const burntOptionsRef = React.useRef(burntOptions);
108
+ const notificationOptionsRef = React.useRef(notificationOptions);
109
+ React.useEffect(() => {
110
+ burntOptionsRef.current = burntOptions;
111
+ }, [burntOptions]);
112
+ React.useEffect(() => {
113
+ notificationOptionsRef.current = notificationOptions;
114
+ }, [notificationOptions]);
115
+ React.useEffect(() => {
116
+ return ToastState.subscribe((toast) => {
117
+ if (toast.dismiss) {
118
+ setToasts((toasts2) => toasts2.map((t) => t.id === toast.id ? {
119
+ ...t,
120
+ delete: true
121
+ } : t));
122
+ return;
123
+ }
124
+ if (toast.toasterId !== toasterId) {
125
+ return;
126
+ }
127
+ if (native) {
128
+ const handled = dispatchNativeToast(toast, {
129
+ duration,
130
+ burntOptions: burntOptionsRef.current,
131
+ notificationOptions: notificationOptionsRef.current
132
+ });
133
+ if (handled) return;
134
+ }
135
+ setToasts((toasts2) => {
136
+ const idx = toasts2.findIndex((t) => t.id === toast.id);
137
+ if (idx !== -1) {
138
+ return [
139
+ ...toasts2.slice(0, idx),
140
+ {
141
+ ...toasts2[idx],
142
+ ...toast
143
+ },
144
+ ...toasts2.slice(idx + 1)
145
+ ];
146
+ }
147
+ return [toast, ...toasts2];
148
+ });
149
+ });
150
+ }, [
151
+ native,
152
+ duration,
153
+ toasterId
154
+ ]);
155
+ const prevToastCountRef = React.useRef(toasts.length);
156
+ React.useEffect(() => {
157
+ const prevCount = prevToastCountRef.current;
158
+ prevToastCountRef.current = toasts.length;
159
+ if (toasts.length <= 1 && !dismissCooldownRef.current) {
160
+ setExpanded(false);
161
+ } else if (toasts.length > prevCount && expanded) {
162
+ setExpanded(false);
163
+ }
164
+ }, [toasts.length, expanded]);
165
+ const removeToast = React.useCallback((toastToRemove) => {
166
+ setToasts((toasts2) => {
167
+ if (!toasts2.find((t) => t.id === toastToRemove.id)?.delete) {
168
+ ToastState.dismiss(toastToRemove.id);
169
+ }
170
+ return toasts2.filter(({ id }) => id !== toastToRemove.id);
171
+ });
172
+ }, []);
173
+ const swipeDirection = resolveSwipeDirection(swipeDirectionProp, position);
174
+ const currentTheme = useThemeName();
175
+ const resolvedTheme = themeProp === "system" || !themeProp ? currentTheme?.includes("dark") ? "dark" : "light" : themeProp;
176
+ const contextValue = {
177
+ toasts,
178
+ heights,
179
+ setToastHeight,
180
+ removeToastHeight,
181
+ expanded,
182
+ setExpanded,
183
+ interacting,
184
+ setInteracting,
185
+ triggerDismissCooldown,
186
+ isInDismissCooldown,
187
+ removeToast,
188
+ position,
189
+ duration,
190
+ gap,
191
+ visibleToasts,
192
+ swipeDirection,
193
+ swipeThreshold,
194
+ toastHeight,
195
+ closeButton,
196
+ reducedMotion,
197
+ native,
198
+ burntOptions,
199
+ notificationOptions,
200
+ icons
201
+ };
202
+ return /* @__PURE__ */ jsx(ToastContext.Provider, {
203
+ ...contextValue,
204
+ children: /* @__PURE__ */ jsx(Theme, {
205
+ name: resolvedTheme,
206
+ children
207
+ })
208
+ });
218
209
  });
219
210
  const ToastViewportFrame = styled(View, {
220
- name: "ToastViewport",
221
- variants: {
222
- unstyled: {
223
- false: {
224
- position: isWeb ? "fixed" : "absolute",
225
- zIndex: 1e5,
226
- pointerEvents: "box-none",
227
- maxWidth: "100%",
228
- ...(isWeb && {
229
- width: 356
230
- }),
231
- minHeight: 1
232
- }
233
- }
234
- },
235
- defaultVariants: {
236
- unstyled: process.env.TAMAGUI_HEADLESS === "1"
237
- }
211
+ displayName: "ToastViewport",
212
+ position: isWeb ? "fixed" : "absolute",
213
+ zIndex: 1e5,
214
+ pointerEvents: "box-none",
215
+ maxWidth: "100%",
216
+ ...isWeb && { width: 356 },
217
+ minHeight: 1
238
218
  });
239
- const ToastViewport = ToastViewportFrame.styleable(function ToastViewport2(props, ref) {
240
- const {
241
- offset = VIEWPORT_OFFSET,
242
- hotkey = DEFAULT_HOTKEY,
243
- label = "Notifications",
244
- portalToRoot = true,
245
- portalZIndex = Number.MAX_SAFE_INTEGER,
246
- children,
247
- ...rest
248
- } = props;
249
- const ctx = useToastContext("Toast.Viewport");
250
- const listRef = React.useRef(null);
251
- const hoverTimeoutRef = React.useRef(null);
252
- const hoverCooldownRef = React.useRef(false);
253
- const deferredCollapseRef = React.useRef(null);
254
- const mouseInsideRef = React.useRef(false);
255
- const [yPosition, xPosition] = ctx.position.split("-");
256
- const {
257
- insets: safeInsets
258
- } = useConfiguration();
259
- const offsetStyles = React.useMemo(() => {
260
- const styles = {};
261
- const defaultOffset = typeof offset === "number" ? offset : VIEWPORT_OFFSET;
262
- const offsetObj = typeof offset === "object" ? offset : {
263
- top: defaultOffset,
264
- right: defaultOffset,
265
- bottom: defaultOffset,
266
- left: defaultOffset
267
- };
268
- const safeTop = safeInsets?.top ?? 0;
269
- const safeBottom = safeInsets?.bottom ?? 0;
270
- const topOffset = safeTop > 0 ? safeTop : offsetObj.top ?? defaultOffset;
271
- const bottomOffset = safeBottom > 0 ? safeBottom : offsetObj.bottom ?? defaultOffset;
272
- if (yPosition === "top") styles.top = topOffset;else styles.bottom = bottomOffset;
273
- if (isWeb) {
274
- if (xPosition === "left") styles.left = offsetObj.left ?? defaultOffset;else if (xPosition === "right") styles.right = offsetObj.right ?? defaultOffset;else {
275
- styles.left = "50%";
276
- styles.transform = "translateX(-50%)";
277
- }
278
- } else {
279
- styles.left = offsetObj.left ?? defaultOffset;
280
- styles.right = offsetObj.right ?? defaultOffset;
281
- }
282
- return styles;
283
- }, [offset, yPosition, xPosition]);
284
- React.useEffect(() => {
285
- if (!isWeb) return;
286
- const handleKeyDown = event => {
287
- const isHotkeyPressed = hotkey.length > 0 && hotkey.every(key => event[key] || event.code === key);
288
- if (isHotkeyPressed) {
289
- ctx.setExpanded(true);
290
- listRef.current?.focus();
291
- }
292
- };
293
- document.addEventListener("keydown", handleKeyDown);
294
- return () => document.removeEventListener("keydown", handleKeyDown);
295
- }, [hotkey]);
296
- if (ctx.toasts.length === 0) return null;
297
- const hotkeyLabel = hotkey.join("+").replace(/Key/g, "").replace(/Digit/g, "");
298
- const content = /* @__PURE__ */jsx(ToastViewportFrame, {
299
- ref: listRef,
300
- "aria-label": `${label} ${hotkeyLabel}`,
301
- tabIndex: -1,
302
- "aria-live": "polite",
303
- style: offsetStyles,
304
- "data-y-position": yPosition,
305
- "data-x-position": xPosition,
306
- ...(isWeb ? {
307
- onMouseEnter: () => {
308
- mouseInsideRef.current = true;
309
- if (deferredCollapseRef.current) {
310
- clearTimeout(deferredCollapseRef.current);
311
- deferredCollapseRef.current = null;
312
- }
313
- if (ctx.toasts.length > 1 && !ctx.interacting && !hoverCooldownRef.current) {
314
- hoverTimeoutRef.current = setTimeout(() => ctx.setExpanded(true), 50);
315
- }
316
- },
317
- onMouseLeave: () => {
318
- mouseInsideRef.current = false;
319
- if (hoverTimeoutRef.current) {
320
- clearTimeout(hoverTimeoutRef.current);
321
- hoverTimeoutRef.current = null;
322
- }
323
- if (!ctx.interacting && !ctx.isInDismissCooldown()) {
324
- ctx.setExpanded(false);
325
- } else if (ctx.isInDismissCooldown()) {
326
- if (deferredCollapseRef.current) {
327
- clearTimeout(deferredCollapseRef.current);
328
- }
329
- deferredCollapseRef.current = setTimeout(() => {
330
- deferredCollapseRef.current = null;
331
- if (!mouseInsideRef.current) {
332
- ctx.setExpanded(false);
333
- }
334
- }, 1200);
335
- }
336
- },
337
- onPointerDown: () => {
338
- if (hoverTimeoutRef.current) {
339
- clearTimeout(hoverTimeoutRef.current);
340
- hoverTimeoutRef.current = null;
341
- }
342
- ctx.setInteracting(true);
343
- },
344
- onPointerUp: () => ctx.setInteracting(false),
345
- onPointerCancel: () => ctx.setInteracting(false)
346
- } : {
347
- onPress: () => {
348
- if (ctx.toasts.length > 1) {
349
- ctx.setExpanded(prev => !prev);
350
- }
351
- }
352
- }),
353
- ...(isWeb && {
354
- onFocus: event => {
355
- if (!event.currentTarget.contains(event.relatedTarget)) {
356
- if (ctx.toasts.length > 1) {
357
- ctx.setExpanded(true);
358
- }
359
- ctx.setInteracting(true);
360
- }
361
- },
362
- onBlur: event => {
363
- if (!event.currentTarget.contains(event.relatedTarget)) {
364
- ctx.setInteracting(false);
365
- if (!ctx.isInDismissCooldown()) {
366
- ctx.setExpanded(false);
367
- }
368
- }
369
- }
370
- }),
371
- ...rest,
372
- children
373
- });
374
- if (portalToRoot) {
375
- return /* @__PURE__ */jsx(Portal, {
376
- zIndex: portalZIndex,
377
- children: /* @__PURE__ */jsx(ToastContext.Provider, {
378
- ...ctx,
379
- children: content
380
- })
381
- });
382
- }
383
- return content;
219
+ const ToastViewport = createStyledHOC(ToastViewportFrame, function ToastViewport2(props, ref) {
220
+ const { offset = VIEWPORT_OFFSET, hotkey = DEFAULT_HOTKEY, label = "Notifications", portalToRoot = true, portalZIndex = Number.MAX_SAFE_INTEGER, children, ...rest } = props;
221
+ const ctx = useToastContext("Toast.Viewport");
222
+ const listRef = React.useRef(null);
223
+ const hoverTimeoutRef = React.useRef(null);
224
+ const hoverCooldownRef = React.useRef(false);
225
+ const deferredCollapseRef = React.useRef(null);
226
+ const mouseInsideRef = React.useRef(false);
227
+ const [yPosition, xPosition] = ctx.position.split("-");
228
+ const { insets: safeInsets } = useConfiguration();
229
+ const offsetStyles = React.useMemo(() => {
230
+ const styles = {};
231
+ const defaultOffset = typeof offset === "number" ? offset : VIEWPORT_OFFSET;
232
+ const offsetObj = typeof offset === "object" ? offset : {
233
+ top: defaultOffset,
234
+ right: defaultOffset,
235
+ bottom: defaultOffset,
236
+ left: defaultOffset
237
+ };
238
+ const safeTop = safeInsets?.top ?? 0;
239
+ const safeBottom = safeInsets?.bottom ?? 0;
240
+ const topOffset = safeTop > 0 ? safeTop : offsetObj.top ?? defaultOffset;
241
+ const bottomOffset = safeBottom > 0 ? safeBottom : offsetObj.bottom ?? defaultOffset;
242
+ if (yPosition === "top") styles.top = topOffset;
243
+ else styles.bottom = bottomOffset;
244
+ if (isWeb) {
245
+ if (xPosition === "left") styles.left = offsetObj.left ?? defaultOffset;
246
+ else if (xPosition === "right") styles.right = offsetObj.right ?? defaultOffset;
247
+ else {
248
+ styles.left = "50%";
249
+ styles.transform = "translateX(-50%)";
250
+ }
251
+ } else {
252
+ styles.left = offsetObj.left ?? defaultOffset;
253
+ styles.right = offsetObj.right ?? defaultOffset;
254
+ }
255
+ return styles;
256
+ }, [
257
+ offset,
258
+ yPosition,
259
+ xPosition
260
+ ]);
261
+ React.useEffect(() => {
262
+ if (!isWeb) return;
263
+ const handleKeyDown = (event) => {
264
+ const isHotkeyPressed = hotkey.length > 0 && hotkey.every((key) => event[key] || event.code === key);
265
+ if (isHotkeyPressed) {
266
+ ctx.setExpanded(true);
267
+ listRef.current?.focus();
268
+ }
269
+ };
270
+ document.addEventListener("keydown", handleKeyDown);
271
+ return () => document.removeEventListener("keydown", handleKeyDown);
272
+ }, [hotkey]);
273
+ if (ctx.toasts.length === 0) return null;
274
+ const hotkeyLabel = hotkey.join("+").replace(/Key/g, "").replace(/Digit/g, "");
275
+ const content = /* @__PURE__ */ jsx(ToastViewportFrame, {
276
+ ref: listRef,
277
+ "aria-label": `${label} ${hotkeyLabel}`,
278
+ tabIndex: -1,
279
+ "aria-live": "polite",
280
+ style: offsetStyles,
281
+ "data-y-position": yPosition,
282
+ "data-x-position": xPosition,
283
+ ...isWeb ? {
284
+ onMouseEnter: () => {
285
+ mouseInsideRef.current = true;
286
+ if (deferredCollapseRef.current) {
287
+ clearTimeout(deferredCollapseRef.current);
288
+ deferredCollapseRef.current = null;
289
+ }
290
+ if (ctx.toasts.length > 1 && !ctx.interacting && !hoverCooldownRef.current) {
291
+ hoverTimeoutRef.current = setTimeout(() => ctx.setExpanded(true), 50);
292
+ }
293
+ },
294
+ onMouseLeave: () => {
295
+ mouseInsideRef.current = false;
296
+ if (hoverTimeoutRef.current) {
297
+ clearTimeout(hoverTimeoutRef.current);
298
+ hoverTimeoutRef.current = null;
299
+ }
300
+ if (!ctx.interacting && !ctx.isInDismissCooldown()) {
301
+ ctx.setExpanded(false);
302
+ } else if (ctx.isInDismissCooldown()) {
303
+ if (deferredCollapseRef.current) {
304
+ clearTimeout(deferredCollapseRef.current);
305
+ }
306
+ deferredCollapseRef.current = setTimeout(() => {
307
+ deferredCollapseRef.current = null;
308
+ if (!mouseInsideRef.current) {
309
+ ctx.setExpanded(false);
310
+ }
311
+ }, 1200);
312
+ }
313
+ },
314
+ onPointerDown: () => {
315
+ if (hoverTimeoutRef.current) {
316
+ clearTimeout(hoverTimeoutRef.current);
317
+ hoverTimeoutRef.current = null;
318
+ }
319
+ ctx.setInteracting(true);
320
+ },
321
+ onPointerUp: () => ctx.setInteracting(false),
322
+ onPointerCancel: () => ctx.setInteracting(false)
323
+ } : { onPress: () => {
324
+ if (ctx.toasts.length > 1) {
325
+ ctx.setExpanded((prev) => !prev);
326
+ }
327
+ } },
328
+ ...isWeb && {
329
+ onFocus: (event) => {
330
+ if (!event.currentTarget.contains(event.relatedTarget)) {
331
+ if (ctx.toasts.length > 1) {
332
+ ctx.setExpanded(true);
333
+ }
334
+ ctx.setInteracting(true);
335
+ }
336
+ },
337
+ onBlur: (event) => {
338
+ if (!event.currentTarget.contains(event.relatedTarget)) {
339
+ ctx.setInteracting(false);
340
+ if (!ctx.isInDismissCooldown()) {
341
+ ctx.setExpanded(false);
342
+ }
343
+ }
344
+ }
345
+ },
346
+ ...rest,
347
+ children
348
+ });
349
+ if (portalToRoot) {
350
+ return /* @__PURE__ */ jsx(Portal, {
351
+ zIndex: portalZIndex,
352
+ children: /* @__PURE__ */ jsx(ToastContext.Provider, {
353
+ ...ctx,
354
+ children: content
355
+ })
356
+ });
357
+ }
358
+ return content;
384
359
  });
385
- function ToastList({
386
- renderItem
387
- }) {
388
- const ctx = useToastContext("Toast.List");
389
- const maxRender = ctx.toasts.length;
390
- return /* @__PURE__ */jsx(AnimatePresence, {
391
- children: ctx.toasts.slice(0, maxRender).map((toast, index) => {
392
- const handleClose = () => {
393
- if (toast.dismissible === false) return;
394
- toast.onDismiss?.(toast);
395
- ctx.removeToast(toast);
396
- };
397
- const itemContextValue = {
398
- toast,
399
- handleClose
400
- };
401
- if (!renderItem) {
402
- return /* @__PURE__ */jsx(ToastItemContext.Provider, {
403
- value: itemContextValue,
404
- children: /* @__PURE__ */jsx(ToastItemInner, {
405
- toast,
406
- index,
407
- children: /* @__PURE__ */jsx(DefaultToastContent, {
408
- toast
409
- })
410
- })
411
- }, toast.id);
412
- }
413
- return /* @__PURE__ */jsx(ToastItemContext.Provider, {
414
- value: itemContextValue,
415
- children: renderItem({
416
- toast,
417
- index,
418
- handleClose
419
- })
420
- }, toast.id);
421
- })
422
- });
360
+ function ToastList({ renderItem }) {
361
+ const ctx = useToastContext("Toast.List");
362
+ const maxRender = ctx.toasts.length;
363
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: ctx.toasts.slice(0, maxRender).map((toast, index) => {
364
+ const handleClose = () => {
365
+ if (toast.dismissible === false) return;
366
+ toast.onDismiss?.(toast);
367
+ ctx.removeToast(toast);
368
+ };
369
+ const itemContextValue = {
370
+ toast,
371
+ handleClose
372
+ };
373
+ if (!renderItem) {
374
+ return /* @__PURE__ */ jsx(ToastItemContext.Provider, {
375
+ value: itemContextValue,
376
+ children: /* @__PURE__ */ jsx(ToastItemInner, {
377
+ toast,
378
+ index,
379
+ children: /* @__PURE__ */ jsx(DefaultToastContent, { toast })
380
+ })
381
+ }, toast.id);
382
+ }
383
+ return /* @__PURE__ */ jsx(ToastItemContext.Provider, {
384
+ value: itemContextValue,
385
+ children: renderItem({
386
+ toast,
387
+ index,
388
+ handleClose
389
+ })
390
+ }, toast.id);
391
+ }) });
423
392
  }
424
- function DefaultToastContent({
425
- toast
426
- }) {
427
- const ctx = useToastContext("Toast.Item");
428
- const {
429
- handleClose
430
- } = useToastItemContext();
431
- const toastType = toast.type ?? "default";
432
- const dismissible = toast.dismissible !== false;
433
- const title = typeof toast.title === "function" ? toast.title() : toast.title;
434
- const description = typeof toast.description === "function" ? toast.description() : toast.description;
435
- return /* @__PURE__ */jsxs(XStack, {
436
- alignItems: "flex-start",
437
- gap: "$3",
438
- children: [/* @__PURE__ */jsx(ToastIcon, {}), /* @__PURE__ */jsxs(YStack, {
439
- flex: 1,
440
- gap: "$1",
441
- children: [title && /* @__PURE__ */jsx(ToastTitle, {
442
- children: title
443
- }), description && /* @__PURE__ */jsx(ToastDescription, {
444
- children: description
445
- }), (toast.action || toast.cancel) && /* @__PURE__ */jsxs(XStack, {
446
- gap: "$2",
447
- marginTop: "$2",
448
- children: [toast.cancel && /* @__PURE__ */jsx(ToastActionFrame, {
449
- backgroundColor: "transparent",
450
- onPress: e => {
451
- toast.cancel?.onClick?.(e);
452
- handleClose();
453
- },
454
- children: /* @__PURE__ */jsx(SizableText, {
455
- size: "$2",
456
- color: "$color11",
457
- children: toast.cancel.label
458
- })
459
- }), toast.action && /* @__PURE__ */jsx(ToastActionFrame, {
460
- backgroundColor: "$color12",
461
- hoverStyle: {
462
- backgroundColor: "$color11"
463
- },
464
- pressStyle: {
465
- backgroundColor: "$color10"
466
- },
467
- onPress: e => {
468
- toast.action?.onClick?.(e);
469
- if (!e.defaultPrevented) {
470
- handleClose();
471
- }
472
- },
473
- children: /* @__PURE__ */jsx(SizableText, {
474
- size: "$2",
475
- fontWeight: "600",
476
- color: "$background",
477
- children: toast.action.label
478
- })
479
- })]
480
- })]
481
- }), ctx.closeButton && dismissible && /* @__PURE__ */jsx(ToastClose, {})]
482
- });
393
+ function DefaultToastContent({ toast }) {
394
+ const ctx = useToastContext("Toast.Item");
395
+ const { handleClose } = useToastItemContext();
396
+ const toastType = toast.type ?? "default";
397
+ const dismissible = toast.dismissible !== false;
398
+ const title = typeof toast.title === "function" ? toast.title() : toast.title;
399
+ const description = typeof toast.description === "function" ? toast.description() : toast.description;
400
+ return /* @__PURE__ */ jsxs(XStack, {
401
+ alignItems: "flex-start",
402
+ gap: "3",
403
+ children: [
404
+ /* @__PURE__ */ jsx(ToastIcon, {}),
405
+ /* @__PURE__ */ jsxs(YStack, {
406
+ flex: 1,
407
+ gap: "1",
408
+ children: [
409
+ title && /* @__PURE__ */ jsx(ToastTitle, { children: title }),
410
+ description && /* @__PURE__ */ jsx(ToastDescription, { children: description }),
411
+ (toast.action || toast.cancel) && /* @__PURE__ */ jsxs(XStack, {
412
+ gap: "2",
413
+ marginTop: "2",
414
+ children: [toast.cancel && /* @__PURE__ */ jsx(ToastActionFrame, {
415
+ onPress: (e) => {
416
+ toast.cancel?.onClick?.(e);
417
+ handleClose();
418
+ },
419
+ children: /* @__PURE__ */ jsx(SizableText, {
420
+ size: "2",
421
+ children: toast.cancel.label
422
+ })
423
+ }), toast.action && /* @__PURE__ */ jsx(ToastActionFrame, {
424
+ onPress: (e) => {
425
+ toast.action?.onClick?.(e);
426
+ if (!e.defaultPrevented) {
427
+ handleClose();
428
+ }
429
+ },
430
+ children: /* @__PURE__ */ jsx(SizableText, {
431
+ size: "2",
432
+ children: toast.action.label
433
+ })
434
+ })]
435
+ })
436
+ ]
437
+ }),
438
+ ctx.closeButton && dismissible && /* @__PURE__ */ jsx(ToastClose, {})
439
+ ]
440
+ });
483
441
  }
484
- function DragWrapper({
485
- animatedStyle,
486
- gestureHandlers,
487
- gesture,
488
- AnimatedView,
489
- dragRef,
490
- children
491
- }) {
492
- if (isWeb) {
493
- return /* @__PURE__ */jsx("div", {
494
- ref: dragRef,
495
- style: {
496
- flex: 1,
497
- display: "flex",
498
- flexDirection: "column",
499
- userSelect: "none",
500
- WebkitUserSelect: "none",
501
- touchAction: "none",
502
- cursor: "default"
503
- },
504
- ...gestureHandlers,
505
- children
506
- });
507
- }
508
- if (gesture) {
509
- const gh = getGestureHandler();
510
- const GestureDetector = gh.state.GestureDetector;
511
- if (GestureDetector) {
512
- return /* @__PURE__ */jsx(GestureDetector, {
513
- gesture,
514
- children: /* @__PURE__ */jsx(View, {
515
- style: {
516
- flex: 1
517
- },
518
- ...{
519
- collapsable: false
520
- },
521
- children: /* @__PURE__ */jsx(AnimatedView, {
522
- style: [{
523
- flex: 1
524
- }, animatedStyle],
525
- children
526
- })
527
- })
528
- });
529
- }
530
- }
531
- return /* @__PURE__ */jsx(AnimatedView, {
532
- style: [{
533
- flex: 1
534
- }, animatedStyle],
535
- ...gestureHandlers,
536
- children
537
- });
442
+ function DragWrapper({ animatedStyle, gestureHandlers, gesture, AnimatedView, dragRef, children }) {
443
+ if (isWeb) {
444
+ return /* @__PURE__ */ jsx("div", {
445
+ ref: dragRef,
446
+ style: {
447
+ flex: 1,
448
+ display: "flex",
449
+ flexDirection: "column",
450
+ userSelect: "none",
451
+ WebkitUserSelect: "none",
452
+ touchAction: "none",
453
+ cursor: "default"
454
+ },
455
+ ...gestureHandlers,
456
+ children
457
+ });
458
+ }
459
+ if (gesture) {
460
+ const gh = getGestureHandler();
461
+ const GestureDetector = gh.state.GestureDetector;
462
+ if (GestureDetector) {
463
+ return /* @__PURE__ */ jsx(GestureDetector, {
464
+ gesture,
465
+ children: /* @__PURE__ */ jsx(View, {
466
+ style: { flex: 1 },
467
+ ...{ collapsable: false },
468
+ children: /* @__PURE__ */ jsx(AnimatedView, {
469
+ style: [{ flex: 1 }, animatedStyle],
470
+ children
471
+ })
472
+ })
473
+ });
474
+ }
475
+ }
476
+ return /* @__PURE__ */ jsx(AnimatedView, {
477
+ style: [{ flex: 1 }, animatedStyle],
478
+ ...gestureHandlers,
479
+ children
480
+ });
538
481
  }
539
- const ToastItemInner = ToastItemFrame.styleable(function ToastItem(props, ref) {
540
- const {
541
- toast,
542
- index,
543
- children,
544
- ...rest
545
- } = props;
546
- const ctx = useToastContext("Toast.Item");
547
- const [mounted, setMounted] = React.useState(false);
548
- const [removed, setRemoved] = React.useState(false);
549
- const [swipeOut, setSwipeOut] = React.useState(false);
550
- const [offsetBeforeRemove, setOffsetBeforeRemove] = React.useState(0);
551
- const swipeExitYRef = React.useRef(null);
552
- const closeTimerRef = React.useRef(null);
553
- const closeTimerStartRef = React.useRef(0);
554
- const lastPauseTimeRef = React.useRef(0);
555
- const remainingTimeRef = React.useRef(toast.duration ?? ctx.duration);
556
- const isFront = index === 0;
557
- const isVisible = index < ctx.visibleToasts;
558
- const toastType = toast.type ?? "default";
559
- const dismissible = toast.dismissible !== false;
560
- const duration = toast.duration ?? ctx.duration;
561
- const [yPosition] = ctx.position.split("-");
562
- const isTop = yPosition === "top";
563
- const expandedOffset = isWeb ? (() => {
564
- let totalHeight = 0;
565
- let activeCount = 0;
566
- for (let i = 0; i < index; i++) {
567
- const toastId = ctx.toasts[i]?.id;
568
- if (toastId == null) continue;
569
- const h = ctx.heights[toastId];
570
- if (h === 0) continue;
571
- totalHeight += h ?? ctx.toastHeight;
572
- activeCount++;
573
- }
574
- return totalHeight + activeCount * ctx.gap;
575
- })() : index * (ctx.toastHeight + ctx.gap);
576
- const expandedOffsetRef = React.useRef(expandedOffset);
577
- expandedOffsetRef.current = expandedOffset;
578
- const isExpandedRef = React.useRef(ctx.expanded);
579
- isExpandedRef.current = ctx.expanded;
580
- const startTimer = React.useCallback(() => {
581
- if (duration === Number.POSITIVE_INFINITY || toastType === "loading") return;
582
- closeTimerStartRef.current = Date.now();
583
- closeTimerRef.current = setTimeout(() => {
584
- toast.onAutoClose?.(toast);
585
- setRemoved(true);
586
- setTimeout(() => ctx.removeToast(toast), TIME_BEFORE_UNMOUNT);
587
- }, remainingTimeRef.current);
588
- }, [duration, toastType, toast, ctx.removeToast]);
589
- const pauseTimer = useEvent(() => {
590
- if (closeTimerRef.current) {
591
- clearTimeout(closeTimerRef.current);
592
- }
593
- if (lastPauseTimeRef.current < closeTimerStartRef.current) {
594
- const elapsed = Date.now() - closeTimerStartRef.current;
595
- remainingTimeRef.current = Math.max(0, remainingTimeRef.current - elapsed);
596
- }
597
- lastPauseTimeRef.current = Date.now();
598
- });
599
- const resumeTimer = useEvent(() => {
600
- if (ctx.expanded || ctx.interacting) return;
601
- remainingTimeRef.current = duration;
602
- startTimer();
603
- });
604
- React.useEffect(() => {
605
- setMounted(true);
606
- }, []);
607
- React.useEffect(() => {
608
- if (toast.delete) {
609
- setRemoved(true);
610
- if (isExpandedRef.current) {
611
- setOffsetBeforeRemove(expandedOffsetRef.current);
612
- }
613
- setTimeout(() => ctx.removeToast(toast), TIME_BEFORE_UNMOUNT);
614
- }
615
- }, [toast.delete, toast, ctx.removeToast]);
616
- React.useEffect(() => {
617
- if (ctx.expanded || ctx.interacting) {
618
- pauseTimer();
619
- } else {
620
- startTimer();
621
- }
622
- return () => {
623
- if (closeTimerRef.current) clearTimeout(closeTimerRef.current);
624
- };
625
- }, [ctx.expanded, ctx.interacting, startTimer]);
626
- React.useEffect(() => {
627
- remainingTimeRef.current = duration;
628
- }, [duration]);
629
- const {
630
- setDragOffset,
631
- springBack,
632
- animateOut,
633
- animatedStyle,
634
- AnimatedView,
635
- dragRef
636
- } = useToastAnimations({
637
- reducedMotion: ctx.reducedMotion,
638
- swipeAxis: ctx.swipeDirection === "up" || ctx.swipeDirection === "down" || ctx.swipeDirection === "vertical" ? "vertical" : "horizontal"
639
- });
640
- const {
641
- isDragging,
642
- gestureHandlers,
643
- gesture
644
- } = useAnimatedDragGesture({
645
- direction: ctx.swipeDirection,
646
- threshold: ctx.swipeThreshold,
647
- disabled: !dismissible || toastType === "loading",
648
- expanded: ctx.expanded,
649
- onDragStart: pauseTimer,
650
- onDragMove: setDragOffset,
651
- onDismiss: (exitDirection, velocity) => {
652
- ctx.triggerDismissCooldown();
653
- setSwipeOut(true);
654
- toast.onDismiss?.(toast);
655
- swipeExitYRef.current = isExpandedRef.current ? isTop ? expandedOffsetRef.current : -expandedOffsetRef.current : isFront ? 0 : isTop ? ctx.gap * index : -ctx.gap * index;
656
- setRemoved(true);
657
- ctx.removeToast(toast);
658
- animateOut(exitDirection, velocity);
659
- },
660
- onCancel: () => {
661
- springBack(() => {
662
- resumeTimer();
663
- });
664
- }
665
- });
666
- const handleLayout = React.useCallback(event => {
667
- if (!isWeb) return;
668
- if (removed) return;
669
- if (!ctx.expanded && index !== 0) return;
670
- const {
671
- height
672
- } = event.nativeEvent.layout;
673
- ctx.setToastHeight(toast.id, height);
674
- }, [toast.id, ctx.setToastHeight, index, ctx.expanded, removed]);
675
- React.useEffect(() => {
676
- if (!isWeb) return;
677
- return () => {
678
- ctx.removeToastHeight(toast.id);
679
- };
680
- }, [toast.id, ctx.removeToastHeight]);
681
- const handleClose = React.useCallback(() => {
682
- if (!dismissible) return;
683
- ctx.triggerDismissCooldown();
684
- toast.onDismiss?.(toast);
685
- setRemoved(true);
686
- if (isExpandedRef.current) {
687
- setOffsetBeforeRemove(expandedOffsetRef.current);
688
- }
689
- setTimeout(() => ctx.removeToast(toast), TIME_BEFORE_UNMOUNT);
690
- }, [dismissible, toast, ctx.removeToast, ctx.triggerDismissCooldown]);
691
- const itemContextValue = React.useMemo(() => ({
692
- toast,
693
- handleClose
694
- }), [toast, handleClose]);
695
- let frontToastHeight = -1;
696
- if (isWeb) {
697
- for (const t of ctx.toasts) {
698
- const h = ctx.heights[t.id];
699
- if (h != null && h > 0) {
700
- frontToastHeight = h;
701
- break;
702
- }
703
- }
704
- }
705
- const stackScale = !ctx.expanded && !isFront ? 1 - index * 0.05 : 1;
706
- const activeExpandedOffset = removed ? offsetBeforeRemove : expandedOffset;
707
- const stackY = ctx.expanded ? isTop ? activeExpandedOffset : -activeExpandedOffset : isFront ? 0 : isTop ? ctx.gap * index : -ctx.gap * index;
708
- const computedOpacity = removed && !swipeOut ? 0 : index >= ctx.visibleToasts ? 0 : 1;
709
- const computedZIndex = removed ? 0 : ctx.visibleToasts - index + 1;
710
- const computedHeight = isWeb ? ctx.expanded ? ctx.heights[toast.id] || void 0 : !isFront && frontToastHeight > 0 ? frontToastHeight : void 0 : void 0;
711
- const computedPointerEvents = index >= ctx.visibleToasts ? "none" : "auto";
712
- const gapFillerHeight = ctx.expanded ? ctx.gap + 1 : 0;
713
- const dataAttributes = {
714
- "data-mounted": mounted ? "true" : "false",
715
- "data-removed": removed ? "true" : "false",
716
- "data-swipe-out": swipeOut ? "true" : "false",
717
- "data-visible": isVisible ? "true" : "false",
718
- "data-front": isFront ? "true" : "false",
719
- "data-index": String(index),
720
- "data-type": toastType,
721
- "data-expanded": ctx.expanded ? "true" : "false"
722
- };
723
- return /* @__PURE__ */jsx(ToastPositionWrapper, {
724
- ref,
725
- testID: rest.testID,
726
- accessibilityLabel: rest.accessibilityLabel,
727
- ...dataAttributes,
728
- transition: isDragging || ctx.reducedMotion ? void 0 : removed ? "200ms" : "400ms",
729
- animateOnly: isWeb ? ["transform", "opacity", "height"] : ["transform", "opacity"],
730
- y: stackY,
731
- scale: stackScale,
732
- opacity: computedOpacity,
733
- zIndex: computedZIndex,
734
- height: computedHeight,
735
- overflow: "visible",
736
- pointerEvents: computedPointerEvents,
737
- top: isTop ? 0 : void 0,
738
- bottom: isTop ? void 0 : 0,
739
- ...(isWeb && !isFront && {
740
- style: {
741
- transformOrigin: isTop ? "top center" : "bottom center"
742
- }
743
- }),
744
- enterStyle: ctx.reducedMotion ? {
745
- opacity: 0
746
- } : {
747
- opacity: 0,
748
- y: isTop ? -80 : 80
749
- },
750
- exitStyle: ctx.reducedMotion ? {
751
- opacity: 0
752
- } : swipeOut ? {
753
- opacity: 0,
754
- y: swipeExitYRef.current ?? stackY,
755
- scale: stackScale
756
- } : {
757
- opacity: 0,
758
- y: stackY,
759
- scale: stackScale
760
- },
761
- children: /* @__PURE__ */jsx(DragWrapper, {
762
- animatedStyle,
763
- gestureHandlers,
764
- gesture,
765
- AnimatedView,
766
- dragRef,
767
- children: /* @__PURE__ */jsxs(ToastItemFrame, {
768
- role: "status",
769
- "aria-live": "polite",
770
- "aria-atomic": true,
771
- tabIndex: 0,
772
- onLayout: handleLayout,
773
- ...(isWeb && {
774
- onKeyDown: event => {
775
- if (event.key === "Escape" && dismissible) {
776
- const current = event.currentTarget;
777
- const container = current.closest("[aria-label]");
778
- if (container) {
779
- const focusables = container.querySelectorAll('[tabindex="0"]');
780
- const arr = Array.from(focusables);
781
- const idx = arr.indexOf(current);
782
- const next = arr[idx + 1] || arr[idx - 1];
783
- next?.focus();
784
- }
785
- handleClose();
786
- }
787
- }
788
- }),
789
- ...rest,
790
- children: [ctx.expanded && gapFillerHeight > 0 && /* @__PURE__ */jsx(View, {
791
- position: "absolute",
792
- left: 0,
793
- right: 0,
794
- height: gapFillerHeight,
795
- pointerEvents: "auto",
796
- ...(isTop ? {
797
- top: "100%"
798
- } : {
799
- bottom: "100%"
800
- })
801
- }), /* @__PURE__ */jsx(ToastItemContext.Provider, {
802
- value: itemContextValue,
803
- children
804
- })]
805
- })
806
- })
807
- });
482
+ const ToastItemInner = createStyledHOC(ToastItemFrame, function ToastItem(props, ref) {
483
+ const { toast, index, children, ...rest } = props;
484
+ const ctx = useToastContext("Toast.Item");
485
+ const [mounted, setMounted] = React.useState(false);
486
+ const [removed, setRemoved] = React.useState(false);
487
+ const [swipeOut, setSwipeOut] = React.useState(false);
488
+ const [offsetBeforeRemove, setOffsetBeforeRemove] = React.useState(0);
489
+ const swipeExitYRef = React.useRef(null);
490
+ const closeTimerRef = React.useRef(null);
491
+ const closeTimerStartRef = React.useRef(0);
492
+ const lastPauseTimeRef = React.useRef(0);
493
+ const remainingTimeRef = React.useRef(toast.duration ?? ctx.duration);
494
+ const isFront = index === 0;
495
+ const isVisible = index < ctx.visibleToasts;
496
+ const toastType = toast.type ?? "default";
497
+ const dismissible = toast.dismissible !== false;
498
+ const duration = toast.duration ?? ctx.duration;
499
+ const [yPosition] = ctx.position.split("-");
500
+ const isTop = yPosition === "top";
501
+ const expandedOffset = isWeb ? (() => {
502
+ let totalHeight = 0;
503
+ let activeCount = 0;
504
+ for (let i = 0; i < index; i++) {
505
+ const toastId = ctx.toasts[i]?.id;
506
+ if (toastId == null) continue;
507
+ const h = ctx.heights[toastId];
508
+ if (h === 0) continue;
509
+ totalHeight += h ?? ctx.toastHeight;
510
+ activeCount++;
511
+ }
512
+ return totalHeight + activeCount * ctx.gap;
513
+ })() : index * (ctx.toastHeight + ctx.gap);
514
+ const expandedOffsetRef = React.useRef(expandedOffset);
515
+ expandedOffsetRef.current = expandedOffset;
516
+ const isExpandedRef = React.useRef(ctx.expanded);
517
+ isExpandedRef.current = ctx.expanded;
518
+ const startTimer = React.useCallback(() => {
519
+ if (duration === Number.POSITIVE_INFINITY || toastType === "loading") return;
520
+ closeTimerStartRef.current = Date.now();
521
+ closeTimerRef.current = setTimeout(() => {
522
+ toast.onAutoClose?.(toast);
523
+ setRemoved(true);
524
+ setTimeout(() => ctx.removeToast(toast), TIME_BEFORE_UNMOUNT);
525
+ }, remainingTimeRef.current);
526
+ }, [
527
+ duration,
528
+ toastType,
529
+ toast,
530
+ ctx.removeToast
531
+ ]);
532
+ const pauseTimer = useEvent(() => {
533
+ if (closeTimerRef.current) {
534
+ clearTimeout(closeTimerRef.current);
535
+ }
536
+ if (lastPauseTimeRef.current < closeTimerStartRef.current) {
537
+ const elapsed = Date.now() - closeTimerStartRef.current;
538
+ remainingTimeRef.current = Math.max(0, remainingTimeRef.current - elapsed);
539
+ }
540
+ lastPauseTimeRef.current = Date.now();
541
+ });
542
+ const resumeTimer = useEvent(() => {
543
+ if (ctx.expanded || ctx.interacting) return;
544
+ remainingTimeRef.current = duration;
545
+ startTimer();
546
+ });
547
+ React.useEffect(() => {
548
+ setMounted(true);
549
+ }, []);
550
+ React.useEffect(() => {
551
+ if (toast.delete) {
552
+ setRemoved(true);
553
+ if (isExpandedRef.current) {
554
+ setOffsetBeforeRemove(expandedOffsetRef.current);
555
+ }
556
+ setTimeout(() => ctx.removeToast(toast), TIME_BEFORE_UNMOUNT);
557
+ }
558
+ }, [
559
+ toast.delete,
560
+ toast,
561
+ ctx.removeToast
562
+ ]);
563
+ React.useEffect(() => {
564
+ if (ctx.expanded || ctx.interacting) {
565
+ pauseTimer();
566
+ } else {
567
+ startTimer();
568
+ }
569
+ return () => {
570
+ if (closeTimerRef.current) clearTimeout(closeTimerRef.current);
571
+ };
572
+ }, [
573
+ ctx.expanded,
574
+ ctx.interacting,
575
+ startTimer
576
+ ]);
577
+ React.useEffect(() => {
578
+ remainingTimeRef.current = duration;
579
+ }, [duration]);
580
+ const { setDragOffset, springBack, animateOut, animatedStyle, AnimatedView, dragRef } = useToastAnimations({ reducedMotion: ctx.reducedMotion });
581
+ const { isDragging, gestureHandlers, gesture } = useAnimatedDragGesture({
582
+ direction: ctx.swipeDirection,
583
+ threshold: ctx.swipeThreshold,
584
+ disabled: !dismissible || toastType === "loading",
585
+ expanded: ctx.expanded,
586
+ onDragStart: pauseTimer,
587
+ onDragMove: setDragOffset,
588
+ onDismiss: (exitDirection, velocity) => {
589
+ ctx.triggerDismissCooldown();
590
+ setSwipeOut(true);
591
+ toast.onDismiss?.(toast);
592
+ swipeExitYRef.current = isExpandedRef.current ? isTop ? expandedOffsetRef.current : -expandedOffsetRef.current : isFront ? 0 : isTop ? ctx.gap * index : -ctx.gap * index;
593
+ setRemoved(true);
594
+ ctx.removeToast(toast);
595
+ animateOut(exitDirection, velocity);
596
+ },
597
+ onCancel: () => {
598
+ springBack(() => {
599
+ resumeTimer();
600
+ });
601
+ }
602
+ });
603
+ const handleLayout = React.useCallback((event) => {
604
+ if (!isWeb) return;
605
+ if (removed) return;
606
+ if (!ctx.expanded && index !== 0) return;
607
+ const { height } = event.nativeEvent.layout;
608
+ ctx.setToastHeight(toast.id, height);
609
+ }, [
610
+ toast.id,
611
+ ctx.setToastHeight,
612
+ index,
613
+ ctx.expanded,
614
+ removed
615
+ ]);
616
+ React.useEffect(() => {
617
+ if (!isWeb) return;
618
+ return () => {
619
+ ctx.removeToastHeight(toast.id);
620
+ };
621
+ }, [toast.id, ctx.removeToastHeight]);
622
+ const handleClose = React.useCallback(() => {
623
+ if (!dismissible) return;
624
+ ctx.triggerDismissCooldown();
625
+ toast.onDismiss?.(toast);
626
+ setRemoved(true);
627
+ if (isExpandedRef.current) {
628
+ setOffsetBeforeRemove(expandedOffsetRef.current);
629
+ }
630
+ setTimeout(() => ctx.removeToast(toast), TIME_BEFORE_UNMOUNT);
631
+ }, [
632
+ dismissible,
633
+ toast,
634
+ ctx.removeToast,
635
+ ctx.triggerDismissCooldown
636
+ ]);
637
+ const itemContextValue = React.useMemo(() => ({
638
+ toast,
639
+ handleClose
640
+ }), [toast, handleClose]);
641
+ let frontToastHeight = -1;
642
+ if (isWeb) {
643
+ for (const t of ctx.toasts) {
644
+ const h = ctx.heights[t.id];
645
+ if (h != null && h > 0) {
646
+ frontToastHeight = h;
647
+ break;
648
+ }
649
+ }
650
+ }
651
+ const stackScale = !ctx.expanded && !isFront ? 1 - index * .05 : 1;
652
+ const activeExpandedOffset = removed ? offsetBeforeRemove : expandedOffset;
653
+ const stackY = ctx.expanded ? isTop ? activeExpandedOffset : -activeExpandedOffset : isFront ? 0 : isTop ? ctx.gap * index : -ctx.gap * index;
654
+ const computedOpacity = removed && !swipeOut ? 0 : index >= ctx.visibleToasts ? 0 : 1;
655
+ const computedZIndex = removed ? 0 : ctx.visibleToasts - index + 1;
656
+ const computedHeight = isWeb ? ctx.expanded ? ctx.heights[toast.id] || void 0 : !isFront && frontToastHeight > 0 ? frontToastHeight : void 0 : void 0;
657
+ const computedPointerEvents = index >= ctx.visibleToasts ? "none" : "auto";
658
+ const gapFillerHeight = ctx.expanded ? ctx.gap + 1 : 0;
659
+ const dataAttributes = {
660
+ "data-mounted": mounted ? "true" : "false",
661
+ "data-removed": removed ? "true" : "false",
662
+ "data-swipe-out": swipeOut ? "true" : "false",
663
+ "data-visible": isVisible ? "true" : "false",
664
+ "data-front": isFront ? "true" : "false",
665
+ "data-index": String(index),
666
+ "data-type": toastType,
667
+ "data-expanded": ctx.expanded ? "true" : "false"
668
+ };
669
+ return /* @__PURE__ */ jsx(ToastPositionWrapper, {
670
+ ref,
671
+ testID: rest.testID,
672
+ "aria-label": rest["aria-label"],
673
+ ...dataAttributes,
674
+ transition: isDragging || ctx.reducedMotion ? void 0 : removed ? "200ms" : "400ms",
675
+ y: ctx.reducedMotion ? stackY : `${stackY} enter:${isTop ? -80 : 80}px exit:${swipeOut ? swipeExitYRef.current ?? stackY : stackY}px`,
676
+ scale: stackScale,
677
+ opacity: `${computedOpacity} enter:0 exit:0`,
678
+ zIndex: computedZIndex,
679
+ height: computedHeight,
680
+ overflow: "visible",
681
+ pointerEvents: computedPointerEvents,
682
+ top: isTop ? 0 : void 0,
683
+ bottom: isTop ? void 0 : 0,
684
+ ...isWeb && !isFront && { style: { transformOrigin: isTop ? "top center" : "bottom center" } },
685
+ animateOnly: isWeb ? [
686
+ "transform",
687
+ "opacity",
688
+ "height"
689
+ ] : ["transform", "opacity"],
690
+ children: /* @__PURE__ */ jsx(DragWrapper, {
691
+ animatedStyle,
692
+ gestureHandlers,
693
+ gesture,
694
+ AnimatedView,
695
+ dragRef,
696
+ children: /* @__PURE__ */ jsxs(ToastItemFrame, {
697
+ role: "status",
698
+ "aria-live": "polite",
699
+ "aria-atomic": true,
700
+ tabIndex: 0,
701
+ onLayout: handleLayout,
702
+ ...isWeb && { onKeyDown: (event) => {
703
+ if (event.key === "Escape" && dismissible) {
704
+ const current = event.currentTarget;
705
+ const container = current.closest("[aria-label]");
706
+ if (container) {
707
+ const focusables = container.querySelectorAll("[tabindex=\"0\"]");
708
+ const arr = Array.from(focusables);
709
+ const idx = arr.indexOf(current);
710
+ const next = arr[idx + 1] || arr[idx - 1];
711
+ next?.focus();
712
+ }
713
+ handleClose();
714
+ }
715
+ } },
716
+ ...rest,
717
+ children: [ctx.expanded && gapFillerHeight > 0 && /* @__PURE__ */ jsx(View, {
718
+ position: "absolute",
719
+ left: 0,
720
+ right: 0,
721
+ height: gapFillerHeight,
722
+ pointerEvents: "auto",
723
+ ...isTop ? { top: "100%" } : { bottom: "100%" }
724
+ }), /* @__PURE__ */ jsx(ToastItemContext.Provider, {
725
+ value: itemContextValue,
726
+ children
727
+ })]
728
+ })
729
+ })
730
+ });
808
731
  });
809
- const ToastTitle = styled(SizableText, {
810
- name: "ToastTitle",
811
- variants: {
812
- unstyled: {
813
- false: {
814
- color: "$color",
815
- fontWeight: "600",
816
- size: "$4"
817
- }
818
- }
819
- },
820
- defaultVariants: {
821
- unstyled: process.env.TAMAGUI_HEADLESS === "1"
822
- }
732
+ const ToastTitle = styled(SizableText, { displayName: "ToastTitle" });
733
+ const ToastDescription = styled(SizableText, { displayName: "ToastDescription" });
734
+ const ToastClose = createStyledHOC(ToastCloseFrame, function ToastClose2(props, ref) {
735
+ let handleClose;
736
+ try {
737
+ const itemCtx = useToastItemContext();
738
+ handleClose = itemCtx.handleClose;
739
+ } catch {}
740
+ const ctx = useToastContext("Toast.Close");
741
+ return /* @__PURE__ */ jsx(ToastCloseFrame, {
742
+ ref,
743
+ "aria-label": "Close toast",
744
+ onPress: handleClose,
745
+ ...props,
746
+ children: props.children ?? ctx.icons?.close ?? /* @__PURE__ */ jsx(DefaultCloseIcon, {})
747
+ });
823
748
  });
824
- const ToastDescription = styled(SizableText, {
825
- name: "ToastDescription",
826
- variants: {
827
- unstyled: {
828
- false: {
829
- color: "$color11",
830
- size: "$2"
831
- }
832
- }
833
- },
834
- defaultVariants: {
835
- unstyled: process.env.TAMAGUI_HEADLESS === "1"
836
- }
837
- });
838
- const ToastClose = ToastCloseFrame.styleable(function ToastClose2(props, ref) {
839
- let handleClose;
840
- try {
841
- const itemCtx = useToastItemContext();
842
- handleClose = itemCtx.handleClose;
843
- } catch {}
844
- const ctx = useToastContext("Toast.Close");
845
- return /* @__PURE__ */jsx(ToastCloseFrame, {
846
- ref,
847
- "aria-label": "Close toast",
848
- onPress: handleClose,
849
- ...props,
850
- children: props.children ?? ctx.icons?.close ?? /* @__PURE__ */jsx(DefaultCloseIcon, {})
851
- });
852
- });
853
- const ToastAction = ToastActionFrame.styleable(function ToastAction2(props, ref) {
854
- return /* @__PURE__ */jsx(ToastActionFrame, {
855
- ref,
856
- ...props
857
- });
749
+ const ToastAction = createStyledHOC(ToastActionFrame, function ToastAction2(props, ref) {
750
+ return /* @__PURE__ */ jsx(ToastActionFrame, {
751
+ ref,
752
+ ...props
753
+ });
858
754
  });
859
755
  function ToastIcon(props) {
860
- const ctx = useToastContext("Toast.Icon");
861
- let toast;
862
- try {
863
- const itemCtx = useToastItemContext();
864
- toast = itemCtx.toast;
865
- } catch {
866
- return null;
867
- }
868
- if (!toast) return null;
869
- if (toast.icon !== void 0) {
870
- return /* @__PURE__ */jsx(View, {
871
- flexShrink: 0,
872
- marginTop: "$0.5",
873
- children: toast.icon
874
- });
875
- }
876
- const toastType = toast.type ?? "default";
877
- const icon = ctx.icons?.[toastType] ?? null;
878
- if (!icon) return null;
879
- return /* @__PURE__ */jsx(View, {
880
- flexShrink: 0,
881
- marginTop: "$0.5",
882
- children: icon
883
- });
756
+ const ctx = useToastContext("Toast.Icon");
757
+ let toast;
758
+ try {
759
+ const itemCtx = useToastItemContext();
760
+ toast = itemCtx.toast;
761
+ } catch {
762
+ return null;
763
+ }
764
+ if (!toast) return null;
765
+ if (toast.icon !== void 0) {
766
+ return /* @__PURE__ */ jsx(View, {
767
+ flexShrink: 0,
768
+ marginTop: "0-5",
769
+ children: toast.icon
770
+ });
771
+ }
772
+ const toastType = toast.type ?? "default";
773
+ const icon = ctx.icons?.[toastType] ?? null;
774
+ if (!icon) return null;
775
+ return /* @__PURE__ */ jsx(View, {
776
+ flexShrink: 0,
777
+ marginTop: "0-5",
778
+ children: icon
779
+ });
884
780
  }
885
781
  function useToasts() {
886
- const ctx = useToastContext("useToasts");
887
- return {
888
- toasts: ctx.toasts,
889
- expanded: ctx.expanded,
890
- position: ctx.position
891
- };
782
+ const ctx = useToastContext("useToasts");
783
+ return {
784
+ toasts: ctx.toasts,
785
+ expanded: ctx.expanded,
786
+ position: ctx.position,
787
+ closeButton: ctx.closeButton
788
+ };
892
789
  }
893
790
  function useToastItem() {
894
- return useToastItemContext();
791
+ return useToastItemContext();
895
792
  }
896
793
  ToastRoot.displayName = "Toast";
897
794
  const Toast = withStaticProperties(ToastRoot, {
898
- Viewport: ToastViewport,
899
- List: ToastList,
900
- Item: ToastItemInner,
901
- Title: ToastTitle,
902
- Description: ToastDescription,
903
- Close: ToastClose,
904
- Action: ToastAction,
905
- Icon: ToastIcon
795
+ Viewport: ToastViewport,
796
+ List: ToastList,
797
+ Item: ToastItemInner,
798
+ Title: ToastTitle,
799
+ Description: ToastDescription,
800
+ Close: ToastClose,
801
+ Action: ToastAction,
802
+ Icon: ToastIcon
906
803
  });
804
+
907
805
  export { Toast, useToastItem, useToasts };
908
806
  //# sourceMappingURL=ToastComposable.mjs.map