@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,234 @@
1
+ import React from 'react';
2
+ import type { ReactTestInstance } from 'react-test-renderer';
3
+ import { render } from '@testing-library/react-native';
4
+
5
+ import type { TabBarSurfaceProps } from '../tab-bar/shared';
6
+ import type { TabBarTheme } from '../tab-bar/types';
7
+
8
+ /**
9
+ * The native capsule surface must DEGRADE, never crash, when `expo-glass-effect`
10
+ * is not really usable.
11
+ *
12
+ * This is the one thing the rest of the tab-bar suite structurally cannot see.
13
+ * `TabBar.test.tsx` renders the native surface against the manual mock in
14
+ * `__mocks__/expo-glass-effect.ts`, which is a HEALTHY install reporting
15
+ * `isLiquidGlassAvailable() === false` — so it only ever exercises the branch a
16
+ * correctly-packaged Android device takes. Every failure mode below is a
17
+ * different install: the module resolved but handed back no exports, or the JS
18
+ * package is there while the native module is not.
19
+ *
20
+ * Each case is re-mocked into its own module registry because both hazards live at
21
+ * MODULE scope. `Animated.createAnimatedComponent(GlassView)` runs on import, and
22
+ * on iOS `isLiquidGlassAvailable()` reaches a native module through
23
+ * `requireNativeModule`, which throws by contract when it is absent. Mocking after
24
+ * the module under test was imported would test a render branch and miss both.
25
+ *
26
+ * The two counter-tests at the end are what keep the rest honest: a guard that
27
+ * always fell through to the solid surface would satisfy every other assertion
28
+ * here while silently deleting the glass look on every iOS 26 device.
29
+ */
30
+
31
+ /** Every export may be absent — that is the whole point of these fixtures. */
32
+ interface GlassEffectModule {
33
+ GlassView?: unknown;
34
+ isLiquidGlassAvailable?: () => boolean;
35
+ isGlassEffectAPIAvailable?: () => boolean;
36
+ }
37
+
38
+ /**
39
+ * A host tag stands in for the real `GlassView` component: under the reanimated
40
+ * mock `createAnimatedComponent` is the identity, so whatever the package exports
41
+ * IS the element type, and a string host is the cheapest valid one to assert on.
42
+ * It matches the tag the manual mock renders.
43
+ */
44
+ const GLASS_HOST = 'GlassView';
45
+
46
+ const THEME: TabBarTheme = {
47
+ activeTint: 'rgb(20 20 20)',
48
+ inactiveTint: 'rgb(120 120 120)',
49
+ highlight: 'rgb(230 230 230)',
50
+ glassTint: 'rgba(255, 255, 255, 0.55)',
51
+ solidFallback: 'rgb(246 246 246)',
52
+ };
53
+
54
+ const STYLE = { borderRadius: 29 };
55
+
56
+ function flattenStyle(style: unknown): Record<string, unknown> {
57
+ const out: Record<string, unknown> = {};
58
+ const visit = (s: unknown): void => {
59
+ if (Array.isArray(s)) s.forEach(visit);
60
+ else if (s && typeof s === 'object') Object.assign(out, s);
61
+ };
62
+ visit(style);
63
+ return out;
64
+ }
65
+
66
+ /** Every host node rendered as `tag`. */
67
+ function hosts(root: ReactTestInstance, tag: string): ReactTestInstance[] {
68
+ return root.findAll((node) => typeof node.type === 'string' && node.type === tag);
69
+ }
70
+
71
+ /**
72
+ * Render `surface.native.tsx` against a given `expo-glass-effect`.
73
+ *
74
+ * Only the surface comes from the isolated registry — testing-library registers
75
+ * suite-level hooks when it loads, so it has to be imported at the top of the file
76
+ * rather than inside a test. Nothing in the rendered tree calls a hook, and the
77
+ * surface renders host strings from the reanimated mock, so the two registries
78
+ * never have to agree on a React instance. `times` re-renders within one registry,
79
+ * for the assertion about module-scoped memoization.
80
+ */
81
+ function renderNativeSurface(glassEffect: GlassEffectModule, times = 1): ReactTestInstance {
82
+ let root: ReactTestInstance | undefined;
83
+
84
+ jest.isolateModules(() => {
85
+ jest.doMock('expo-glass-effect', () => glassEffect);
86
+
87
+ const { TabBarSurface } = require('../tab-bar/surface.native') as {
88
+ TabBarSurface: React.ComponentType<TabBarSurfaceProps>;
89
+ };
90
+
91
+ for (let i = 0; i < times; i += 1) {
92
+ root = render(<TabBarSurface theme={THEME} style={STYLE} />).UNSAFE_root;
93
+ }
94
+ });
95
+
96
+ if (!root) throw new Error('the native surface did not render');
97
+ return root;
98
+ }
99
+
100
+ /** Assert the tree is the opaque non-glass surface, filled from the theme. */
101
+ function expectSolidFallback(root: ReactTestInstance): void {
102
+ expect(hosts(root, GLASS_HOST)).toHaveLength(0);
103
+ const surface = hosts(root, 'Animated.View')[0];
104
+ expect(surface).toBeTruthy();
105
+ expect(flattenStyle(surface?.props.style).backgroundColor).toBe(THEME.solidFallback);
106
+ // The animated capsule radius must survive the fallback — the pill still
107
+ // reshapes as the bar minimizes.
108
+ expect(flattenStyle(surface?.props.style).borderRadius).toBe(STYLE.borderRadius);
109
+ }
110
+
111
+ describe('TabBarSurface (native) — degrading when glass is unusable', () => {
112
+ let warn: jest.SpyInstance<void, Parameters<typeof console.warn>>;
113
+
114
+ beforeEach(() => {
115
+ jest.resetModules();
116
+ warn = jest.spyOn(console, 'warn').mockImplementation(() => undefined);
117
+ });
118
+
119
+ afterEach(() => {
120
+ warn.mockRestore();
121
+ });
122
+
123
+ it('falls back when the module resolved without GlassView', () => {
124
+ // `createAnimatedComponent(undefined)` produces an element type React rejects
125
+ // with "Element type is invalid … but got: undefined" — and it happens at
126
+ // import, so the whole screen the bar is on goes down with it.
127
+ expectSolidFallback(
128
+ renderNativeSurface({ GlassView: undefined, isLiquidGlassAvailable: () => true }),
129
+ );
130
+ });
131
+
132
+ it('falls back when the module delivered no exports at all', () => {
133
+ // A stub, an alias, or a resolver that landed on a platform-specific file:
134
+ // there is no `isLiquidGlassAvailable` to call either, so calling it blindly
135
+ // is a TypeError.
136
+ expectSolidFallback(renderNativeSurface({}));
137
+ });
138
+
139
+ it('falls back when the native module is missing from the build', () => {
140
+ // On iOS `isLiquidGlassAvailable()` resolves `ExpoGlassEffect` through
141
+ // `requireNativeModule`, which THROWS by contract when the module is not in
142
+ // the binary — an OTA JS update landing on a binary built before the package
143
+ // was linked reaches exactly this state.
144
+ expectSolidFallback(
145
+ renderNativeSurface({
146
+ GlassView: GLASS_HOST,
147
+ isLiquidGlassAvailable: () => {
148
+ throw new Error("Cannot find native module 'ExpoGlassEffect'");
149
+ },
150
+ }),
151
+ );
152
+ });
153
+
154
+ it('reports the missing native module instead of swallowing it', () => {
155
+ renderNativeSurface({
156
+ GlassView: GLASS_HOST,
157
+ isLiquidGlassAvailable: () => {
158
+ throw new Error("Cannot find native module 'ExpoGlassEffect'");
159
+ },
160
+ });
161
+
162
+ expect(warn).toHaveBeenCalledTimes(1);
163
+ const [message, detail] = warn.mock.calls[0] ?? [];
164
+ expect(String(message)).toContain('expo-glass-effect');
165
+ expect(String(detail)).toContain("Cannot find native module 'ExpoGlassEffect'");
166
+ });
167
+
168
+ it('falls back when the platform has no glass API (iOS 26 betas)', () => {
169
+ // Upstream's own guard: on those builds `isLiquidGlassAvailable()` answers
170
+ // true while touching `GlassView` crashes NATIVELY, below JS.
171
+ expectSolidFallback(
172
+ renderNativeSurface({
173
+ GlassView: GLASS_HOST,
174
+ isLiquidGlassAvailable: () => true,
175
+ isGlassEffectAPIAvailable: () => false,
176
+ }),
177
+ );
178
+ });
179
+
180
+ it('renders real glass when the package is fully there', () => {
181
+ const root = renderNativeSurface({
182
+ GlassView: GLASS_HOST,
183
+ isLiquidGlassAvailable: () => true,
184
+ isGlassEffectAPIAvailable: () => true,
185
+ });
186
+
187
+ const glass = hosts(root, GLASS_HOST)[0];
188
+ expect(glass).toBeTruthy();
189
+ expect(glass?.props.glassEffectStyle).toBe('regular');
190
+ expect(flattenStyle(glass?.props.style).backgroundColor).toBe(THEME.glassTint);
191
+ expect(warn).not.toHaveBeenCalled();
192
+ });
193
+
194
+ it('renders glass on a version that predates isGlassEffectAPIAvailable', () => {
195
+ // The probe first shipped in 0.1.9, so the `>=0.1.9` peer floor guarantees it
196
+ // — but a peer range only WARNS, so a consumer can still resolve an older
197
+ // copy. A missing probe means "not applicable", never "unavailable"; treating
198
+ // it as the latter would delete the glass look on every working device.
199
+ expect(
200
+ hosts(
201
+ renderNativeSurface({ GlassView: GLASS_HOST, isLiquidGlassAvailable: () => true }),
202
+ GLASS_HOST,
203
+ ),
204
+ ).toHaveLength(1);
205
+ });
206
+
207
+ it('probes availability once per session, not once per render', () => {
208
+ let probes = 0;
209
+ renderNativeSurface(
210
+ {
211
+ GlassView: GLASS_HOST,
212
+ isLiquidGlassAvailable: () => {
213
+ probes += 1;
214
+ return true;
215
+ },
216
+ },
217
+ 3,
218
+ );
219
+ expect(probes).toBe(1);
220
+ });
221
+
222
+ it('reuses the neutral surface rather than a second implementation', () => {
223
+ // Two copies of the fallback would drift: the neutral variant is what web
224
+ // bundlers and a consumer's `tsc` resolve, and it must paint exactly what an
225
+ // Android device paints.
226
+ jest.isolateModules(() => {
227
+ const { TabBarSurface } = require('../tab-bar/surface') as { TabBarSurface: unknown };
228
+ const { SolidTabBarSurface } = require('../tab-bar/surface-solid') as {
229
+ SolidTabBarSurface: unknown;
230
+ };
231
+ expect(TabBarSurface).toBe(SolidTabBarSurface);
232
+ });
233
+ });
234
+ });
@@ -0,0 +1,130 @@
1
+ import { readdirSync, readFileSync, statSync } from 'node:fs';
2
+ import { join, relative } from 'node:path';
3
+
4
+ /**
5
+ * Every reanimated mapper in the tab bar must pass a NON-EMPTY dependency array.
6
+ *
7
+ * On web WITHOUT the react-native-worklets babel plugin — the production reality
8
+ * for every Oxy RN-Web app — reanimated cannot auto-detect which shared values a
9
+ * worklet reads, so it drives the mapper off its deps array instead. A missing or
10
+ * empty array means the mapper runs ONCE and freezes at the first frame: the
11
+ * shared values keep animating underneath, the DOM never updates. For this
12
+ * component that means a bar that never minimizes, a highlight that never moves
13
+ * and a scroll handler bound to the first render's state — with no error
14
+ * anywhere. Native (plugin present) auto-tracks and ignores the extra deps, so
15
+ * listing them is correct on both platforms.
16
+ *
17
+ * This is deliberately STRICTER than the repo-wide `animated-style-deps` guard,
18
+ * which only checks that the values a mapper reads appear in the deps it
19
+ * declares. Here every mapper must carry a real deps array whether or not the
20
+ * regex can see a `.value` read inside it, and `useAnimatedScrollHandler` — which
21
+ * the repo-wide guard does not scan at all — is included, because
22
+ * `useMinimizeOnScroll` is the single entry point through which every screen
23
+ * drives the bar.
24
+ *
25
+ * Jest cannot catch this class at all: the reanimated mock resolves mappers
26
+ * synchronously, so a frozen mapper and a working one render identically. Source
27
+ * analysis is the only automatable check; the real behaviour is verified in a
28
+ * foregrounded browser tab.
29
+ */
30
+
31
+ const SRC = join(__dirname, '..');
32
+ const ROOTS = ['tab-bar', 'progressive-blur'] as const;
33
+ const MAPPERS = [
34
+ 'useAnimatedStyle',
35
+ 'useAnimatedScrollHandler',
36
+ 'useDerivedValue',
37
+ 'useAnimatedProps',
38
+ ] as const;
39
+
40
+ /**
41
+ * Floors for the self-check, not exact counts — a new mapper or module must not
42
+ * fail this suite, but a walk that silently stops finding things must.
43
+ */
44
+ const MIN_FILES = 16;
45
+ const MIN_MAPPERS = 7;
46
+
47
+ type Offender = { location: string; mapper: string; problem: string };
48
+
49
+ /** Comments legitimately discuss mappers and show them in examples. */
50
+ function stripComments(source: string): string {
51
+ return source
52
+ .replace(/\/\*[\s\S]*?\*\//g, (block) => '\n'.repeat((block.match(/\n/g) ?? []).length))
53
+ .replace(/^[ \t]*\/\/.*$/gm, '');
54
+ }
55
+
56
+ function sourceFiles(dir: string): string[] {
57
+ return readdirSync(dir).flatMap((entry) => {
58
+ const full = join(dir, entry);
59
+ if (statSync(full).isDirectory()) {
60
+ return entry === '__tests__' ? [] : sourceFiles(full);
61
+ }
62
+ return /\.tsx?$/.test(entry) ? [full] : [];
63
+ });
64
+ }
65
+
66
+ /** Text between the parens of the call starting at `start`, paren-balanced. */
67
+ function callText(source: string, start: number): string {
68
+ const open = source.indexOf('(', start);
69
+ let depth = 0;
70
+ for (let i = open; i < source.length; i++) {
71
+ if (source[i] === '(') depth += 1;
72
+ else if (source[i] === ')') {
73
+ depth -= 1;
74
+ if (depth === 0) return source.slice(open + 1, i);
75
+ }
76
+ }
77
+ return source.slice(open + 1);
78
+ }
79
+
80
+ function analyse(): { offenders: Offender[]; files: number; calls: number } {
81
+ const offenders: Offender[] = [];
82
+ const scanned = ROOTS.flatMap((root) => sourceFiles(join(SRC, root)));
83
+ let calls = 0;
84
+
85
+ for (const file of scanned) {
86
+ const source = stripComments(readFileSync(file, 'utf8'));
87
+
88
+ for (const mapper of MAPPERS) {
89
+ // `\b` before the name so `useAnimatedStyleX` can never match.
90
+ for (const call of source.matchAll(new RegExp(`\\b${mapper}\\s*\\(`, 'g'))) {
91
+ if (call.index === undefined) continue;
92
+ calls += 1;
93
+
94
+ const text = callText(source, call.index);
95
+ const line = source.slice(0, call.index).split('\n').length;
96
+ const location = `${relative(SRC, file)}:${line}`;
97
+
98
+ // Trailing comma after the deps array is idiomatic and must parse.
99
+ const deps = [...text.matchAll(/,\s*(\[[\s\S]*?\])\s*,?\s*$/g)].pop();
100
+ if (!deps) {
101
+ offenders.push({ location, mapper, problem: 'no deps array' });
102
+ continue;
103
+ }
104
+ if ((deps[1] ?? '').replace(/\s/g, '') === '[]') {
105
+ offenders.push({ location, mapper, problem: 'empty deps array' });
106
+ }
107
+ }
108
+ }
109
+ }
110
+
111
+ return { offenders, files: scanned.length, calls };
112
+ }
113
+
114
+ const { offenders, files, calls } = analyse();
115
+
116
+ describe('tab-bar reanimated mapper dependency arrays', () => {
117
+ it('walked a plausible number of source files (guards against a broken walk)', () => {
118
+ expect(files).toBeGreaterThanOrEqual(MIN_FILES);
119
+ });
120
+
121
+ it('found a plausible number of mapper call sites (guards against a vacuous pass)', () => {
122
+ // Without this, a broken regex would make the real assertion below pass by
123
+ // finding nothing at all.
124
+ expect(calls).toBeGreaterThanOrEqual(MIN_MAPPERS);
125
+ });
126
+
127
+ it('has no mapper with a missing or empty deps array', () => {
128
+ expect(offenders.map((o) => `${o.location} ${o.mapper} — ${o.problem}`)).toEqual([]);
129
+ });
130
+ });
@@ -0,0 +1,243 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+
4
+ /**
5
+ * Structural guard for the tab bar's platform split.
6
+ *
7
+ * `@oxyhq/bloom/tab-bar` has to resolve cleanly in four places at once: Metro on
8
+ * iOS/Android (platform extensions), a web bundler (the `browser` export
9
+ * condition), a non-Metro bundler reading the published `lib/`, and a consumer's
10
+ * `tsc` (which follows the `"react-native"` source condition). Three packages
11
+ * break that the moment they appear outside a `.native` file:
12
+ * `expo-glass-effect` and `expo-symbols` are native-only, and `expo-router` /
13
+ * `react-native-screens` belong solely to the opt-in
14
+ * `@oxyhq/bloom/tab-bar/expo-router` subpath so the core bar stays usable in an
15
+ * app with no router at all.
16
+ *
17
+ * None of that is observable from a jest render — a missing `.web` retarget or a
18
+ * leaked native import fails at a consumer's BUILD, in a repo that isn't this
19
+ * one. Hence source/contract assertions.
20
+ *
21
+ * Every assertion below matches on real import/export/require STATEMENTS, never
22
+ * on bare substrings: the doc comments in these files name all four packages on
23
+ * purpose (explaining why they are absent), so `includes('expo-symbols')` would
24
+ * report a failure that is actually the documentation doing its job.
25
+ */
26
+
27
+ const SRC = join(__dirname, '..');
28
+ const REPO_ROOT = join(SRC, '..');
29
+
30
+ const read = (rel: string) => readFileSync(join(SRC, rel), 'utf8');
31
+
32
+ /** Packages that must never be reached from a neutral or web module. */
33
+ const PLATFORM_ONLY = [
34
+ 'expo-glass-effect',
35
+ 'expo-symbols',
36
+ 'expo-router',
37
+ 'react-native-screens',
38
+ ] as const;
39
+
40
+ /**
41
+ * Files resolved by a web bundler, a non-Metro bundler, or a consumer's `tsc`.
42
+ * `expo-router/index.ts` and its siblings are deliberately absent — that subpath
43
+ * is where the router packages are allowed to live.
44
+ */
45
+ const NEUTRAL_AND_WEB_FILES = [
46
+ 'tab-bar/index.ts',
47
+ 'tab-bar/index.web.tsx',
48
+ 'tab-bar/types.ts',
49
+ 'tab-bar/shared.ts',
50
+ 'tab-bar/TabBarBase.tsx',
51
+ 'tab-bar/minimize-context.tsx',
52
+ 'tab-bar/surface.tsx',
53
+ 'tab-bar/surface-solid.tsx',
54
+ 'tab-bar/surface.web.tsx',
55
+ 'tab-bar/glyph.tsx',
56
+ 'progressive-blur/index.web.tsx',
57
+ 'progressive-blur/shared.ts',
58
+ 'progressive-blur/types.ts',
59
+ ] as const;
60
+
61
+ /**
62
+ * Blank out comments so a doc comment discussing a package is not mistaken for
63
+ * an import of it. Line comments are matched only when they START the line, so
64
+ * a `//` inside a string literal (a URL) survives untouched.
65
+ */
66
+ function stripComments(source: string): string {
67
+ return source
68
+ .replace(/\/\*[\s\S]*?\*\//g, '')
69
+ .replace(/^[ \t]*\/\/.*$/gm, '');
70
+ }
71
+
72
+ /** Every module specifier the file actually imports, re-exports or requires. */
73
+ function moduleSpecifiers(source: string): string[] {
74
+ const code = stripComments(source);
75
+ const patterns = [
76
+ /\bfrom\s*['"]([^'"]+)['"]/g, // import … from 'x' / export … from 'x'
77
+ /\bimport\s*['"]([^'"]+)['"]/g, // bare side-effect import 'x'
78
+ /\brequire\(\s*['"]([^'"]+)['"]\s*\)/g,
79
+ /\bimport\(\s*['"]([^'"]+)['"]\s*\)/g,
80
+ ];
81
+ const found = new Set<string>();
82
+ for (const pattern of patterns) {
83
+ for (const match of code.matchAll(pattern)) {
84
+ if (match[1]) found.add(match[1]);
85
+ }
86
+ }
87
+ return [...found];
88
+ }
89
+
90
+ /** True when `specifier` resolves to `pkg` (bare or a subpath of it). */
91
+ function isFrom(specifier: string, pkg: string): boolean {
92
+ return specifier === pkg || specifier.startsWith(`${pkg}/`);
93
+ }
94
+
95
+ describe('tab-bar platform split', () => {
96
+ it('the extractor sees real imports and ignores commented-out ones', () => {
97
+ // Self-check: if `moduleSpecifiers` breaks, every assertion below would
98
+ // pass vacuously by finding nothing.
99
+ const probe = [
100
+ "/* a doc comment naming expo-symbols and expo-router */",
101
+ "// import { Nope } from 'react-native-screens';",
102
+ "import { A } from 'react-native';",
103
+ "export type { B } from './types';",
104
+ "const c = require('expo-glass-effect');",
105
+ ].join('\n');
106
+ expect(moduleSpecifiers(probe).sort()).toEqual([
107
+ './types',
108
+ 'expo-glass-effect',
109
+ 'react-native',
110
+ ]);
111
+ });
112
+
113
+ it.each(NEUTRAL_AND_WEB_FILES)('%s imports no native-only or router package', (file) => {
114
+ const specifiers = moduleSpecifiers(read(file));
115
+ const leaked = specifiers.filter((s) => PLATFORM_ONLY.some((pkg) => isFrom(s, pkg)));
116
+ expect(leaked).toEqual([]);
117
+ });
118
+
119
+ it('the web progressive blur drops expo-blur for one masked backdrop-filter', () => {
120
+ // Ten stacked BlurViews would be ten composited backdrop passes per frame.
121
+ expect(moduleSpecifiers(read('progressive-blur/index.web.tsx'))).not.toContain('expo-blur');
122
+ expect(moduleSpecifiers(read('progressive-blur/index.tsx'))).toContain('expo-blur');
123
+ });
124
+
125
+ it('the native surface and glyph are the ONLY holders of the native packages', () => {
126
+ // The guard above only proves absence; this proves the split is real rather
127
+ // than the feature having quietly lost its native path.
128
+ expect(moduleSpecifiers(read('tab-bar/surface.native.tsx'))).toContain('expo-glass-effect');
129
+ expect(moduleSpecifiers(read('tab-bar/glyph.native.tsx'))).toContain('expo-symbols');
130
+ });
131
+
132
+ it('the native surface takes its fallback from surface-solid, never ./surface', () => {
133
+ // Metro resolves a bare `./surface` to `surface.native.tsx` from ANY caller,
134
+ // so importing the neutral sibling by that name would be a self-import — which
135
+ // is the entire reason `surface-solid.tsx` exists as a separate name.
136
+ const specifiers = moduleSpecifiers(read('tab-bar/surface.native.tsx'));
137
+ expect(specifiers).toContain('./surface-solid');
138
+ expect(specifiers).not.toContain('./surface');
139
+ // And the neutral variant must be that same component, not a second copy.
140
+ expect(moduleSpecifiers(read('tab-bar/surface.tsx'))).toContain('./surface-solid');
141
+ });
142
+
143
+ it('the router packages live only under tab-bar/expo-router', () => {
144
+ const router = moduleSpecifiers(read('tab-bar/expo-router/RouterTabBar.tsx'));
145
+ expect(router.some((s) => isFrom(s, 'expo-router'))).toBe(true);
146
+ const screen = moduleSpecifiers(read('tab-bar/expo-router/fading-tab-screen.tsx'));
147
+ expect(screen).toContain('react-native-screens');
148
+ });
149
+
150
+ it('the default entry imports the platform pieces BY BARE NAME (Metro picks .native)', () => {
151
+ const specifiers = moduleSpecifiers(read('tab-bar/index.ts'));
152
+ expect(specifiers).toContain('./surface');
153
+ expect(specifiers).toContain('./glyph');
154
+ expect(specifiers).toContain('../progressive-blur');
155
+ // A `.web` path here would pin every platform to the web fork.
156
+ expect(specifiers).not.toContain('./surface.web');
157
+ });
158
+
159
+ it('the web entry imports the web pieces by their FULL .web name', () => {
160
+ // Inside the published `lib/` every file is plain `.js`, and no web bundler
161
+ // resolves a bare `./surface` to the `.web` sibling — only Metro does.
162
+ const specifiers = moduleSpecifiers(read('tab-bar/index.web.tsx'));
163
+ expect(specifiers).toContain('./surface.web');
164
+ expect(specifiers).toContain('../progressive-blur/index.web');
165
+ expect(specifiers).not.toContain('./surface');
166
+ // `./glyph` has no web fork: the neutral file already renders `item.icon`,
167
+ // which is the correct web behaviour.
168
+ expect(specifiers).toContain('./glyph');
169
+ });
170
+ });
171
+
172
+ describe('tab-bar published surface', () => {
173
+ const pkg = JSON.parse(readFileSync(join(REPO_ROOT, 'package.json'), 'utf8')) as {
174
+ exports: Record<string, { browser?: { import?: string; require?: string } }>;
175
+ peerDependencies: Record<string, string>;
176
+ peerDependenciesMeta: Record<string, { optional?: boolean }>;
177
+ };
178
+
179
+ it('exports ./tab-bar with a browser condition → index.web.js', () => {
180
+ const entry = pkg.exports['./tab-bar'];
181
+ expect(entry).toBeDefined();
182
+ expect(entry?.browser?.import).toBe('./lib/module/tab-bar/index.web.js');
183
+ expect(entry?.browser?.require).toBe('./lib/commonjs/tab-bar/index.web.js');
184
+ });
185
+
186
+ it('exports ./progressive-blur with a browser condition → index.web.js', () => {
187
+ expect(pkg.exports['./progressive-blur']?.browser?.import).toBe(
188
+ './lib/module/progressive-blur/index.web.js',
189
+ );
190
+ });
191
+
192
+ it('exports ./tab-bar/expo-router with NO browser condition', () => {
193
+ // The router adapter is universal — it only re-binds `TabBar`/`TabBarButton`,
194
+ // whose own entry already resolves per platform. There is no `.web` sibling,
195
+ // so a browser condition would point at a file bob never emits.
196
+ const entry = pkg.exports['./tab-bar/expo-router'];
197
+ expect(entry).toBeDefined();
198
+ expect(entry?.browser).toBeUndefined();
199
+ });
200
+
201
+ it('declares the two Apple-only native peers REQUIRED, keeping their ranges', () => {
202
+ // `expo-glass-effect` and `expo-symbols` are imported STATICALLY, by
203
+ // `tab-bar/surface.native` and `tab-bar/glyph.native`. That is what settles
204
+ // this: optional means "you may omit this", but omitting it does not degrade
205
+ // — the native bundle fails to RESOLVE the specifier and the build dies. An
206
+ // optional peer plus a static import is an incoherent pair, and the only
207
+ // thing marking them optional would achieve is silencing the one warning
208
+ // that tells a consumer their build is about to break. Declared the same way
209
+ // `expo-blur` already is, for the same reason.
210
+ //
211
+ // The RANGE carries the second half: both files import symbols that arrived
212
+ // after 1.0 — `isGlassEffectAPIAvailable` first shipped in
213
+ // expo-glass-effect 0.1.9 — so an older installed copy is a real
214
+ // incompatibility, not merely an absent one.
215
+ for (const peer of ['expo-glass-effect', 'expo-symbols']) {
216
+ expect(pkg.peerDependencies[peer]).toMatch(/^>=\d/);
217
+ expect(pkg.peerDependenciesMeta[peer]).toBeUndefined();
218
+ }
219
+ });
220
+
221
+ it('keeps the cross-platform native peers REQUIRED', () => {
222
+ // `expo-blur` and `expo-image` are apple+android native modules imported from
223
+ // platform-NEUTRAL files (`progressive-blur/index.tsx`,
224
+ // `frosted-icon-button/FrostedIconButton.tsx`, `zoomable-image-gallery/`), so
225
+ // every native platform genuinely needs them. Marking them optional would
226
+ // silence the one warning that tells a consumer their build is about to fail.
227
+ for (const peer of ['expo-blur', 'expo-image']) {
228
+ expect(pkg.peerDependencies[peer]).toBeDefined();
229
+ expect(pkg.peerDependenciesMeta[peer]).toBeUndefined();
230
+ }
231
+ });
232
+
233
+ it('the generator lists exactly the right subpaths as web-forked', () => {
234
+ const gen = readFileSync(join(REPO_ROOT, 'scripts/generate-platform-exports.mjs'), 'utf8');
235
+ const block = /const WEB_FORKED_SUBPATHS = new Set\(\[([\s\S]*?)\]\);/.exec(gen)?.[1];
236
+ expect(block).toBeDefined();
237
+ const listed = [...(block ?? '').matchAll(/^\s*'([^']+)',/gm)].map((m) => m[1]);
238
+ expect(listed).toContain('./tab-bar');
239
+ expect(listed).toContain('./progressive-blur');
240
+ // `assertWebSourceExists()` throws for this one — it has no `.web` sibling.
241
+ expect(listed).not.toContain('./tab-bar/expo-router');
242
+ });
243
+ });