@tamagui/v2-toast 2.0.0-1769464493958

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 (307) hide show
  1. package/dist/cjs/Toast.cjs +170 -0
  2. package/dist/cjs/Toast.js +119 -0
  3. package/dist/cjs/Toast.js.map +6 -0
  4. package/dist/cjs/Toast.native.js +174 -0
  5. package/dist/cjs/Toast.native.js.map +1 -0
  6. package/dist/cjs/ToastAnnounce.cjs +97 -0
  7. package/dist/cjs/ToastAnnounce.js +72 -0
  8. package/dist/cjs/ToastAnnounce.js.map +6 -0
  9. package/dist/cjs/ToastAnnounce.native.js +105 -0
  10. package/dist/cjs/ToastAnnounce.native.js.map +1 -0
  11. package/dist/cjs/ToastImperative.cjs +100 -0
  12. package/dist/cjs/ToastImperative.js +71 -0
  13. package/dist/cjs/ToastImperative.js.map +6 -0
  14. package/dist/cjs/ToastImperative.native.js +122 -0
  15. package/dist/cjs/ToastImperative.native.js.map +1 -0
  16. package/dist/cjs/ToastImpl.cjs +292 -0
  17. package/dist/cjs/ToastImpl.js +227 -0
  18. package/dist/cjs/ToastImpl.js.map +6 -0
  19. package/dist/cjs/ToastImpl.native.js +327 -0
  20. package/dist/cjs/ToastImpl.native.js.map +1 -0
  21. package/dist/cjs/ToastItem.cjs +466 -0
  22. package/dist/cjs/ToastItem.js +356 -0
  23. package/dist/cjs/ToastItem.js.map +6 -0
  24. package/dist/cjs/ToastItem.native.js +547 -0
  25. package/dist/cjs/ToastItem.native.js.map +1 -0
  26. package/dist/cjs/ToastPortal.cjs +44 -0
  27. package/dist/cjs/ToastPortal.js +26 -0
  28. package/dist/cjs/ToastPortal.js.map +6 -0
  29. package/dist/cjs/ToastPortal.native.js +47 -0
  30. package/dist/cjs/ToastPortal.native.js.map +1 -0
  31. package/dist/cjs/ToastProvider.cjs +146 -0
  32. package/dist/cjs/ToastProvider.js +105 -0
  33. package/dist/cjs/ToastProvider.js.map +6 -0
  34. package/dist/cjs/ToastProvider.native.js +159 -0
  35. package/dist/cjs/ToastProvider.native.js.map +1 -0
  36. package/dist/cjs/ToastState.cjs +248 -0
  37. package/dist/cjs/ToastState.js +160 -0
  38. package/dist/cjs/ToastState.js.map +6 -0
  39. package/dist/cjs/ToastState.native.js +257 -0
  40. package/dist/cjs/ToastState.native.js.map +1 -0
  41. package/dist/cjs/ToastViewport.cjs +278 -0
  42. package/dist/cjs/ToastViewport.js +263 -0
  43. package/dist/cjs/ToastViewport.js.map +6 -0
  44. package/dist/cjs/ToastViewport.native.js +316 -0
  45. package/dist/cjs/ToastViewport.native.js.map +1 -0
  46. package/dist/cjs/Toaster.cjs +219 -0
  47. package/dist/cjs/Toaster.js +177 -0
  48. package/dist/cjs/Toaster.js.map +6 -0
  49. package/dist/cjs/Toaster.native.js +279 -0
  50. package/dist/cjs/Toaster.native.js.map +1 -0
  51. package/dist/cjs/constants.cjs +28 -0
  52. package/dist/cjs/constants.js +22 -0
  53. package/dist/cjs/constants.js.map +6 -0
  54. package/dist/cjs/constants.native.js +31 -0
  55. package/dist/cjs/constants.native.js.map +1 -0
  56. package/dist/cjs/createNativeToast.cjs +51 -0
  57. package/dist/cjs/createNativeToast.js +44 -0
  58. package/dist/cjs/createNativeToast.js.map +6 -0
  59. package/dist/cjs/createNativeToast.native.js +47 -0
  60. package/dist/cjs/createNativeToast.native.js.map +1 -0
  61. package/dist/cjs/index.cjs +28 -0
  62. package/dist/cjs/index.js +22 -0
  63. package/dist/cjs/index.js.map +6 -0
  64. package/dist/cjs/index.native.js +31 -0
  65. package/dist/cjs/index.native.js.map +1 -0
  66. package/dist/cjs/types.cjs +16 -0
  67. package/dist/cjs/types.js +14 -0
  68. package/dist/cjs/types.js.map +6 -0
  69. package/dist/cjs/types.native.js +19 -0
  70. package/dist/cjs/types.native.js.map +1 -0
  71. package/dist/cjs/useDragGesture.cjs +129 -0
  72. package/dist/cjs/useDragGesture.js +100 -0
  73. package/dist/cjs/useDragGesture.js.map +6 -0
  74. package/dist/cjs/useDragGesture.native.js +146 -0
  75. package/dist/cjs/useDragGesture.native.js.map +1 -0
  76. package/dist/esm/Toast.js +107 -0
  77. package/dist/esm/Toast.js.map +6 -0
  78. package/dist/esm/Toast.mjs +131 -0
  79. package/dist/esm/Toast.mjs.map +1 -0
  80. package/dist/esm/Toast.native.js +132 -0
  81. package/dist/esm/Toast.native.js.map +1 -0
  82. package/dist/esm/ToastAnnounce.js +55 -0
  83. package/dist/esm/ToastAnnounce.js.map +6 -0
  84. package/dist/esm/ToastAnnounce.mjs +62 -0
  85. package/dist/esm/ToastAnnounce.mjs.map +1 -0
  86. package/dist/esm/ToastAnnounce.native.js +67 -0
  87. package/dist/esm/ToastAnnounce.native.js.map +1 -0
  88. package/dist/esm/ToastImperative.js +50 -0
  89. package/dist/esm/ToastImperative.js.map +6 -0
  90. package/dist/esm/ToastImperative.mjs +63 -0
  91. package/dist/esm/ToastImperative.mjs.map +1 -0
  92. package/dist/esm/ToastImperative.native.js +82 -0
  93. package/dist/esm/ToastImperative.native.js.map +1 -0
  94. package/dist/esm/ToastImpl.js +225 -0
  95. package/dist/esm/ToastImpl.js.map +6 -0
  96. package/dist/esm/ToastImpl.mjs +256 -0
  97. package/dist/esm/ToastImpl.mjs.map +1 -0
  98. package/dist/esm/ToastImpl.native.js +288 -0
  99. package/dist/esm/ToastImpl.native.js.map +1 -0
  100. package/dist/esm/ToastItem.js +339 -0
  101. package/dist/esm/ToastItem.js.map +6 -0
  102. package/dist/esm/ToastItem.mjs +432 -0
  103. package/dist/esm/ToastItem.mjs.map +1 -0
  104. package/dist/esm/ToastItem.native.js +510 -0
  105. package/dist/esm/ToastItem.native.js.map +1 -0
  106. package/dist/esm/ToastPortal.js +13 -0
  107. package/dist/esm/ToastPortal.js.map +6 -0
  108. package/dist/esm/ToastPortal.mjs +21 -0
  109. package/dist/esm/ToastPortal.mjs.map +1 -0
  110. package/dist/esm/ToastPortal.native.js +21 -0
  111. package/dist/esm/ToastPortal.native.js.map +1 -0
  112. package/dist/esm/ToastProvider.js +87 -0
  113. package/dist/esm/ToastProvider.js.map +6 -0
  114. package/dist/esm/ToastProvider.mjs +108 -0
  115. package/dist/esm/ToastProvider.mjs.map +1 -0
  116. package/dist/esm/ToastProvider.native.js +118 -0
  117. package/dist/esm/ToastProvider.native.js.map +1 -0
  118. package/dist/esm/ToastState.js +144 -0
  119. package/dist/esm/ToastState.js.map +6 -0
  120. package/dist/esm/ToastState.mjs +224 -0
  121. package/dist/esm/ToastState.mjs.map +1 -0
  122. package/dist/esm/ToastState.native.js +230 -0
  123. package/dist/esm/ToastState.native.js.map +1 -0
  124. package/dist/esm/ToastViewport.js +250 -0
  125. package/dist/esm/ToastViewport.js.map +6 -0
  126. package/dist/esm/ToastViewport.mjs +241 -0
  127. package/dist/esm/ToastViewport.mjs.map +1 -0
  128. package/dist/esm/ToastViewport.native.js +276 -0
  129. package/dist/esm/ToastViewport.native.js.map +1 -0
  130. package/dist/esm/Toaster.js +160 -0
  131. package/dist/esm/Toaster.js.map +6 -0
  132. package/dist/esm/Toaster.mjs +185 -0
  133. package/dist/esm/Toaster.mjs.map +1 -0
  134. package/dist/esm/Toaster.native.js +242 -0
  135. package/dist/esm/Toaster.native.js.map +1 -0
  136. package/dist/esm/constants.js +6 -0
  137. package/dist/esm/constants.js.map +6 -0
  138. package/dist/esm/constants.mjs +4 -0
  139. package/dist/esm/constants.mjs.map +1 -0
  140. package/dist/esm/constants.native.js +4 -0
  141. package/dist/esm/constants.native.js.map +1 -0
  142. package/dist/esm/createNativeToast.js +28 -0
  143. package/dist/esm/createNativeToast.js.map +6 -0
  144. package/dist/esm/createNativeToast.mjs +27 -0
  145. package/dist/esm/createNativeToast.mjs.map +1 -0
  146. package/dist/esm/createNativeToast.native.js +20 -0
  147. package/dist/esm/createNativeToast.native.js.map +1 -0
  148. package/dist/esm/index.js +7 -0
  149. package/dist/esm/index.js.map +6 -0
  150. package/dist/esm/index.mjs +4 -0
  151. package/dist/esm/index.mjs.map +1 -0
  152. package/dist/esm/index.native.js +4 -0
  153. package/dist/esm/index.native.js.map +1 -0
  154. package/dist/esm/types.js +1 -0
  155. package/dist/esm/types.js.map +6 -0
  156. package/dist/esm/types.mjs +2 -0
  157. package/dist/esm/types.mjs.map +1 -0
  158. package/dist/esm/types.native.js +2 -0
  159. package/dist/esm/types.native.js.map +1 -0
  160. package/dist/esm/useDragGesture.js +76 -0
  161. package/dist/esm/useDragGesture.js.map +6 -0
  162. package/dist/esm/useDragGesture.mjs +95 -0
  163. package/dist/esm/useDragGesture.mjs.map +1 -0
  164. package/dist/esm/useDragGesture.native.js +109 -0
  165. package/dist/esm/useDragGesture.native.js.map +1 -0
  166. package/dist/jsx/Toast.js +107 -0
  167. package/dist/jsx/Toast.js.map +6 -0
  168. package/dist/jsx/Toast.mjs +131 -0
  169. package/dist/jsx/Toast.mjs.map +1 -0
  170. package/dist/jsx/Toast.native.js +174 -0
  171. package/dist/jsx/Toast.native.js.map +1 -0
  172. package/dist/jsx/ToastAnnounce.js +55 -0
  173. package/dist/jsx/ToastAnnounce.js.map +6 -0
  174. package/dist/jsx/ToastAnnounce.mjs +62 -0
  175. package/dist/jsx/ToastAnnounce.mjs.map +1 -0
  176. package/dist/jsx/ToastAnnounce.native.js +105 -0
  177. package/dist/jsx/ToastAnnounce.native.js.map +1 -0
  178. package/dist/jsx/ToastImperative.js +50 -0
  179. package/dist/jsx/ToastImperative.js.map +6 -0
  180. package/dist/jsx/ToastImperative.mjs +63 -0
  181. package/dist/jsx/ToastImperative.mjs.map +1 -0
  182. package/dist/jsx/ToastImperative.native.js +122 -0
  183. package/dist/jsx/ToastImperative.native.js.map +1 -0
  184. package/dist/jsx/ToastImpl.js +225 -0
  185. package/dist/jsx/ToastImpl.js.map +6 -0
  186. package/dist/jsx/ToastImpl.mjs +256 -0
  187. package/dist/jsx/ToastImpl.mjs.map +1 -0
  188. package/dist/jsx/ToastImpl.native.js +327 -0
  189. package/dist/jsx/ToastImpl.native.js.map +1 -0
  190. package/dist/jsx/ToastItem.js +339 -0
  191. package/dist/jsx/ToastItem.js.map +6 -0
  192. package/dist/jsx/ToastItem.mjs +432 -0
  193. package/dist/jsx/ToastItem.mjs.map +1 -0
  194. package/dist/jsx/ToastItem.native.js +547 -0
  195. package/dist/jsx/ToastItem.native.js.map +1 -0
  196. package/dist/jsx/ToastPortal.js +13 -0
  197. package/dist/jsx/ToastPortal.js.map +6 -0
  198. package/dist/jsx/ToastPortal.mjs +21 -0
  199. package/dist/jsx/ToastPortal.mjs.map +1 -0
  200. package/dist/jsx/ToastPortal.native.js +47 -0
  201. package/dist/jsx/ToastPortal.native.js.map +1 -0
  202. package/dist/jsx/ToastProvider.js +87 -0
  203. package/dist/jsx/ToastProvider.js.map +6 -0
  204. package/dist/jsx/ToastProvider.mjs +108 -0
  205. package/dist/jsx/ToastProvider.mjs.map +1 -0
  206. package/dist/jsx/ToastProvider.native.js +159 -0
  207. package/dist/jsx/ToastProvider.native.js.map +1 -0
  208. package/dist/jsx/ToastState.js +144 -0
  209. package/dist/jsx/ToastState.js.map +6 -0
  210. package/dist/jsx/ToastState.mjs +224 -0
  211. package/dist/jsx/ToastState.mjs.map +1 -0
  212. package/dist/jsx/ToastState.native.js +257 -0
  213. package/dist/jsx/ToastState.native.js.map +1 -0
  214. package/dist/jsx/ToastViewport.js +250 -0
  215. package/dist/jsx/ToastViewport.js.map +6 -0
  216. package/dist/jsx/ToastViewport.mjs +241 -0
  217. package/dist/jsx/ToastViewport.mjs.map +1 -0
  218. package/dist/jsx/ToastViewport.native.js +316 -0
  219. package/dist/jsx/ToastViewport.native.js.map +1 -0
  220. package/dist/jsx/Toaster.js +160 -0
  221. package/dist/jsx/Toaster.js.map +6 -0
  222. package/dist/jsx/Toaster.mjs +185 -0
  223. package/dist/jsx/Toaster.mjs.map +1 -0
  224. package/dist/jsx/Toaster.native.js +279 -0
  225. package/dist/jsx/Toaster.native.js.map +1 -0
  226. package/dist/jsx/constants.js +6 -0
  227. package/dist/jsx/constants.js.map +6 -0
  228. package/dist/jsx/constants.mjs +4 -0
  229. package/dist/jsx/constants.mjs.map +1 -0
  230. package/dist/jsx/constants.native.js +31 -0
  231. package/dist/jsx/constants.native.js.map +1 -0
  232. package/dist/jsx/createNativeToast.js +28 -0
  233. package/dist/jsx/createNativeToast.js.map +6 -0
  234. package/dist/jsx/createNativeToast.mjs +27 -0
  235. package/dist/jsx/createNativeToast.mjs.map +1 -0
  236. package/dist/jsx/createNativeToast.native.js +47 -0
  237. package/dist/jsx/createNativeToast.native.js.map +1 -0
  238. package/dist/jsx/index.js +7 -0
  239. package/dist/jsx/index.js.map +6 -0
  240. package/dist/jsx/index.mjs +4 -0
  241. package/dist/jsx/index.mjs.map +1 -0
  242. package/dist/jsx/index.native.js +31 -0
  243. package/dist/jsx/index.native.js.map +1 -0
  244. package/dist/jsx/types.js +1 -0
  245. package/dist/jsx/types.js.map +6 -0
  246. package/dist/jsx/types.mjs +2 -0
  247. package/dist/jsx/types.mjs.map +1 -0
  248. package/dist/jsx/types.native.js +19 -0
  249. package/dist/jsx/types.native.js.map +1 -0
  250. package/dist/jsx/useDragGesture.js +76 -0
  251. package/dist/jsx/useDragGesture.js.map +6 -0
  252. package/dist/jsx/useDragGesture.mjs +95 -0
  253. package/dist/jsx/useDragGesture.mjs.map +1 -0
  254. package/dist/jsx/useDragGesture.native.js +146 -0
  255. package/dist/jsx/useDragGesture.native.js.map +1 -0
  256. package/package.json +77 -0
  257. package/src/Toast.tsx +219 -0
  258. package/src/ToastAnnounce.tsx +102 -0
  259. package/src/ToastImperative.tsx +190 -0
  260. package/src/ToastImpl.tsx +503 -0
  261. package/src/ToastItem.tsx +694 -0
  262. package/src/ToastPortal.tsx +19 -0
  263. package/src/ToastProvider.tsx +197 -0
  264. package/src/ToastState.ts +397 -0
  265. package/src/ToastViewport.tsx +430 -0
  266. package/src/Toaster.tsx +445 -0
  267. package/src/constants.ts +2 -0
  268. package/src/createNativeToast.native.tsx +22 -0
  269. package/src/createNativeToast.tsx +48 -0
  270. package/src/index.ts +17 -0
  271. package/src/types.ts +71 -0
  272. package/src/useDragGesture.native.ts +199 -0
  273. package/src/useDragGesture.ts +218 -0
  274. package/types/Toast.d.ts +84 -0
  275. package/types/Toast.d.ts.map +1 -0
  276. package/types/ToastAnnounce.d.ts +18 -0
  277. package/types/ToastAnnounce.d.ts.map +1 -0
  278. package/types/ToastImperative.d.ts +95 -0
  279. package/types/ToastImperative.d.ts.map +1 -0
  280. package/types/ToastImpl.d.ts +109 -0
  281. package/types/ToastImpl.d.ts.map +1 -0
  282. package/types/ToastItem.d.ts +34 -0
  283. package/types/ToastItem.d.ts.map +1 -0
  284. package/types/ToastPortal.d.ts +8 -0
  285. package/types/ToastPortal.d.ts.map +1 -0
  286. package/types/ToastProvider.d.ts +92 -0
  287. package/types/ToastProvider.d.ts.map +1 -0
  288. package/types/ToastState.d.ts +177 -0
  289. package/types/ToastState.d.ts.map +1 -0
  290. package/types/ToastViewport.d.ts +75 -0
  291. package/types/ToastViewport.d.ts.map +1 -0
  292. package/types/Toaster.d.ts +120 -0
  293. package/types/Toaster.d.ts.map +1 -0
  294. package/types/constants.d.ts +3 -0
  295. package/types/constants.d.ts.map +1 -0
  296. package/types/createNativeToast.d.ts +4 -0
  297. package/types/createNativeToast.d.ts.map +1 -0
  298. package/types/createNativeToast.native.d.ts +4 -0
  299. package/types/createNativeToast.native.d.ts.map +1 -0
  300. package/types/index.d.ts +7 -0
  301. package/types/index.d.ts.map +1 -0
  302. package/types/types.d.ts +61 -0
  303. package/types/types.d.ts.map +1 -0
  304. package/types/useDragGesture.d.ts +32 -0
  305. package/types/useDragGesture.d.ts.map +1 -0
  306. package/types/useDragGesture.native.d.ts +26 -0
  307. package/types/useDragGesture.native.d.ts.map +1 -0
package/src/Toast.tsx ADDED
@@ -0,0 +1,219 @@
1
+ import { AnimatePresence } from '@tamagui/animate-presence'
2
+ import type { GetProps, NativePlatform, NativeValue, TamaguiElement } from '@tamagui/core'
3
+ import { styled, useEvent } from '@tamagui/core'
4
+ import { composeEventHandlers, withStaticProperties } from '@tamagui/helpers'
5
+ import { YStack } from '@tamagui/stacks'
6
+ import { SizableText } from '@tamagui/text'
7
+ import { useControllableState } from '@tamagui/use-controllable-state'
8
+ import * as React from 'react'
9
+ import { ToastAnnounceExclude } from './ToastAnnounce'
10
+ import type { CustomData } from './ToastImperative'
11
+ import { useToast, useToastController, useToastState } from './ToastImperative'
12
+ import type { ToastExtraProps, ToastProps } from './ToastImpl'
13
+ import { ToastImpl, ToastImplFrame, useToastInteractiveContext } from './ToastImpl'
14
+ import type { ScopedProps, ToastProviderProps } from './ToastProvider'
15
+ import { ToastProvider } from './ToastProvider'
16
+ import type { ToastViewportProps } from './ToastViewport'
17
+ import { ToastViewport } from './ToastViewport'
18
+
19
+ /* -------------------------------------------------------------------------------------------------
20
+ * ToastTitle
21
+ * -----------------------------------------------------------------------------------------------*/
22
+
23
+ const TITLE_NAME = 'ToastTitle'
24
+
25
+ const ToastTitle = styled(SizableText, {
26
+ name: TITLE_NAME,
27
+
28
+ variants: {
29
+ unstyled: {
30
+ false: {
31
+ color: '$color',
32
+ size: '$4',
33
+ },
34
+ },
35
+ } as const,
36
+
37
+ defaultVariants: {
38
+ unstyled: process.env.TAMAGUI_HEADLESS === '1',
39
+ },
40
+ })
41
+
42
+ type ToastTitleProps = GetProps<typeof ToastTitle>
43
+
44
+ /* -------------------------------------------------------------------------------------------------
45
+ * ToastDescription
46
+ * -----------------------------------------------------------------------------------------------*/
47
+
48
+ const DESCRIPTION_NAME = 'ToastDescription'
49
+
50
+ const ToastDescription = styled(SizableText, {
51
+ name: DESCRIPTION_NAME,
52
+
53
+ variants: {
54
+ unstyled: {
55
+ false: {
56
+ color: '$color11',
57
+ size: '$1',
58
+ },
59
+ },
60
+ } as const,
61
+
62
+ defaultVariants: {
63
+ unstyled: process.env.TAMAGUI_HEADLESS === '1',
64
+ },
65
+ })
66
+
67
+ type ToastDescriptionProps = GetProps<typeof ToastDescription>
68
+
69
+ /* -------------------------------------------------------------------------------------------------
70
+ * ToastAction
71
+ * -----------------------------------------------------------------------------------------------*/
72
+
73
+ const ACTION_NAME = 'ToastAction'
74
+
75
+ type ToastActionProps = ScopedProps<
76
+ ToastCloseProps & {
77
+ /**
78
+ * A short description for an alternate way to carry out the action. For screen reader users
79
+ * who will not be able to navigate to the button easily/quickly.
80
+ * @example <ToastAction altText="Goto account settings to updgrade">Upgrade</ToastAction>
81
+ * @example <ToastAction altText="Undo (Alt+U)">Undo</ToastAction>
82
+ */
83
+ altText: string
84
+ }
85
+ >
86
+
87
+ const ToastAction = React.forwardRef<TamaguiElement, ScopedProps<ToastActionProps>>(
88
+ function ToastAction(props, forwardedRef) {
89
+ const { altText, ...actionProps } = props
90
+ if (!altText) return null
91
+ return (
92
+ <ToastAnnounceExclude altText={altText} asChild>
93
+ <ToastClose {...actionProps} ref={forwardedRef} />
94
+ </ToastAnnounceExclude>
95
+ )
96
+ }
97
+ )
98
+
99
+ ToastAction.propTypes = {
100
+ altText(props) {
101
+ if (!props.altText) {
102
+ return new Error(`Missing prop \`altText\` expected on \`${ACTION_NAME}\``)
103
+ }
104
+ return null
105
+ },
106
+ }
107
+
108
+ /* -------------------------------------------------------------------------------------------------
109
+ * ToastClose
110
+ * -----------------------------------------------------------------------------------------------*/
111
+
112
+ const CLOSE_NAME = 'ToastClose'
113
+
114
+ const ToastCloseFrame = styled(YStack, {
115
+ name: CLOSE_NAME,
116
+ render: 'button',
117
+ })
118
+
119
+ type ToastCloseFrameProps = GetProps<typeof ToastCloseFrame>
120
+ type ToastCloseProps = ScopedProps<ToastCloseFrameProps & {}>
121
+
122
+ const ToastClose = React.forwardRef<TamaguiElement, ToastCloseProps>(
123
+ function ToastClose(props, forwardedRef) {
124
+ const { scope, ...closeProps } = props
125
+ const interactiveContext = useToastInteractiveContext(scope)
126
+
127
+ return (
128
+ <ToastAnnounceExclude asChild>
129
+ <ToastCloseFrame
130
+ aria-label="Close"
131
+ {...closeProps}
132
+ ref={forwardedRef}
133
+ onPress={composeEventHandlers(props.onPress as any, interactiveContext.onClose)}
134
+ />
135
+ </ToastAnnounceExclude>
136
+ )
137
+ }
138
+ )
139
+
140
+ /* -------------------------------------------------------------------------------------------------
141
+ * Toast
142
+ * -----------------------------------------------------------------------------------------------*/
143
+
144
+ const ToastComponent = ToastImplFrame.styleable<ToastExtraProps>(
145
+ function Toast(props, forwardedRef) {
146
+ const { forceMount, open: openProp, defaultOpen, onOpenChange, ...toastProps } = props
147
+ const [open, setOpen] = useControllableState({
148
+ prop: openProp,
149
+ defaultProp: defaultOpen ?? true,
150
+ onChange: onOpenChange,
151
+ strategy: 'most-recent-wins',
152
+ })
153
+
154
+ const currentToast = useToastState()
155
+ const { hide } = useToastController()
156
+
157
+ const id = React.useId()
158
+ const onPause = useEvent(props.onPause)
159
+ const onResume = useEvent(props.onResume)
160
+ const isHide = currentToast?.hide === true
161
+ const shouldShow = (forceMount || open) && !isHide
162
+
163
+ return (
164
+ <AnimatePresence key={id}>
165
+ {shouldShow ? (
166
+ <ToastImpl
167
+ id={id}
168
+ open={open}
169
+ {...toastProps}
170
+ ref={forwardedRef}
171
+ onClose={() => {
172
+ setOpen(false)
173
+ hide()
174
+ }}
175
+ onPause={onPause}
176
+ onResume={onResume}
177
+ onSwipeEnd={composeEventHandlers(props.onSwipeEnd, (event) => {
178
+ setOpen(false)
179
+ })}
180
+ />
181
+ ) : null}
182
+ </AnimatePresence>
183
+ )
184
+ }
185
+ )
186
+
187
+ const Toast = withStaticProperties(ToastComponent, {
188
+ Title: ToastTitle,
189
+ Description: ToastDescription,
190
+ Action: ToastAction,
191
+ Close: ToastClose,
192
+ })
193
+
194
+ /* ---------------------------------------------------------------------------------------------- */
195
+
196
+ export {
197
+ Toast,
198
+ ToastProvider,
199
+ ToastViewport,
200
+ //
201
+ // imperative
202
+ useToast,
203
+ useToastController,
204
+ useToastState,
205
+ }
206
+ export type {
207
+ // imperative
208
+ CustomData,
209
+ ToastActionProps,
210
+ ToastCloseProps,
211
+ ToastDescriptionProps,
212
+ NativePlatform as ToastNativePlatform,
213
+ // backwards
214
+ NativeValue as ToastNativeValue,
215
+ ToastProps,
216
+ ToastProviderProps,
217
+ ToastTitleProps,
218
+ ToastViewportProps,
219
+ }
@@ -0,0 +1,102 @@
1
+ import { useIsomorphicLayoutEffect } from '@tamagui/constants'
2
+ import type { GetProps, TamaguiElement } from '@tamagui/core'
3
+ import { View, Text, styled, useEvent } from '@tamagui/core'
4
+ import { Portal } from '@tamagui/portal'
5
+ import { startTransition } from '@tamagui/start-transition'
6
+ import { VisuallyHidden } from '@tamagui/visually-hidden'
7
+ import * as React from 'react'
8
+
9
+ import type { ScopedProps } from './ToastProvider'
10
+ import { useToastProviderContext } from './ToastProvider'
11
+
12
+ const ToastAnnounceExcludeFrame = styled(View, {
13
+ name: 'ToastAnnounceExclude',
14
+ })
15
+
16
+ type ToastAnnounceExcludeFrameProps = GetProps<typeof ToastAnnounceExcludeFrame>
17
+
18
+ type ToastAnnounceExcludeExtraProps = {
19
+ altText?: string
20
+ }
21
+
22
+ type ToastAnnounceExcludeProps = ToastAnnounceExcludeFrameProps &
23
+ ToastAnnounceExcludeExtraProps
24
+
25
+ const ToastAnnounceExclude = React.forwardRef<TamaguiElement, ToastAnnounceExcludeProps>(
26
+ (props, forwardedRef) => {
27
+ const { altText, ...announceExcludeProps } = props
28
+
29
+ return (
30
+ <ToastAnnounceExcludeFrame
31
+ data-toast-announce-exclude=""
32
+ data-toast-announce-alt={altText || undefined}
33
+ {...announceExcludeProps}
34
+ ref={forwardedRef}
35
+ />
36
+ )
37
+ }
38
+ )
39
+
40
+ /* -----------------------------------------------------------------------------------------------*/
41
+
42
+ interface ToastAnnounceProps
43
+ extends Omit<GetProps<typeof VisuallyHidden>, 'children'>,
44
+ ScopedProps<{ children: string[] }> {}
45
+
46
+ const ToastAnnounce: React.FC<ToastAnnounceProps> = (
47
+ props: ScopedProps<ToastAnnounceProps>
48
+ ) => {
49
+ const { scope, children, ...announceProps } = props
50
+ const context = useToastProviderContext(scope)
51
+ const [renderAnnounceText, setRenderAnnounceText] = React.useState(false)
52
+ const [isAnnounced, setIsAnnounced] = React.useState(false)
53
+
54
+ // render text content in the next frame to ensure toast is announced in NVDA
55
+ useNextFrame(() => {
56
+ startTransition(() => {
57
+ setRenderAnnounceText(true)
58
+ })
59
+ })
60
+
61
+ // cleanup after announcing
62
+ React.useEffect(() => {
63
+ const timer = setTimeout(() => setIsAnnounced(true), 1000)
64
+ return () => clearTimeout(timer)
65
+ }, [])
66
+
67
+ return isAnnounced ? null : (
68
+ <Portal>
69
+ <VisuallyHidden {...announceProps}>
70
+ {renderAnnounceText && (
71
+ <Text>
72
+ {context.label} {children}
73
+ </Text>
74
+ )}
75
+ </VisuallyHidden>
76
+ </Portal>
77
+ )
78
+ }
79
+
80
+ /* -----------------------------------------------------------------------------------------------*/
81
+
82
+ function useNextFrame(callback = () => {}) {
83
+ const fn = useEvent(callback)
84
+ useIsomorphicLayoutEffect(() => {
85
+ let raf1 = 0
86
+ let raf2 = 0
87
+ raf1 = requestAnimationFrame(() => {
88
+ raf2 = requestAnimationFrame(fn)
89
+ })
90
+ return () => {
91
+ cancelAnimationFrame(raf1)
92
+ cancelAnimationFrame(raf2)
93
+ }
94
+ }, [fn])
95
+ }
96
+
97
+ export {
98
+ ToastAnnounce,
99
+ ToastAnnounceExclude,
100
+ type ToastAnnounceExcludeProps,
101
+ type ToastAnnounceProps,
102
+ }
@@ -0,0 +1,190 @@
1
+ import type { NativePlatform, NativeValue } from '@tamagui/core'
2
+ import { isAndroid, isIos, isWeb } from '@tamagui/core'
3
+ import React from 'react'
4
+ import { createNativeToast } from './createNativeToast'
5
+ import type { CreateNativeToastOptions, NativeToastRef } from './types'
6
+
7
+ export interface ToastImperativeOptions
8
+ extends Omit<CreateNativeToastOptions, 'message'> {
9
+ /**
10
+ * Will show a native toast if is true or is set to the current platform. On iOS, it wraps `SPIndicator` and `SPAlert`. On Android, it wraps `ToastAndroid`. On web, it wraps Notification API. Mobile's native features are handled by `burnt`.
11
+ */
12
+ native?: NativeValue
13
+ }
14
+
15
+ /**
16
+ * Override this in your application to get custom toast fields.
17
+ *
18
+ * e.g.
19
+ * ```ts
20
+ * declare module '@tamagui/toast' {
21
+ * interface CustomData {
22
+ * preset: 'error' | 'success'
23
+ * isUrgent: true
24
+ * }
25
+ * }
26
+ *```
27
+ * You will get auto-completion:
28
+ * ```ts
29
+ * toast.show("Message", { preset: 'error', isUrgent: true })
30
+ * ```
31
+ */
32
+ export interface CustomData {
33
+ [key: string]: any
34
+ }
35
+
36
+ type ShowOptions = CreateNativeToastOptions &
37
+ CustomData & {
38
+ /**
39
+ * Used when need custom data
40
+ */
41
+ customData?: CustomData
42
+ /**
43
+ * Overrides the native option on `ToastImperativeProvider`
44
+ */
45
+ native?: NativeValue
46
+ /**
47
+ * Which viewport to send this toast to. This is only intended to be used with custom toasts and you should wire it up when creating the toast.
48
+ */
49
+ viewportName?: string | 'default'
50
+ }
51
+
52
+ type ToastData = { title: string; id: string } & ShowOptions & {
53
+ isHandledNatively: boolean
54
+ } & CustomData
55
+
56
+ interface ToastContextI {
57
+ nativeToast: NativeToastRef | null
58
+
59
+ /**
60
+ * Call it to show a new toast. If you're using native toasts, you can pass native options using \`burntOptions\` or \`notificationOptions\` depending on the native platform (mobile/web).
61
+ */
62
+ show: (title: string, options?: ShowOptions) => boolean
63
+
64
+ /**
65
+ * Call it to hide the currently displayed toast.
66
+ *
67
+ * _NOTE_: does not work on Android native toasts
68
+ *
69
+ * _NOTE_: hides the last toast on web notification toasts
70
+ */
71
+ hide: () => void
72
+
73
+ options?: ToastImperativeOptions
74
+ }
75
+
76
+ const ToastContext = React.createContext<ToastContextI>({} as any)
77
+ const ToastCurrentContext = React.createContext<ToastData | null>(null)
78
+
79
+ export const useToastController = () => {
80
+ return React.useContext(ToastContext)
81
+ }
82
+
83
+ export const useToastState = () => {
84
+ return React.useContext(ToastCurrentContext)
85
+ }
86
+
87
+ /** @deprecated use `useToastController` and `useToastState` instead to avoid performance pitfalls */
88
+ export const useToast = () => {
89
+ return {
90
+ ...useToastController(),
91
+ currentToast: useToastState(),
92
+ }
93
+ }
94
+
95
+ interface ToastImperativeProviderProps {
96
+ children: React.ReactNode
97
+ /**
98
+ * Used to provide defaults to imperative API. Options can be overwritten when calling `show()`.
99
+ */
100
+ options: ToastImperativeOptions
101
+ }
102
+
103
+ export const ToastImperativeProvider = ({
104
+ children,
105
+ options,
106
+ }: ToastImperativeProviderProps) => {
107
+ const counterRef = React.useRef(0)
108
+
109
+ const [toast, setToast] = React.useState<ToastData | null>(null)
110
+
111
+ const [lastNativeToastRef, setLastNativeToastRef] =
112
+ React.useState<ToastContextI['nativeToast']>(null)
113
+
114
+ const show = React.useCallback<ToastContextI['show']>(
115
+ (title, showOptions) => {
116
+ const native = showOptions?.native ?? options.native
117
+ const isWebNative = Array.isArray(native)
118
+ ? native.includes('web')
119
+ : native === 'web'
120
+ const isMobileNative = Array.isArray(native)
121
+ ? native.includes('mobile')
122
+ : native === 'mobile'
123
+ const isAndroidNative =
124
+ isMobileNative ||
125
+ (Array.isArray(native) ? native.includes('android') : native === 'android')
126
+ const isIosNative =
127
+ isMobileNative ||
128
+ (Array.isArray(native) ? native.includes('ios') : native === 'ios')
129
+
130
+ const isHandledNatively =
131
+ native === true ||
132
+ (isWeb && isWebNative) ||
133
+ (!isWeb && isMobileNative) ||
134
+ (isAndroid && isAndroidNative) ||
135
+ (isIos && isIosNative)
136
+
137
+ if (isHandledNatively) {
138
+ const nativeToastResult = createNativeToast(title, showOptions ?? {})
139
+ if (typeof nativeToastResult === 'object' && nativeToastResult.nativeToastRef) {
140
+ setLastNativeToastRef(nativeToastResult.nativeToastRef)
141
+ }
142
+ }
143
+ counterRef.current++
144
+ setToast({
145
+ ...showOptions?.customData,
146
+ ...showOptions,
147
+ viewportName: showOptions?.viewportName ?? 'default',
148
+ title,
149
+ id: counterRef.current.toString(),
150
+ isHandledNatively,
151
+ })
152
+ return true
153
+ },
154
+ [setToast, JSON.stringify(options.native || null)]
155
+ )
156
+
157
+ const hide = React.useCallback(() => {
158
+ lastNativeToastRef?.close()
159
+ setToast((prev) => {
160
+ if (!prev) return null
161
+ return {
162
+ ...prev,
163
+ hide: true,
164
+ }
165
+ })
166
+
167
+ setTimeout(() => {
168
+ setToast(null)
169
+ }, 100)
170
+ }, [setToast, lastNativeToastRef])
171
+
172
+ const contextValue = React.useMemo(() => {
173
+ return {
174
+ show,
175
+ hide,
176
+ nativeToast: lastNativeToastRef,
177
+ options,
178
+ }
179
+ }, [show, hide, lastNativeToastRef, JSON.stringify(options || null)])
180
+
181
+ return (
182
+ <ToastContext.Provider value={contextValue}>
183
+ <ToastCurrentContext.Provider value={toast}>
184
+ {children}
185
+ </ToastCurrentContext.Provider>
186
+ </ToastContext.Provider>
187
+ )
188
+ }
189
+
190
+ export type { NativePlatform, NativeValue, ToastImperativeProviderProps }