@oxyhq/bloom 0.50.2 → 0.51.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 (567) hide show
  1. package/NOTICE +89 -0
  2. package/README.md +12 -7
  3. package/lib/commonjs/avatar-group/AvatarGroup.web.js +2 -1
  4. package/lib/commonjs/avatar-group/AvatarGroup.web.js.map +1 -1
  5. package/lib/commonjs/bottom-sheet/index.web.js +2 -1
  6. package/lib/commonjs/bottom-sheet/index.web.js.map +1 -1
  7. package/lib/commonjs/context-menu/index.web.js +3 -2
  8. package/lib/commonjs/context-menu/index.web.js.map +1 -1
  9. package/lib/commonjs/dialog/Dialog.web.js +4 -3
  10. package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
  11. package/lib/commonjs/frosted-icon-button/shared.js +1 -1
  12. package/lib/commonjs/index.js +90 -83
  13. package/lib/commonjs/index.js.map +1 -1
  14. package/lib/commonjs/index.web.js +116 -109
  15. package/lib/commonjs/index.web.js.map +1 -1
  16. package/lib/commonjs/menu/index.web.js +2 -1
  17. package/lib/commonjs/menu/index.web.js.map +1 -1
  18. package/lib/commonjs/popover/index.web.js +3 -2
  19. package/lib/commonjs/popover/index.web.js.map +1 -1
  20. package/lib/commonjs/portal/index.js +4 -1
  21. package/lib/commonjs/portal/index.js.map +1 -1
  22. package/lib/commonjs/progressive-blur/index.js +79 -0
  23. package/lib/commonjs/progressive-blur/index.js.map +1 -0
  24. package/lib/commonjs/progressive-blur/index.web.js +67 -0
  25. package/lib/commonjs/progressive-blur/index.web.js.map +1 -0
  26. package/lib/commonjs/progressive-blur/shared.js +66 -0
  27. package/lib/commonjs/progressive-blur/shared.js.map +1 -0
  28. package/lib/commonjs/progressive-blur/types.js +6 -0
  29. package/lib/commonjs/progressive-blur/types.js.map +1 -0
  30. package/lib/commonjs/select/index.web.js +2 -1
  31. package/lib/commonjs/select/index.web.js.map +1 -1
  32. package/lib/commonjs/styles/web-view-style.js +26 -0
  33. package/lib/commonjs/styles/web-view-style.js.map +1 -0
  34. package/lib/commonjs/tab-bar/TabBarBase.js +415 -0
  35. package/lib/commonjs/tab-bar/TabBarBase.js.map +1 -0
  36. package/lib/commonjs/tab-bar/expo-router/RouterTabBar.js +83 -0
  37. package/lib/commonjs/tab-bar/expo-router/RouterTabBar.js.map +1 -0
  38. package/lib/commonjs/tab-bar/expo-router/fading-tab-screen.js +119 -0
  39. package/lib/commonjs/tab-bar/expo-router/fading-tab-screen.js.map +1 -0
  40. package/lib/commonjs/tab-bar/expo-router/index.js +26 -0
  41. package/lib/commonjs/tab-bar/expo-router/index.js.map +1 -0
  42. package/lib/commonjs/tab-bar/glyph.js +43 -0
  43. package/lib/commonjs/tab-bar/glyph.js.map +1 -0
  44. package/lib/commonjs/tab-bar/glyph.native.js +55 -0
  45. package/lib/commonjs/tab-bar/glyph.native.js.map +1 -0
  46. package/lib/commonjs/tab-bar/index.js +65 -0
  47. package/lib/commonjs/tab-bar/index.js.map +1 -0
  48. package/lib/commonjs/tab-bar/index.web.js +67 -0
  49. package/lib/commonjs/tab-bar/index.web.js.map +1 -0
  50. package/lib/commonjs/tab-bar/minimize-context.js +127 -0
  51. package/lib/commonjs/tab-bar/minimize-context.js.map +1 -0
  52. package/lib/commonjs/tab-bar/shared.js +139 -0
  53. package/lib/commonjs/tab-bar/shared.js.map +1 -0
  54. package/lib/commonjs/tab-bar/surface-solid.js +43 -0
  55. package/lib/commonjs/tab-bar/surface-solid.js.map +1 -0
  56. package/lib/commonjs/tab-bar/surface.js +13 -0
  57. package/lib/commonjs/tab-bar/surface.js.map +1 -0
  58. package/lib/commonjs/tab-bar/surface.native.js +113 -0
  59. package/lib/commonjs/tab-bar/surface.native.js.map +1 -0
  60. package/lib/commonjs/tab-bar/surface.web.js +59 -0
  61. package/lib/commonjs/tab-bar/surface.web.js.map +1 -0
  62. package/lib/commonjs/tab-bar/types.js +6 -0
  63. package/lib/commonjs/tab-bar/types.js.map +1 -0
  64. package/lib/commonjs/toast/Positioner.js +117 -0
  65. package/lib/commonjs/toast/Positioner.js.map +1 -0
  66. package/lib/commonjs/toast/ToastContent.js +301 -0
  67. package/lib/commonjs/toast/ToastContent.js.map +1 -0
  68. package/lib/commonjs/toast/ToastHost.js +69 -0
  69. package/lib/commonjs/toast/ToastHost.js.map +1 -0
  70. package/lib/commonjs/toast/ToastHost.native.js +44 -0
  71. package/lib/commonjs/toast/ToastHost.native.js.map +1 -0
  72. package/lib/commonjs/toast/ToastIcon.js +57 -0
  73. package/lib/commonjs/toast/ToastIcon.js.map +1 -0
  74. package/lib/commonjs/toast/ToastRow.js +411 -0
  75. package/lib/commonjs/toast/ToastRow.js.map +1 -0
  76. package/lib/commonjs/toast/ToastSwipeHandler.js +189 -0
  77. package/lib/commonjs/toast/ToastSwipeHandler.js.map +1 -0
  78. package/lib/commonjs/toast/Toaster.js +205 -0
  79. package/lib/commonjs/toast/Toaster.js.map +1 -0
  80. package/lib/commonjs/toast/animations.js +274 -0
  81. package/lib/commonjs/toast/animations.js.map +1 -0
  82. package/lib/commonjs/toast/constants.js +56 -0
  83. package/lib/commonjs/toast/constants.js.map +1 -0
  84. package/lib/commonjs/toast/context.js +42 -0
  85. package/lib/commonjs/toast/context.js.map +1 -0
  86. package/lib/commonjs/toast/index.js +32 -126
  87. package/lib/commonjs/toast/index.js.map +1 -1
  88. package/lib/commonjs/toast/position-utils.js +115 -0
  89. package/lib/commonjs/toast/position-utils.js.map +1 -0
  90. package/lib/commonjs/toast/positioner-utils.js +141 -0
  91. package/lib/commonjs/toast/positioner-utils.js.map +1 -0
  92. package/lib/commonjs/toast/toast-comparator.js +28 -0
  93. package/lib/commonjs/toast/toast-comparator.js.map +1 -0
  94. package/lib/commonjs/toast/toast-fns.js +90 -0
  95. package/lib/commonjs/toast/toast-fns.js.map +1 -0
  96. package/lib/commonjs/toast/toast-store.js +352 -0
  97. package/lib/commonjs/toast/toast-store.js.map +1 -0
  98. package/lib/commonjs/toast/toast-timers.js +110 -0
  99. package/lib/commonjs/toast/toast-timers.js.map +1 -0
  100. package/lib/commonjs/toast/types.js +42 -0
  101. package/lib/commonjs/toast/types.js.map +1 -1
  102. package/lib/commonjs/toast/use-animated-target.js +57 -0
  103. package/lib/commonjs/toast/use-animated-target.js.map +1 -0
  104. package/lib/commonjs/toast/use-app-state.js +76 -0
  105. package/lib/commonjs/toast/use-app-state.js.map +1 -0
  106. package/lib/commonjs/toast/use-toast-colors.js +114 -0
  107. package/lib/commonjs/toast/use-toast-colors.js.map +1 -0
  108. package/lib/commonjs/toast/use-toast-position.js +40 -0
  109. package/lib/commonjs/toast/use-toast-position.js.map +1 -0
  110. package/lib/commonjs/tooltip/index.web.js +2 -1
  111. package/lib/commonjs/tooltip/index.web.js.map +1 -1
  112. package/lib/commonjs/zoomable-image-gallery/ZoomableImageGallery.js +20 -8
  113. package/lib/commonjs/zoomable-image-gallery/ZoomableImageGallery.js.map +1 -1
  114. package/lib/module/avatar-group/AvatarGroup.web.js +2 -1
  115. package/lib/module/avatar-group/AvatarGroup.web.js.map +1 -1
  116. package/lib/module/bottom-sheet/index.web.js +2 -1
  117. package/lib/module/bottom-sheet/index.web.js.map +1 -1
  118. package/lib/module/context-menu/index.web.js +3 -2
  119. package/lib/module/context-menu/index.web.js.map +1 -1
  120. package/lib/module/dialog/Dialog.web.js +4 -3
  121. package/lib/module/dialog/Dialog.web.js.map +1 -1
  122. package/lib/module/frosted-icon-button/shared.js +1 -1
  123. package/lib/module/index.js +3 -2
  124. package/lib/module/index.js.map +1 -1
  125. package/lib/module/index.web.js +3 -2
  126. package/lib/module/index.web.js.map +1 -1
  127. package/lib/module/menu/index.web.js +2 -1
  128. package/lib/module/menu/index.web.js.map +1 -1
  129. package/lib/module/popover/index.web.js +3 -2
  130. package/lib/module/popover/index.web.js.map +1 -1
  131. package/lib/module/portal/index.js +4 -1
  132. package/lib/module/portal/index.js.map +1 -1
  133. package/lib/module/progressive-blur/index.js +74 -0
  134. package/lib/module/progressive-blur/index.js.map +1 -0
  135. package/lib/module/progressive-blur/index.web.js +62 -0
  136. package/lib/module/progressive-blur/index.web.js.map +1 -0
  137. package/lib/module/progressive-blur/shared.js +60 -0
  138. package/lib/module/progressive-blur/shared.js.map +1 -0
  139. package/lib/module/progressive-blur/types.js +4 -0
  140. package/lib/module/progressive-blur/types.js.map +1 -0
  141. package/lib/module/select/index.web.js +2 -1
  142. package/lib/module/select/index.web.js.map +1 -1
  143. package/lib/module/styles/web-view-style.js +22 -0
  144. package/lib/module/styles/web-view-style.js.map +1 -0
  145. package/lib/module/tab-bar/TabBarBase.js +408 -0
  146. package/lib/module/tab-bar/TabBarBase.js.map +1 -0
  147. package/lib/module/tab-bar/expo-router/RouterTabBar.js +78 -0
  148. package/lib/module/tab-bar/expo-router/RouterTabBar.js.map +1 -0
  149. package/lib/module/tab-bar/expo-router/fading-tab-screen.js +113 -0
  150. package/lib/module/tab-bar/expo-router/fading-tab-screen.js.map +1 -0
  151. package/lib/module/tab-bar/expo-router/index.js +15 -0
  152. package/lib/module/tab-bar/expo-router/index.js.map +1 -0
  153. package/lib/module/tab-bar/glyph.js +38 -0
  154. package/lib/module/tab-bar/glyph.js.map +1 -0
  155. package/lib/module/tab-bar/glyph.native.js +50 -0
  156. package/lib/module/tab-bar/glyph.native.js.map +1 -0
  157. package/lib/module/tab-bar/index.js +24 -0
  158. package/lib/module/tab-bar/index.js.map +1 -0
  159. package/lib/module/tab-bar/index.web.js +26 -0
  160. package/lib/module/tab-bar/index.web.js.map +1 -0
  161. package/lib/module/tab-bar/minimize-context.js +118 -0
  162. package/lib/module/tab-bar/minimize-context.js.map +1 -0
  163. package/lib/module/tab-bar/shared.js +132 -0
  164. package/lib/module/tab-bar/shared.js.map +1 -0
  165. package/lib/module/tab-bar/surface-solid.js +37 -0
  166. package/lib/module/tab-bar/surface-solid.js.map +1 -0
  167. package/lib/module/tab-bar/surface.js +31 -0
  168. package/lib/module/tab-bar/surface.js.map +1 -0
  169. package/lib/module/tab-bar/surface.native.js +109 -0
  170. package/lib/module/tab-bar/surface.native.js.map +1 -0
  171. package/lib/module/tab-bar/surface.web.js +53 -0
  172. package/lib/module/tab-bar/surface.web.js.map +1 -0
  173. package/lib/module/tab-bar/types.js +4 -0
  174. package/lib/module/tab-bar/types.js.map +1 -0
  175. package/lib/module/toast/Positioner.js +110 -0
  176. package/lib/module/toast/Positioner.js.map +1 -0
  177. package/lib/module/toast/ToastContent.js +295 -0
  178. package/lib/module/toast/ToastContent.js.map +1 -0
  179. package/lib/module/toast/ToastHost.js +63 -0
  180. package/lib/module/toast/ToastHost.js.map +1 -0
  181. package/lib/module/toast/ToastHost.native.js +38 -0
  182. package/lib/module/toast/ToastHost.native.js.map +1 -0
  183. package/lib/module/toast/ToastIcon.js +52 -0
  184. package/lib/module/toast/ToastIcon.js.map +1 -0
  185. package/lib/module/toast/ToastRow.js +407 -0
  186. package/lib/module/toast/ToastRow.js.map +1 -0
  187. package/lib/module/toast/ToastSwipeHandler.js +182 -0
  188. package/lib/module/toast/ToastSwipeHandler.js.map +1 -0
  189. package/lib/module/toast/Toaster.js +198 -0
  190. package/lib/module/toast/Toaster.js.map +1 -0
  191. package/lib/module/toast/animations.js +261 -0
  192. package/lib/module/toast/animations.js.map +1 -0
  193. package/lib/module/toast/constants.js +52 -0
  194. package/lib/module/toast/constants.js.map +1 -0
  195. package/lib/module/toast/context.js +34 -0
  196. package/lib/module/toast/context.js.map +1 -0
  197. package/lib/module/toast/index.js +27 -103
  198. package/lib/module/toast/index.js.map +1 -1
  199. package/lib/module/toast/position-utils.js +107 -0
  200. package/lib/module/toast/position-utils.js.map +1 -0
  201. package/lib/module/toast/positioner-utils.js +134 -0
  202. package/lib/module/toast/positioner-utils.js.map +1 -0
  203. package/lib/module/toast/toast-comparator.js +22 -0
  204. package/lib/module/toast/toast-comparator.js.map +1 -0
  205. package/lib/module/toast/toast-fns.js +85 -0
  206. package/lib/module/toast/toast-fns.js.map +1 -0
  207. package/lib/module/toast/toast-store.js +346 -0
  208. package/lib/module/toast/toast-store.js.map +1 -0
  209. package/lib/module/toast/toast-timers.js +104 -0
  210. package/lib/module/toast/toast-timers.js.map +1 -0
  211. package/lib/module/toast/types.js +38 -0
  212. package/lib/module/toast/types.js.map +1 -1
  213. package/lib/module/toast/use-animated-target.js +52 -0
  214. package/lib/module/toast/use-animated-target.js.map +1 -0
  215. package/lib/module/toast/use-app-state.js +70 -0
  216. package/lib/module/toast/use-app-state.js.map +1 -0
  217. package/lib/module/toast/use-toast-colors.js +109 -0
  218. package/lib/module/toast/use-toast-colors.js.map +1 -0
  219. package/lib/module/toast/use-toast-position.js +35 -0
  220. package/lib/module/toast/use-toast-position.js.map +1 -0
  221. package/lib/module/tooltip/index.web.js +2 -1
  222. package/lib/module/tooltip/index.web.js.map +1 -1
  223. package/lib/module/zoomable-image-gallery/ZoomableImageGallery.js +20 -8
  224. package/lib/module/zoomable-image-gallery/ZoomableImageGallery.js.map +1 -1
  225. package/lib/typescript/commonjs/avatar-group/AvatarGroup.web.d.ts.map +1 -1
  226. package/lib/typescript/commonjs/benefit-list/types.d.ts +2 -1
  227. package/lib/typescript/commonjs/benefit-list/types.d.ts.map +1 -1
  228. package/lib/typescript/commonjs/bottom-sheet/index.web.d.ts.map +1 -1
  229. package/lib/typescript/commonjs/context-menu/index.web.d.ts.map +1 -1
  230. package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
  231. package/lib/typescript/commonjs/fab/types.d.ts +4 -2
  232. package/lib/typescript/commonjs/fab/types.d.ts.map +1 -1
  233. package/lib/typescript/commonjs/frosted-icon-button/shared.d.ts +1 -1
  234. package/lib/typescript/commonjs/frosted-icon-button/types.d.ts +2 -1
  235. package/lib/typescript/commonjs/frosted-icon-button/types.d.ts.map +1 -1
  236. package/lib/typescript/commonjs/index.d.ts +2 -1
  237. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  238. package/lib/typescript/commonjs/index.web.d.ts +2 -1
  239. package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
  240. package/lib/typescript/commonjs/menu/index.web.d.ts.map +1 -1
  241. package/lib/typescript/commonjs/popover/index.web.d.ts.map +1 -1
  242. package/lib/typescript/commonjs/portal/index.d.ts.map +1 -1
  243. package/lib/typescript/commonjs/progressive-blur/index.d.ts +23 -0
  244. package/lib/typescript/commonjs/progressive-blur/index.d.ts.map +1 -0
  245. package/lib/typescript/commonjs/progressive-blur/index.web.d.ts +30 -0
  246. package/lib/typescript/commonjs/progressive-blur/index.web.d.ts.map +1 -0
  247. package/lib/typescript/commonjs/progressive-blur/shared.d.ts +35 -0
  248. package/lib/typescript/commonjs/progressive-blur/shared.d.ts.map +1 -0
  249. package/lib/typescript/commonjs/progressive-blur/types.d.ts +21 -0
  250. package/lib/typescript/commonjs/progressive-blur/types.d.ts.map +1 -0
  251. package/lib/typescript/commonjs/select/index.web.d.ts.map +1 -1
  252. package/lib/typescript/commonjs/styles/web-view-style.d.ts +21 -0
  253. package/lib/typescript/commonjs/styles/web-view-style.d.ts.map +1 -0
  254. package/lib/typescript/commonjs/tab-bar/TabBarBase.d.ts +36 -0
  255. package/lib/typescript/commonjs/tab-bar/TabBarBase.d.ts.map +1 -0
  256. package/lib/typescript/commonjs/tab-bar/expo-router/RouterTabBar.d.ts +59 -0
  257. package/lib/typescript/commonjs/tab-bar/expo-router/RouterTabBar.d.ts.map +1 -0
  258. package/lib/typescript/commonjs/tab-bar/expo-router/fading-tab-screen.d.ts +11 -0
  259. package/lib/typescript/commonjs/tab-bar/expo-router/fading-tab-screen.d.ts.map +1 -0
  260. package/lib/typescript/commonjs/tab-bar/expo-router/index.d.ts +14 -0
  261. package/lib/typescript/commonjs/tab-bar/expo-router/index.d.ts.map +1 -0
  262. package/lib/typescript/commonjs/tab-bar/glyph.d.ts +6 -0
  263. package/lib/typescript/commonjs/tab-bar/glyph.d.ts.map +1 -0
  264. package/lib/typescript/commonjs/tab-bar/glyph.native.d.ts +6 -0
  265. package/lib/typescript/commonjs/tab-bar/glyph.native.d.ts.map +1 -0
  266. package/lib/typescript/commonjs/tab-bar/index.d.ts +12 -0
  267. package/lib/typescript/commonjs/tab-bar/index.d.ts.map +1 -0
  268. package/lib/typescript/commonjs/tab-bar/index.web.d.ts +12 -0
  269. package/lib/typescript/commonjs/tab-bar/index.web.d.ts.map +1 -0
  270. package/lib/typescript/commonjs/tab-bar/minimize-context.d.ts +51 -0
  271. package/lib/typescript/commonjs/tab-bar/minimize-context.d.ts.map +1 -0
  272. package/lib/typescript/commonjs/tab-bar/shared.d.ts +93 -0
  273. package/lib/typescript/commonjs/tab-bar/shared.d.ts.map +1 -0
  274. package/lib/typescript/commonjs/tab-bar/surface-solid.d.ts +6 -0
  275. package/lib/typescript/commonjs/tab-bar/surface-solid.d.ts.map +1 -0
  276. package/lib/typescript/commonjs/tab-bar/surface.d.ts +29 -0
  277. package/lib/typescript/commonjs/tab-bar/surface.d.ts.map +1 -0
  278. package/lib/typescript/commonjs/tab-bar/surface.native.d.ts +6 -0
  279. package/lib/typescript/commonjs/tab-bar/surface.native.d.ts.map +1 -0
  280. package/lib/typescript/commonjs/tab-bar/surface.web.d.ts +6 -0
  281. package/lib/typescript/commonjs/tab-bar/surface.web.d.ts.map +1 -0
  282. package/lib/typescript/commonjs/tab-bar/types.d.ts +88 -0
  283. package/lib/typescript/commonjs/tab-bar/types.d.ts.map +1 -0
  284. package/lib/typescript/commonjs/toast/Positioner.d.ts +21 -0
  285. package/lib/typescript/commonjs/toast/Positioner.d.ts.map +1 -0
  286. package/lib/typescript/commonjs/toast/ToastContent.d.ts +14 -0
  287. package/lib/typescript/commonjs/toast/ToastContent.d.ts.map +1 -0
  288. package/lib/typescript/commonjs/toast/ToastHost.d.ts +6 -0
  289. package/lib/typescript/commonjs/toast/ToastHost.d.ts.map +1 -0
  290. package/lib/typescript/commonjs/toast/ToastHost.native.d.ts +6 -0
  291. package/lib/typescript/commonjs/toast/ToastHost.native.d.ts.map +1 -0
  292. package/lib/typescript/commonjs/toast/ToastIcon.d.ts +9 -0
  293. package/lib/typescript/commonjs/toast/ToastIcon.d.ts.map +1 -0
  294. package/lib/typescript/commonjs/toast/ToastRow.d.ts +80 -0
  295. package/lib/typescript/commonjs/toast/ToastRow.d.ts.map +1 -0
  296. package/lib/typescript/commonjs/toast/ToastSwipeHandler.d.ts +30 -0
  297. package/lib/typescript/commonjs/toast/ToastSwipeHandler.d.ts.map +1 -0
  298. package/lib/typescript/commonjs/toast/Toaster.d.ts +19 -0
  299. package/lib/typescript/commonjs/toast/Toaster.d.ts.map +1 -0
  300. package/lib/typescript/commonjs/toast/animations.d.ts +62 -0
  301. package/lib/typescript/commonjs/toast/animations.d.ts.map +1 -0
  302. package/lib/typescript/commonjs/toast/constants.d.ts +39 -0
  303. package/lib/typescript/commonjs/toast/constants.d.ts.map +1 -0
  304. package/lib/typescript/commonjs/toast/context.d.ts +19 -0
  305. package/lib/typescript/commonjs/toast/context.d.ts.map +1 -0
  306. package/lib/typescript/commonjs/toast/index.d.ts +23 -76
  307. package/lib/typescript/commonjs/toast/index.d.ts.map +1 -1
  308. package/lib/typescript/commonjs/toast/position-utils.d.ts +30 -0
  309. package/lib/typescript/commonjs/toast/position-utils.d.ts.map +1 -0
  310. package/lib/typescript/commonjs/toast/positioner-utils.d.ts +72 -0
  311. package/lib/typescript/commonjs/toast/positioner-utils.d.ts.map +1 -0
  312. package/lib/typescript/commonjs/toast/toast-comparator.d.ts +12 -0
  313. package/lib/typescript/commonjs/toast/toast-comparator.d.ts.map +1 -0
  314. package/lib/typescript/commonjs/toast/toast-fns.d.ts +3 -0
  315. package/lib/typescript/commonjs/toast/toast-fns.d.ts.map +1 -0
  316. package/lib/typescript/commonjs/toast/toast-store.d.ts +52 -0
  317. package/lib/typescript/commonjs/toast/toast-store.d.ts.map +1 -0
  318. package/lib/typescript/commonjs/toast/toast-timers.d.ts +24 -0
  319. package/lib/typescript/commonjs/toast/toast-timers.d.ts.map +1 -0
  320. package/lib/typescript/commonjs/toast/types.d.ts +222 -5
  321. package/lib/typescript/commonjs/toast/types.d.ts.map +1 -1
  322. package/lib/typescript/commonjs/toast/use-animated-target.d.ts +7 -0
  323. package/lib/typescript/commonjs/toast/use-animated-target.d.ts.map +1 -0
  324. package/lib/typescript/commonjs/toast/use-app-state.d.ts +18 -0
  325. package/lib/typescript/commonjs/toast/use-app-state.d.ts.map +1 -0
  326. package/lib/typescript/commonjs/toast/use-toast-colors.d.ts +22 -0
  327. package/lib/typescript/commonjs/toast/use-toast-colors.d.ts.map +1 -0
  328. package/lib/typescript/commonjs/toast/use-toast-position.d.ts +37 -0
  329. package/lib/typescript/commonjs/toast/use-toast-position.d.ts.map +1 -0
  330. package/lib/typescript/commonjs/tooltip/index.web.d.ts.map +1 -1
  331. package/lib/typescript/commonjs/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +1 -1
  332. package/lib/typescript/module/avatar-group/AvatarGroup.web.d.ts.map +1 -1
  333. package/lib/typescript/module/benefit-list/types.d.ts +2 -1
  334. package/lib/typescript/module/benefit-list/types.d.ts.map +1 -1
  335. package/lib/typescript/module/bottom-sheet/index.web.d.ts.map +1 -1
  336. package/lib/typescript/module/context-menu/index.web.d.ts.map +1 -1
  337. package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
  338. package/lib/typescript/module/fab/types.d.ts +4 -2
  339. package/lib/typescript/module/fab/types.d.ts.map +1 -1
  340. package/lib/typescript/module/frosted-icon-button/shared.d.ts +1 -1
  341. package/lib/typescript/module/frosted-icon-button/types.d.ts +2 -1
  342. package/lib/typescript/module/frosted-icon-button/types.d.ts.map +1 -1
  343. package/lib/typescript/module/index.d.ts +2 -1
  344. package/lib/typescript/module/index.d.ts.map +1 -1
  345. package/lib/typescript/module/index.web.d.ts +2 -1
  346. package/lib/typescript/module/index.web.d.ts.map +1 -1
  347. package/lib/typescript/module/menu/index.web.d.ts.map +1 -1
  348. package/lib/typescript/module/popover/index.web.d.ts.map +1 -1
  349. package/lib/typescript/module/portal/index.d.ts.map +1 -1
  350. package/lib/typescript/module/progressive-blur/index.d.ts +23 -0
  351. package/lib/typescript/module/progressive-blur/index.d.ts.map +1 -0
  352. package/lib/typescript/module/progressive-blur/index.web.d.ts +30 -0
  353. package/lib/typescript/module/progressive-blur/index.web.d.ts.map +1 -0
  354. package/lib/typescript/module/progressive-blur/shared.d.ts +35 -0
  355. package/lib/typescript/module/progressive-blur/shared.d.ts.map +1 -0
  356. package/lib/typescript/module/progressive-blur/types.d.ts +21 -0
  357. package/lib/typescript/module/progressive-blur/types.d.ts.map +1 -0
  358. package/lib/typescript/module/select/index.web.d.ts.map +1 -1
  359. package/lib/typescript/module/styles/web-view-style.d.ts +21 -0
  360. package/lib/typescript/module/styles/web-view-style.d.ts.map +1 -0
  361. package/lib/typescript/module/tab-bar/TabBarBase.d.ts +36 -0
  362. package/lib/typescript/module/tab-bar/TabBarBase.d.ts.map +1 -0
  363. package/lib/typescript/module/tab-bar/expo-router/RouterTabBar.d.ts +59 -0
  364. package/lib/typescript/module/tab-bar/expo-router/RouterTabBar.d.ts.map +1 -0
  365. package/lib/typescript/module/tab-bar/expo-router/fading-tab-screen.d.ts +11 -0
  366. package/lib/typescript/module/tab-bar/expo-router/fading-tab-screen.d.ts.map +1 -0
  367. package/lib/typescript/module/tab-bar/expo-router/index.d.ts +14 -0
  368. package/lib/typescript/module/tab-bar/expo-router/index.d.ts.map +1 -0
  369. package/lib/typescript/module/tab-bar/glyph.d.ts +6 -0
  370. package/lib/typescript/module/tab-bar/glyph.d.ts.map +1 -0
  371. package/lib/typescript/module/tab-bar/glyph.native.d.ts +6 -0
  372. package/lib/typescript/module/tab-bar/glyph.native.d.ts.map +1 -0
  373. package/lib/typescript/module/tab-bar/index.d.ts +12 -0
  374. package/lib/typescript/module/tab-bar/index.d.ts.map +1 -0
  375. package/lib/typescript/module/tab-bar/index.web.d.ts +12 -0
  376. package/lib/typescript/module/tab-bar/index.web.d.ts.map +1 -0
  377. package/lib/typescript/module/tab-bar/minimize-context.d.ts +51 -0
  378. package/lib/typescript/module/tab-bar/minimize-context.d.ts.map +1 -0
  379. package/lib/typescript/module/tab-bar/shared.d.ts +93 -0
  380. package/lib/typescript/module/tab-bar/shared.d.ts.map +1 -0
  381. package/lib/typescript/module/tab-bar/surface-solid.d.ts +6 -0
  382. package/lib/typescript/module/tab-bar/surface-solid.d.ts.map +1 -0
  383. package/lib/typescript/module/tab-bar/surface.d.ts +29 -0
  384. package/lib/typescript/module/tab-bar/surface.d.ts.map +1 -0
  385. package/lib/typescript/module/tab-bar/surface.native.d.ts +6 -0
  386. package/lib/typescript/module/tab-bar/surface.native.d.ts.map +1 -0
  387. package/lib/typescript/module/tab-bar/surface.web.d.ts +6 -0
  388. package/lib/typescript/module/tab-bar/surface.web.d.ts.map +1 -0
  389. package/lib/typescript/module/tab-bar/types.d.ts +88 -0
  390. package/lib/typescript/module/tab-bar/types.d.ts.map +1 -0
  391. package/lib/typescript/module/toast/Positioner.d.ts +21 -0
  392. package/lib/typescript/module/toast/Positioner.d.ts.map +1 -0
  393. package/lib/typescript/module/toast/ToastContent.d.ts +14 -0
  394. package/lib/typescript/module/toast/ToastContent.d.ts.map +1 -0
  395. package/lib/typescript/module/toast/ToastHost.d.ts +6 -0
  396. package/lib/typescript/module/toast/ToastHost.d.ts.map +1 -0
  397. package/lib/typescript/module/toast/ToastHost.native.d.ts +6 -0
  398. package/lib/typescript/module/toast/ToastHost.native.d.ts.map +1 -0
  399. package/lib/typescript/module/toast/ToastIcon.d.ts +9 -0
  400. package/lib/typescript/module/toast/ToastIcon.d.ts.map +1 -0
  401. package/lib/typescript/module/toast/ToastRow.d.ts +80 -0
  402. package/lib/typescript/module/toast/ToastRow.d.ts.map +1 -0
  403. package/lib/typescript/module/toast/ToastSwipeHandler.d.ts +30 -0
  404. package/lib/typescript/module/toast/ToastSwipeHandler.d.ts.map +1 -0
  405. package/lib/typescript/module/toast/Toaster.d.ts +19 -0
  406. package/lib/typescript/module/toast/Toaster.d.ts.map +1 -0
  407. package/lib/typescript/module/toast/animations.d.ts +62 -0
  408. package/lib/typescript/module/toast/animations.d.ts.map +1 -0
  409. package/lib/typescript/module/toast/constants.d.ts +39 -0
  410. package/lib/typescript/module/toast/constants.d.ts.map +1 -0
  411. package/lib/typescript/module/toast/context.d.ts +19 -0
  412. package/lib/typescript/module/toast/context.d.ts.map +1 -0
  413. package/lib/typescript/module/toast/index.d.ts +23 -76
  414. package/lib/typescript/module/toast/index.d.ts.map +1 -1
  415. package/lib/typescript/module/toast/position-utils.d.ts +30 -0
  416. package/lib/typescript/module/toast/position-utils.d.ts.map +1 -0
  417. package/lib/typescript/module/toast/positioner-utils.d.ts +72 -0
  418. package/lib/typescript/module/toast/positioner-utils.d.ts.map +1 -0
  419. package/lib/typescript/module/toast/toast-comparator.d.ts +12 -0
  420. package/lib/typescript/module/toast/toast-comparator.d.ts.map +1 -0
  421. package/lib/typescript/module/toast/toast-fns.d.ts +3 -0
  422. package/lib/typescript/module/toast/toast-fns.d.ts.map +1 -0
  423. package/lib/typescript/module/toast/toast-store.d.ts +52 -0
  424. package/lib/typescript/module/toast/toast-store.d.ts.map +1 -0
  425. package/lib/typescript/module/toast/toast-timers.d.ts +24 -0
  426. package/lib/typescript/module/toast/toast-timers.d.ts.map +1 -0
  427. package/lib/typescript/module/toast/types.d.ts +222 -5
  428. package/lib/typescript/module/toast/types.d.ts.map +1 -1
  429. package/lib/typescript/module/toast/use-animated-target.d.ts +7 -0
  430. package/lib/typescript/module/toast/use-animated-target.d.ts.map +1 -0
  431. package/lib/typescript/module/toast/use-app-state.d.ts +18 -0
  432. package/lib/typescript/module/toast/use-app-state.d.ts.map +1 -0
  433. package/lib/typescript/module/toast/use-toast-colors.d.ts +22 -0
  434. package/lib/typescript/module/toast/use-toast-colors.d.ts.map +1 -0
  435. package/lib/typescript/module/toast/use-toast-position.d.ts +37 -0
  436. package/lib/typescript/module/toast/use-toast-position.d.ts.map +1 -0
  437. package/lib/typescript/module/tooltip/index.web.d.ts.map +1 -1
  438. package/lib/typescript/module/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +1 -1
  439. package/package.json +58 -26
  440. package/src/__tests__/TabBar.test.tsx +342 -0
  441. package/src/__tests__/TabBarGlassFallback.test.tsx +234 -0
  442. package/src/__tests__/TabBarReanimatedDeps.test.ts +130 -0
  443. package/src/__tests__/TabBarWebFork.test.ts +243 -0
  444. package/src/__tests__/ToastContent.test.tsx +192 -0
  445. package/src/__tests__/ToastHostWebFork.test.ts +155 -0
  446. package/src/__tests__/Toaster.test.tsx +527 -0
  447. package/src/__tests__/animated-style-deps.test.ts +156 -0
  448. package/src/__tests__/icon-references.test.ts +243 -0
  449. package/src/__tests__/toast-animations.test.ts +98 -0
  450. package/src/__tests__/toast-comparator.test.ts +131 -0
  451. package/src/__tests__/toast-enter-driver.test.ts +147 -0
  452. package/src/__tests__/toast-fns.test.ts +240 -0
  453. package/src/__tests__/toast-position-utils.test.ts +259 -0
  454. package/src/__tests__/toast-positioner-utils.test.ts +214 -0
  455. package/src/__tests__/toast-store.test.ts +622 -0
  456. package/src/__tests__/toast-timers.test.ts +163 -0
  457. package/src/__tests__/use-animated-target.test.tsx +60 -0
  458. package/src/__tests__/use-app-state.test.tsx +127 -0
  459. package/src/__tests__/use-toast-colors.test.tsx +189 -0
  460. package/src/__tests__/web-position-fixed.test.ts +70 -0
  461. package/src/avatar-group/AvatarGroup.web.tsx +2 -1
  462. package/src/benefit-list/types.ts +2 -1
  463. package/src/bottom-sheet/index.web.tsx +3 -2
  464. package/src/context-menu/index.web.tsx +3 -2
  465. package/src/dialog/Dialog.web.tsx +4 -3
  466. package/src/fab/types.ts +4 -2
  467. package/src/frosted-icon-button/shared.ts +1 -1
  468. package/src/frosted-icon-button/types.ts +2 -1
  469. package/src/index.ts +4 -1
  470. package/src/index.web.ts +4 -1
  471. package/src/menu/index.web.tsx +2 -1
  472. package/src/popover/index.web.tsx +3 -2
  473. package/src/portal/index.tsx +4 -1
  474. package/src/progressive-blur/index.tsx +78 -0
  475. package/src/progressive-blur/index.web.tsx +65 -0
  476. package/src/progressive-blur/shared.ts +81 -0
  477. package/src/progressive-blur/types.ts +21 -0
  478. package/src/select/index.web.tsx +2 -1
  479. package/src/styles/web-view-style.ts +21 -0
  480. package/src/tab-bar/TabBar.stories.tsx +217 -0
  481. package/src/tab-bar/TabBarBase.tsx +517 -0
  482. package/src/tab-bar/expo-router/RouterTabBar.tsx +80 -0
  483. package/src/tab-bar/expo-router/fading-tab-screen.tsx +109 -0
  484. package/src/tab-bar/expo-router/index.ts +13 -0
  485. package/src/tab-bar/glyph.native.tsx +46 -0
  486. package/src/tab-bar/glyph.tsx +31 -0
  487. package/src/tab-bar/index.ts +32 -0
  488. package/src/tab-bar/index.web.tsx +34 -0
  489. package/src/tab-bar/minimize-context.tsx +117 -0
  490. package/src/tab-bar/shared.ts +159 -0
  491. package/src/tab-bar/surface-solid.tsx +40 -0
  492. package/src/tab-bar/surface.native.tsx +122 -0
  493. package/src/tab-bar/surface.tsx +28 -0
  494. package/src/tab-bar/surface.web.tsx +56 -0
  495. package/src/tab-bar/types.ts +91 -0
  496. package/src/toast/Positioner.tsx +121 -0
  497. package/src/toast/Toast.stories.tsx +292 -65
  498. package/src/toast/ToastContent.tsx +405 -0
  499. package/src/toast/ToastHost.native.tsx +31 -0
  500. package/src/toast/ToastHost.tsx +67 -0
  501. package/src/toast/ToastIcon.tsx +55 -0
  502. package/src/toast/ToastRow.tsx +485 -0
  503. package/src/toast/ToastSwipeHandler.tsx +222 -0
  504. package/src/toast/Toaster.tsx +259 -0
  505. package/src/toast/animations.ts +313 -0
  506. package/src/toast/constants.ts +76 -0
  507. package/src/toast/context.tsx +44 -0
  508. package/src/toast/index.tsx +47 -123
  509. package/src/toast/position-utils.ts +149 -0
  510. package/src/toast/positioner-utils.ts +142 -0
  511. package/src/toast/toast-comparator.ts +41 -0
  512. package/src/toast/toast-fns.ts +104 -0
  513. package/src/toast/toast-store.ts +432 -0
  514. package/src/toast/toast-timers.ts +124 -0
  515. package/src/toast/types.ts +301 -5
  516. package/src/toast/use-animated-target.ts +61 -0
  517. package/src/toast/use-app-state.ts +77 -0
  518. package/src/toast/use-toast-colors.ts +133 -0
  519. package/src/toast/use-toast-position.ts +46 -0
  520. package/src/tooltip/index.web.tsx +2 -1
  521. package/src/zoomable-image-gallery/ZoomableImageGallery.stories.tsx +134 -0
  522. package/src/zoomable-image-gallery/ZoomableImageGallery.tsx +50 -27
  523. package/lib/commonjs/toast/Toast.js +0 -267
  524. package/lib/commonjs/toast/Toast.js.map +0 -1
  525. package/lib/commonjs/toast/const.js +0 -8
  526. package/lib/commonjs/toast/const.js.map +0 -1
  527. package/lib/commonjs/toast/index.web.js +0 -114
  528. package/lib/commonjs/toast/index.web.js.map +0 -1
  529. package/lib/commonjs/toast/sonner/index.js +0 -9
  530. package/lib/commonjs/toast/sonner/index.js.map +0 -1
  531. package/lib/commonjs/toast/sonner/index.web.js +0 -9
  532. package/lib/commonjs/toast/sonner/index.web.js.map +0 -1
  533. package/lib/module/toast/Toast.js +0 -258
  534. package/lib/module/toast/Toast.js.map +0 -1
  535. package/lib/module/toast/const.js +0 -4
  536. package/lib/module/toast/const.js.map +0 -1
  537. package/lib/module/toast/index.web.js +0 -74
  538. package/lib/module/toast/index.web.js.map +0 -1
  539. package/lib/module/toast/sonner/index.js +0 -5
  540. package/lib/module/toast/sonner/index.js.map +0 -1
  541. package/lib/module/toast/sonner/index.web.js +0 -5
  542. package/lib/module/toast/sonner/index.web.js.map +0 -1
  543. package/lib/typescript/commonjs/toast/Toast.d.ts +0 -23
  544. package/lib/typescript/commonjs/toast/Toast.d.ts.map +0 -1
  545. package/lib/typescript/commonjs/toast/const.d.ts +0 -2
  546. package/lib/typescript/commonjs/toast/const.d.ts.map +0 -1
  547. package/lib/typescript/commonjs/toast/index.web.d.ts +0 -29
  548. package/lib/typescript/commonjs/toast/index.web.d.ts.map +0 -1
  549. package/lib/typescript/commonjs/toast/sonner/index.d.ts +0 -2
  550. package/lib/typescript/commonjs/toast/sonner/index.d.ts.map +0 -1
  551. package/lib/typescript/commonjs/toast/sonner/index.web.d.ts +0 -2
  552. package/lib/typescript/commonjs/toast/sonner/index.web.d.ts.map +0 -1
  553. package/lib/typescript/module/toast/Toast.d.ts +0 -23
  554. package/lib/typescript/module/toast/Toast.d.ts.map +0 -1
  555. package/lib/typescript/module/toast/const.d.ts +0 -2
  556. package/lib/typescript/module/toast/const.d.ts.map +0 -1
  557. package/lib/typescript/module/toast/index.web.d.ts +0 -29
  558. package/lib/typescript/module/toast/index.web.d.ts.map +0 -1
  559. package/lib/typescript/module/toast/sonner/index.d.ts +0 -2
  560. package/lib/typescript/module/toast/sonner/index.d.ts.map +0 -1
  561. package/lib/typescript/module/toast/sonner/index.web.d.ts +0 -2
  562. package/lib/typescript/module/toast/sonner/index.web.d.ts.map +0 -1
  563. package/src/toast/Toast.tsx +0 -269
  564. package/src/toast/const.ts +0 -1
  565. package/src/toast/index.web.tsx +0 -101
  566. package/src/toast/sonner/index.ts +0 -3
  567. package/src/toast/sonner/index.web.ts +0 -3
@@ -0,0 +1,527 @@
1
+ import React from 'react';
2
+ import { AppState, Text } from 'react-native';
3
+ import { act, fireEvent, render } from '@testing-library/react-native';
4
+
5
+ import { BloomThemeProvider } from '../theme/BloomThemeProvider';
6
+ import { ENTERING_ANIMATION_DURATION } from '../toast/constants';
7
+ import { toast, ToastOutlet } from '../toast';
8
+ import { toastStore } from '../toast/toast-store';
9
+ import type { ToasterProps, ToastPosition } from '../toast/types';
10
+
11
+ /**
12
+ * `ToastHost` (the web/default file jest resolves) portals through Bloom's DOM
13
+ * Portal, which needs react-dom — a different renderer from the one
14
+ * `@testing-library/react-native` drives. The portal has its own tests, and
15
+ * `ToastHostWebFork.test.ts` asserts the real one is wired, so here it is a
16
+ * passthrough and these tests can exercise the engine itself.
17
+ */
18
+ jest.mock('../portal/index.web', () => ({
19
+ Portal: ({ children }: { children: React.ReactNode }) => children,
20
+ }));
21
+
22
+ const renderOutlet = (props: ToasterProps = {}) =>
23
+ render(
24
+ <BloomThemeProvider mode="light" colorPreset="teal">
25
+ <ToastOutlet {...props} />
26
+ </BloomThemeProvider>,
27
+ );
28
+
29
+ const show = (run: () => void) => {
30
+ act(() => {
31
+ run();
32
+ });
33
+ };
34
+
35
+ /**
36
+ * `ReactTestInstance['type']` is `ElementType`, whose string arm is
37
+ * `keyof JSX.IntrinsicElements` — so comparing it to a React Native host name
38
+ * ('Pressable', 'Svg', …) is a type error. Normalise to a plain string instead of
39
+ * asserting the type away.
40
+ */
41
+ const hostName = (node: { type: unknown }): string =>
42
+ typeof node.type === 'string' ? node.type : '';
43
+
44
+ /**
45
+ * Rows are `Animated.View`s; `BloomThemeProvider` contributes a plain `View`
46
+ * wrapper, so `toJSON()` is never null even when the outlet renders nothing.
47
+ */
48
+ const rowsOf = ({ UNSAFE_root }: ReturnType<typeof renderOutlet>) =>
49
+ UNSAFE_root.findAll((node) => hostName(node) === 'Animated.View');
50
+
51
+ /** Total `View` count, used against an idle baseline to prove the host mounted. */
52
+ const viewCountOf = ({ UNSAFE_root }: ReturnType<typeof renderOutlet>) =>
53
+ UNSAFE_root.findAll((node) => hostName(node) === 'View').length;
54
+
55
+ /** The one row wrapper carrying the measurement `onLayout` (tier 3 of W6). */
56
+ const measuredRowOf = ({ UNSAFE_root }: ReturnType<typeof renderOutlet>) =>
57
+ UNSAFE_root.find(
58
+ (node) =>
59
+ hostName(node) === 'Animated.View' && typeof node.props.onLayout === 'function',
60
+ );
61
+
62
+ type Instance = ReturnType<typeof rowsOf>[number];
63
+
64
+ /**
65
+ * This repo's `react-native` mock stubs `StyleSheet.flatten` as an identity
66
+ * no-op, so style arrays have to be merged here rather than through RN.
67
+ */
68
+ const flattenStyle = (style: unknown): Record<string, unknown> => {
69
+ if (Array.isArray(style)) {
70
+ return Object.assign({}, ...style.map(flattenStyle));
71
+ }
72
+ return typeof style === 'object' && style !== null
73
+ ? (style as Record<string, unknown>)
74
+ : {};
75
+ };
76
+
77
+ /**
78
+ * The positioner container for one edge. `getContainerStyle` is the only absolute
79
+ * View that centres its children, and it pins all four edges — so the ANCHORED edge
80
+ * is the one `getInsetValues` pushed off zero. `center` overrides neither, so it
81
+ * matches no edge.
82
+ */
83
+ const positionerFor = (
84
+ { UNSAFE_root }: ReturnType<typeof renderOutlet>,
85
+ edge: 'top' | 'bottom',
86
+ ): Instance | undefined => {
87
+ const other = edge === 'top' ? 'bottom' : 'top';
88
+ return UNSAFE_root.findAll((node) => {
89
+ if (hostName(node) !== 'View') {
90
+ return false;
91
+ }
92
+ const style = flattenStyle(node.props.style);
93
+ return (
94
+ style.position === 'absolute' &&
95
+ style.alignItems === 'center' &&
96
+ typeof style[edge] === 'number' &&
97
+ style[edge] !== 0 &&
98
+ style[other] === 0
99
+ );
100
+ })[0];
101
+ };
102
+
103
+ /** Every string rendered inside a subtree, in render order. */
104
+ const textsIn = (node: Instance): string[] => {
105
+ const strings: string[] = [];
106
+ const visit = (instance: Instance) => {
107
+ for (const child of instance.children) {
108
+ if (typeof child === 'string') {
109
+ strings.push(child);
110
+ } else {
111
+ visit(child);
112
+ }
113
+ }
114
+ };
115
+ visit(node);
116
+ return strings;
117
+ };
118
+
119
+ const textsInPositioner = (
120
+ rendered: ReturnType<typeof renderOutlet>,
121
+ edge: 'top' | 'bottom',
122
+ ): string[] => {
123
+ const positioner = positionerFor(rendered, edge);
124
+ return positioner ? textsIn(positioner) : [];
125
+ };
126
+
127
+ /**
128
+ * A row's outermost anchor: the absolute, full-width box that hangs off one edge of
129
+ * the container. Everything else in the row is relative or statically placed.
130
+ */
131
+ const anchorOf = ({ UNSAFE_root }: ReturnType<typeof renderOutlet>) =>
132
+ UNSAFE_root.findAll((node) => {
133
+ if (hostName(node) !== 'Animated.View') {
134
+ return false;
135
+ }
136
+ const style = flattenStyle(node.props.style);
137
+ return style.position === 'absolute' && style.width === '100%';
138
+ })[0];
139
+
140
+ describe('ToastOutlet', () => {
141
+ beforeEach(() => {
142
+ jest.useFakeTimers();
143
+ toastStore.setConfig({});
144
+ });
145
+
146
+ afterEach(() => {
147
+ act(() => {
148
+ toastStore.dismissToast(undefined);
149
+ jest.runOnlyPendingTimers();
150
+ });
151
+ jest.useRealTimers();
152
+ jest.restoreAllMocks();
153
+ });
154
+
155
+ it('renders nothing while the stack is empty', () => {
156
+ expect(rowsOf(renderOutlet())).toHaveLength(0);
157
+ });
158
+
159
+ it('renders a queued toast', () => {
160
+ const { getByText } = renderOutlet();
161
+ show(() => toast('Saved'));
162
+ expect(getByText('Saved')).toBeTruthy();
163
+ });
164
+
165
+ it('renders the title and description of a variant toast', () => {
166
+ const { getByText } = renderOutlet();
167
+ show(() => toast.success('Profile updated', { description: 'All good' }));
168
+ expect(getByText('Profile updated')).toBeTruthy();
169
+ expect(getByText('All good')).toBeTruthy();
170
+ });
171
+
172
+ it('renders custom jsx instead of the default row', () => {
173
+ const { getByText, queryByText } = renderOutlet();
174
+ show(() => toast.custom(<Text>Fully custom</Text>));
175
+ expect(getByText('Fully custom')).toBeTruthy();
176
+ // The default renderer is bypassed entirely, so no close button or title row.
177
+ expect(queryByText('')).toBeNull();
178
+ });
179
+
180
+ it('renders an action button that runs its handler', () => {
181
+ const onClick = jest.fn();
182
+ const { getByText } = renderOutlet();
183
+ show(() => toast('Message sent', { action: { label: 'Undo', onClick } }));
184
+
185
+ fireEvent.press(getByText('Undo'));
186
+ expect(onClick).toHaveBeenCalledTimes(1);
187
+ });
188
+
189
+ it('stops rendering a dismissed toast', () => {
190
+ const { queryByText } = renderOutlet();
191
+ let id: string | number = '';
192
+ show(() => {
193
+ id = toast('Temporary');
194
+ });
195
+ expect(queryByText('Temporary')).toBeTruthy();
196
+
197
+ show(() => {
198
+ toast.dismiss(id);
199
+ });
200
+ expect(queryByText('Temporary')).toBeNull();
201
+ });
202
+
203
+ it('renders no more rows than visibleToasts', () => {
204
+ const { queryByText } = renderOutlet({ visibleToasts: 2 });
205
+ show(() => {
206
+ toast('first');
207
+ toast('second');
208
+ toast('third');
209
+ });
210
+
211
+ expect(queryByText('first')).toBeNull();
212
+ expect(queryByText('second')).toBeTruthy();
213
+ expect(queryByText('third')).toBeTruthy();
214
+ });
215
+
216
+ it('applies the outlet duration to a toast that does not set one', () => {
217
+ renderOutlet({ duration: 10_000 });
218
+ show(() => toast('Long lived'));
219
+ expect(toastStore.getSnapshot().toasts[0]?.duration).toBe(10_000);
220
+ });
221
+
222
+ it('keeps the host mounted for the exit animation, then tears it down', () => {
223
+ const rendered = renderOutlet();
224
+ const idleViews = viewCountOf(rendered);
225
+
226
+ let id: string | number = '';
227
+ show(() => {
228
+ id = toast('Bye');
229
+ });
230
+ expect(viewCountOf(rendered)).toBeGreaterThan(idleViews);
231
+
232
+ show(() => {
233
+ toast.dismiss(id);
234
+ });
235
+ // Row gone, host still up so the exit animation can play out.
236
+ expect(rendered.queryByText('Bye')).toBeNull();
237
+ expect(viewCountOf(rendered)).toBeGreaterThan(idleViews);
238
+
239
+ act(() => {
240
+ jest.advanceTimersByTime(ENTERING_ANIMATION_DURATION);
241
+ });
242
+ expect(viewCountOf(rendered)).toBe(idleViews);
243
+ expect(rowsOf(rendered)).toHaveLength(0);
244
+ });
245
+
246
+ it('groups toasts into one container per occupied position', () => {
247
+ const { getByText } = renderOutlet();
248
+ show(() => {
249
+ toast('at the bottom');
250
+ toast('at the top', { position: 'top-center' });
251
+ });
252
+
253
+ // Both render, each inside its own positioner.
254
+ expect(getByText('at the bottom')).toBeTruthy();
255
+ expect(getByText('at the top')).toBeTruthy();
256
+ });
257
+
258
+ /**
259
+ * WHICH positioner a row lands in, not just that it renders. Grouping used to
260
+ * key a position-less row on `positionIndex === 0`, so the moment ANY
261
+ * top-center toast existed a plain `toast('Saved')` was assigned to the
262
+ * top-center container — visible only as a sliver above the screen edge — and an
263
+ * already-placed row jumped there when a top-center toast arrived.
264
+ */
265
+ describe('position assignment', () => {
266
+ it('keeps a position-less toast at the outlet position when a top-center one is alive', () => {
267
+ const rendered = renderOutlet();
268
+ show(() => {
269
+ toast('explicitly at the top', { position: 'top-center' });
270
+ toast('no position given');
271
+ });
272
+
273
+ expect(textsInPositioner(rendered, 'top')).toEqual([
274
+ 'explicitly at the top',
275
+ ]);
276
+ expect(textsInPositioner(rendered, 'bottom')).toEqual([
277
+ 'no position given',
278
+ ]);
279
+ });
280
+
281
+ it('does not move an already-placed position-less toast when a top-center one arrives', () => {
282
+ const rendered = renderOutlet();
283
+ show(() => toast('no position given'));
284
+ expect(textsInPositioner(rendered, 'bottom')).toEqual([
285
+ 'no position given',
286
+ ]);
287
+
288
+ show(() => toast('explicitly at the top', { position: 'top-center' }));
289
+ expect(textsInPositioner(rendered, 'bottom')).toEqual([
290
+ 'no position given',
291
+ ]);
292
+ expect(textsInPositioner(rendered, 'top')).toEqual([
293
+ 'explicitly at the top',
294
+ ]);
295
+ });
296
+
297
+ it('follows the outlet position, not a hardcoded default', () => {
298
+ const rendered = renderOutlet({ position: 'top-center' });
299
+ show(() => {
300
+ toast('explicitly at the bottom', { position: 'bottom-center' });
301
+ toast('no position given');
302
+ });
303
+
304
+ expect(textsInPositioner(rendered, 'top')).toEqual(['no position given']);
305
+ expect(textsInPositioner(rendered, 'bottom')).toEqual([
306
+ 'explicitly at the bottom',
307
+ ]);
308
+ });
309
+
310
+ /**
311
+ * The other half of the geometry contract (`toast-positioner-utils.test.ts`
312
+ * pins the container): the row hangs off exactly ONE edge, and which edge it is
313
+ * depends on the position. `center` anchors to the 50% LINE, which lives on the
314
+ * row because the container is no longer itself placed at 50% — dropping that
315
+ * would park every centred toast at the top of the screen.
316
+ */
317
+ it.each<[ToastPosition, 'top' | 'bottom', number | string]>([
318
+ ['bottom-center', 'bottom', 0],
319
+ ['top-center', 'top', 0],
320
+ ['center', 'top', '50%'],
321
+ ])('anchors a %s row to %s: %s', (position, edge, value) => {
322
+ const rendered = renderOutlet({ position });
323
+ show(() => toast('Anchor me'));
324
+
325
+ const anchor = anchorOf(rendered);
326
+ expect(anchor).toBeDefined();
327
+ const style = flattenStyle(anchor?.props.style);
328
+ expect(style[edge]).toBe(value);
329
+ // Anchoring to both edges would stretch the row instead of placing it.
330
+ expect(style[edge === 'top' ? 'bottom' : 'top']).toBeUndefined();
331
+ });
332
+
333
+ it('orders each group by its own position, not the outlet position', () => {
334
+ // Outlet is bottom-center, so its own group renders oldest-first. The
335
+ // top-center group must still render newest-first — a top-anchored stack
336
+ // grows downward from the newest row. `visibleToasts` is raised so the
337
+ // store's cap does not cull the oldest of the four.
338
+ const rendered = renderOutlet({ visibleToasts: 5 });
339
+ show(() => {
340
+ toast('first at the top', { position: 'top-center' });
341
+ toast('second at the top', { position: 'top-center' });
342
+ toast('first at the bottom');
343
+ toast('second at the bottom');
344
+ });
345
+
346
+ expect(textsInPositioner(rendered, 'top')).toEqual([
347
+ 'second at the top',
348
+ 'first at the top',
349
+ ]);
350
+ expect(textsInPositioner(rendered, 'bottom')).toEqual([
351
+ 'first at the bottom',
352
+ 'second at the bottom',
353
+ ]);
354
+ });
355
+ });
356
+
357
+ it('records a measured row height from the onLayout tier', () => {
358
+ const rendered = renderOutlet();
359
+ let id: string | number = '';
360
+ show(() => {
361
+ id = toast('Measure me');
362
+ });
363
+
364
+ const measured = measuredRowOf(rendered);
365
+ act(() => {
366
+ measured.props.onLayout({ nativeEvent: { layout: { height: 84 } } });
367
+ });
368
+ expect(toastStore.getSnapshot().toastHeights[id]).toBe(84);
369
+ });
370
+
371
+ it('ignores a zero height so an unmeasured row keeps the estimate', () => {
372
+ const rendered = renderOutlet();
373
+ let id: string | number = '';
374
+ show(() => {
375
+ id = toast('Not measured yet');
376
+ });
377
+
378
+ const measured = measuredRowOf(rendered);
379
+ act(() => {
380
+ measured.props.onLayout({ nativeEvent: { layout: { height: 0 } } });
381
+ });
382
+ expect(toastStore.getSnapshot().toastHeights[id]).toBeUndefined();
383
+ });
384
+
385
+ /**
386
+ * The outlet's `toastOptions` style slots and a per-toast `styles` object are
387
+ * folded into ONE styles object (`mergeToastStyles`). Upstream threads all
388
+ * fifteen slots down as separate props, so this is Bloom-specific plumbing that
389
+ * has to keep the documented precedence: per-toast beats outlet-level.
390
+ */
391
+ describe('style precedence', () => {
392
+ const titleStyleOf = (
393
+ rendered: ReturnType<typeof renderOutlet>,
394
+ text: string,
395
+ ) => rendered.getByText(text).props.style;
396
+
397
+ it('applies an outlet-level toastOptions style to the row', () => {
398
+ const rendered = renderOutlet({ toastOptions: { titleStyle: { fontSize: 11 } } });
399
+ show(() => toast('From the outlet'));
400
+
401
+ expect(titleStyleOf(rendered, 'From the outlet')).toEqual(
402
+ expect.arrayContaining([expect.objectContaining({ fontSize: 11 })]),
403
+ );
404
+ });
405
+
406
+ it('lets a per-toast style win over the outlet for the same key', () => {
407
+ const rendered = renderOutlet({ toastOptions: { titleStyle: { fontSize: 11 } } });
408
+ show(() => toast('Per-toast wins', { styles: { title: { fontSize: 99 } } }));
409
+
410
+ const style = titleStyleOf(rendered, 'Per-toast wins');
411
+ expect(style).toEqual(
412
+ expect.arrayContaining([expect.objectContaining({ fontSize: 99 })]),
413
+ );
414
+ expect(style).not.toEqual(
415
+ expect.arrayContaining([expect.objectContaining({ fontSize: 11 })]),
416
+ );
417
+ });
418
+
419
+ it('merges rather than replaces when the two set different keys', () => {
420
+ const rendered = renderOutlet({ toastOptions: { titleStyle: { fontSize: 11 } } });
421
+ show(() =>
422
+ toast('Merged', { styles: { title: { letterSpacing: 2 } } }),
423
+ );
424
+
425
+ expect(titleStyleOf(rendered, 'Merged')).toEqual(
426
+ expect.arrayContaining([
427
+ expect.objectContaining({ fontSize: 11, letterSpacing: 2 }),
428
+ ]),
429
+ );
430
+ });
431
+
432
+ it('merges per SLOT — a per-toast toast style does not wipe an outlet title style', () => {
433
+ // The failure mode a naive whole-object `{...outlet, ...perToast}` would
434
+ // produce: setting one slot per-toast drops every other outlet-level slot.
435
+ const rendered = renderOutlet({
436
+ toastOptions: { titleStyle: { fontSize: 11 } },
437
+ });
438
+ show(() =>
439
+ toast('Other slot', { styles: { toast: { borderWidth: 4 } } }),
440
+ );
441
+
442
+ expect(titleStyleOf(rendered, 'Other slot')).toEqual(
443
+ expect.arrayContaining([expect.objectContaining({ fontSize: 11 })]),
444
+ );
445
+ });
446
+
447
+ it('applies the outlet-level per-variant surface style', () => {
448
+ const rendered = renderOutlet({
449
+ toastOptions: { success: { borderWidth: 3 } },
450
+ });
451
+ show(() => toast.success('Variant styled'));
452
+
453
+ // The variant slot lands on the surface, which wraps the title's row.
454
+ const surfaces = rendered.UNSAFE_root.findAll(
455
+ (node) =>
456
+ hostName(node) === 'View' &&
457
+ Array.isArray(node.props.style) &&
458
+ JSON.stringify(node.props.style).includes('"borderWidth":3'),
459
+ );
460
+ expect(surfaces.length).toBeGreaterThan(0);
461
+ });
462
+ });
463
+
464
+ describe('app-state pausing', () => {
465
+ it('subscribes exactly once for the whole stack, not once per row', () => {
466
+ const addEventListener = jest.spyOn(AppState, 'addEventListener');
467
+ renderOutlet();
468
+ show(() => {
469
+ toast('one');
470
+ toast('two');
471
+ toast('three');
472
+ });
473
+
474
+ expect(addEventListener).toHaveBeenCalledTimes(1);
475
+ });
476
+
477
+ it('pauses every timer on background and resumes on foreground', () => {
478
+ const pauseAll = jest.spyOn(toastStore, 'pauseAllTimers');
479
+ const resumeAll = jest.spyOn(toastStore, 'resumeAllTimers');
480
+ const addEventListener = jest.spyOn(AppState, 'addEventListener');
481
+ renderOutlet();
482
+ show(() => toast('Hold me'));
483
+
484
+ const listener = addEventListener.mock.calls[0]?.[1];
485
+ expect(listener).toBeDefined();
486
+
487
+ act(() => {
488
+ listener?.('background');
489
+ });
490
+ expect(pauseAll).toHaveBeenCalledTimes(1);
491
+
492
+ act(() => {
493
+ listener?.('active');
494
+ });
495
+ expect(resumeAll).toHaveBeenCalledTimes(1);
496
+ });
497
+
498
+ it('reports one edge per transition, not one per event', () => {
499
+ const pauseAll = jest.spyOn(toastStore, 'pauseAllTimers');
500
+ const addEventListener = jest.spyOn(AppState, 'addEventListener');
501
+ renderOutlet();
502
+ show(() => toast('Hold me'));
503
+
504
+ const listener = addEventListener.mock.calls[0]?.[1];
505
+ act(() => {
506
+ listener?.('inactive');
507
+ listener?.('background');
508
+ });
509
+
510
+ // Upstream re-pauses on the second transition; only the real edge counts.
511
+ expect(pauseAll).toHaveBeenCalledTimes(1);
512
+ });
513
+
514
+ it('does nothing when pauseWhenPageIsHidden is off', () => {
515
+ const pauseAll = jest.spyOn(toastStore, 'pauseAllTimers');
516
+ const addEventListener = jest.spyOn(AppState, 'addEventListener');
517
+ renderOutlet({ pauseWhenPageIsHidden: false });
518
+ show(() => toast('Keep counting'));
519
+
520
+ const listener = addEventListener.mock.calls[0]?.[1];
521
+ act(() => {
522
+ listener?.('background');
523
+ });
524
+ expect(pauseAll).not.toHaveBeenCalled();
525
+ });
526
+ });
527
+ });
@@ -0,0 +1,156 @@
1
+ import { readdirSync, readFileSync, statSync } from 'node:fs';
2
+ import { join, relative } from 'node:path';
3
+
4
+ /**
5
+ * Every shared value a Reanimated mapper READS must appear in that mapper's
6
+ * dependency array.
7
+ *
8
+ * On web WITHOUT the react-native-worklets babel plugin — the production reality
9
+ * for every Oxy RN-Web app — reanimated cannot auto-detect which shared values a
10
+ * worklet reads, so it drives the mapper off its deps array instead. With a
11
+ * missing or incomplete array the mapper runs ONCE and freezes at the first frame:
12
+ * the shared value keeps animating underneath, the DOM never updates. Native (with
13
+ * the plugin) auto-tracks and ignores the extra deps, so listing them is correct on
14
+ * both platforms.
15
+ *
16
+ * This has bitten Bloom three times — `BottomSheetBase` (fixed), `ConnectionDots` /
17
+ * `AnimatedCheck` (fixed), and `ZoomableImageGallery` (fixed in 0.51.0, found by
18
+ * static analysis because it had no story). Hence a guard rather than vigilance.
19
+ *
20
+ * jest cannot catch this class at all: the reanimated test mock resolves animations
21
+ * synchronously, so a frozen mapper and a working one look identical. Source
22
+ * analysis is the only automatable check; the real behaviour is verified in a
23
+ * foregrounded browser.
24
+ */
25
+
26
+ const SRC = join(__dirname, '..');
27
+ const MAPPERS = ['useAnimatedStyle', 'useDerivedValue', 'useAnimatedProps'] as const;
28
+
29
+ /**
30
+ * Mappers that legitimately omit a read from their deps.
31
+ *
32
+ * Keyed by FILE, not line, so an unrelated edit above them doesn't invalidate the
33
+ * entry — and with an exact count, so a NEW offender in the same file still fails.
34
+ */
35
+ const ALLOWED: Array<{ file: string; count: number; reason: string }> = [
36
+ {
37
+ file: 'dialog/Dialog.tsx',
38
+ count: 2,
39
+ reason:
40
+ 'Native-only fork: web resolves Dialog.web.tsx (see dialog/index.web.ts), ' +
41
+ 'and on native the worklets plugin auto-tracks reads, so the deps array is ' +
42
+ 'not what drives these mappers. Harmless where this file actually runs.',
43
+ },
44
+ ];
45
+
46
+ type Offender = {
47
+ location: string;
48
+ mapper: string;
49
+ problem: 'no deps array' | 'incomplete deps';
50
+ values: string[];
51
+ };
52
+
53
+ /** Comments may legitimately discuss a mapper or show one in an example. */
54
+ function stripComments(source: string): string {
55
+ return source
56
+ .replace(/\/\*[\s\S]*?\*\//g, (block) => '\n'.repeat((block.match(/\n/g) ?? []).length))
57
+ .replace(/^[ \t]*\/\/.*$/gm, '');
58
+ }
59
+
60
+ function sourceFiles(dir: string): string[] {
61
+ return readdirSync(dir).flatMap((entry) => {
62
+ const full = join(dir, entry);
63
+ if (statSync(full).isDirectory()) {
64
+ return entry === '__tests__' ? [] : sourceFiles(full);
65
+ }
66
+ return /\.tsx?$/.test(entry) ? [full] : [];
67
+ });
68
+ }
69
+
70
+ /** Text between the parens of the call starting at `start`, paren-balanced. */
71
+ function callText(source: string, start: number): string {
72
+ const open = source.indexOf('(', start);
73
+ let depth = 0;
74
+ for (let i = open; i < source.length; i++) {
75
+ if (source[i] === '(') depth += 1;
76
+ else if (source[i] === ')') {
77
+ depth -= 1;
78
+ if (depth === 0) return source.slice(open + 1, i);
79
+ }
80
+ }
81
+ return source.slice(open + 1);
82
+ }
83
+
84
+ function analyse(): { offenders: Offender[]; scanned: number } {
85
+ const offenders: Offender[] = [];
86
+ let scanned = 0;
87
+
88
+ for (const file of sourceFiles(SRC)) {
89
+ const source = stripComments(readFileSync(file, 'utf8'));
90
+
91
+ for (const mapper of MAPPERS) {
92
+ const calls = source.matchAll(new RegExp(`${mapper}\\s*\\(`, 'g'));
93
+ for (const call of calls) {
94
+ if (call.index === undefined) continue;
95
+ scanned += 1;
96
+
97
+ const text = callText(source, call.index);
98
+ const line = source.slice(0, call.index).split('\n').length;
99
+ const location = `${relative(SRC, file)}:${line}`;
100
+
101
+ // Trailing comma after the deps array is idiomatic and must parse.
102
+ const deps = [...text.matchAll(/,\s*(\[[\s\S]*?\])\s*,?\s*$/g)].pop();
103
+ const body = deps ? text.slice(0, deps.index) : text;
104
+ const reads = [
105
+ ...new Set([...body.matchAll(/\b([A-Za-z_$][\w$]*)\.value\b/g)].map((m) => m[1] ?? '')),
106
+ ].filter(Boolean);
107
+
108
+ if (reads.length === 0) continue;
109
+
110
+ if (!deps) {
111
+ offenders.push({ location, mapper, problem: 'no deps array', values: reads });
112
+ continue;
113
+ }
114
+ const declared = deps[1] ?? '';
115
+ const missing = reads.filter(
116
+ (read) => !new RegExp(`\\b${read}\\b`).test(declared),
117
+ );
118
+ if (missing.length > 0) {
119
+ offenders.push({ location, mapper, problem: 'incomplete deps', values: missing });
120
+ }
121
+ }
122
+ }
123
+ }
124
+ return { offenders, scanned };
125
+ }
126
+
127
+ const { offenders, scanned } = analyse();
128
+
129
+ describe('reanimated mapper dependency arrays', () => {
130
+ it('scanned a plausible number of mappers (guards against a broken walk)', () => {
131
+ // If the traversal or the regex breaks, this fails instead of passing vacuously.
132
+ expect(scanned).toBeGreaterThanOrEqual(15);
133
+ });
134
+
135
+ it('has no mapper reading a shared value that is absent from its deps', () => {
136
+ const unexpected = offenders.filter(
137
+ (o) => !ALLOWED.some((entry) => o.location.startsWith(`${entry.file}:`)),
138
+ );
139
+ expect(
140
+ unexpected.map((o) => `${o.location} ${o.mapper} — ${o.problem}: ${o.values.join(', ')}`),
141
+ ).toEqual([]);
142
+ });
143
+
144
+ it.each(ALLOWED)('allowlisted $file has exactly $count known mapper(s)', ({ file, count }) => {
145
+ // A NEW offender in an allowlisted file must still fail.
146
+ expect(offenders.filter((o) => o.location.startsWith(`${file}:`))).toHaveLength(count);
147
+ });
148
+
149
+ it('keeps the allowlist small enough to be reviewable', () => {
150
+ // If this grows, that is a finding about the repo — not something to encode.
151
+ expect(ALLOWED.length).toBeLessThanOrEqual(3);
152
+ for (const entry of ALLOWED) {
153
+ expect(entry.reason.length).toBeGreaterThan(40);
154
+ }
155
+ });
156
+ });