@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,517 @@
1
+ /**
2
+ * Ported from expo-glass-tabs v0.1.1 — src/glass-tab-bar.tsx
3
+ * (MIT © 2026 David Mokos). See the top-level NOTICE.
4
+ *
5
+ * The platform-agnostic body of the floating tab bar: gestures, springs, every
6
+ * animated style, the highlight geometry and the button. The only pieces that
7
+ * differ per platform are injected as component props — the capsule `Surface`
8
+ * (liquid glass on iOS 26, backdrop-filter on web, a solid fill everywhere
9
+ * else), the `Blur` behind the bar, and the `Glyph` (SF Symbol on iOS, the
10
+ * item's own icon node elsewhere). Same shape as `BottomSheetBase`'s `Shell`.
11
+ *
12
+ * Nothing here imports expo-glass-effect, expo-symbols, expo-router or
13
+ * react-native-screens, so this file is safe in a web bundle and in a
14
+ * consumer's type-check.
15
+ */
16
+ import {
17
+ Children,
18
+ createContext,
19
+ useCallback,
20
+ useContext,
21
+ useEffect,
22
+ useMemo,
23
+ type ComponentType,
24
+ } from 'react';
25
+ import { Pressable, StyleSheet, useWindowDimensions, View } from 'react-native';
26
+ import { Gesture, GestureDetector } from 'react-native-gesture-handler';
27
+ import Animated, {
28
+ Extrapolation,
29
+ interpolate,
30
+ interpolateColor,
31
+ runOnJS,
32
+ useAnimatedStyle,
33
+ useSharedValue,
34
+ withSpring,
35
+ type SharedValue,
36
+ } from 'react-native-reanimated';
37
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
38
+
39
+ import { useHaptics } from '../hooks/useHaptics';
40
+ import type { ProgressiveBlurProps } from '../progressive-blur/types';
41
+ import { setMinimized, useMinimizeState } from './minimize-context';
42
+ import {
43
+ BAR_MARGIN,
44
+ BLUR_BLEED,
45
+ EXPANDED_HEIGHT,
46
+ HIGHLIGHT_EXPANDED,
47
+ HIGHLIGHT_MINIMIZED,
48
+ ICON_SIZE,
49
+ ITEM_GAP,
50
+ ITEM_PAD_V,
51
+ LABEL_FONT_SIZE,
52
+ MINIMIZED_HEIGHT,
53
+ MINIMIZED_INSET,
54
+ ROW_PAD_H,
55
+ SLIDE_SPRING,
56
+ useTabBarTheme,
57
+ type TabBarGlyphProps,
58
+ type TabBarSurfaceProps,
59
+ } from './shared';
60
+ import type { TabBarButtonProps, TabBarProps, TabBarTheme } from './types';
61
+
62
+ /**
63
+ * What a `TabBarButton` needs from the bar it sits in. `null` when a button is
64
+ * rendered standalone, which keeps a lone button usable (it just falls back to
65
+ * its own `isFocused` for tinting and has no highlight to drive).
66
+ */
67
+ type BarContextValue = {
68
+ /** Live highlight position, in tab units. Fractional while scrubbing. */
69
+ slideIndex: SharedValue<number>;
70
+ /** True while a scrub is in progress — the finger owns the highlight. */
71
+ isDragging: SharedValue<boolean>;
72
+ theme: TabBarTheme;
73
+ /** Set only on the CONTROLLED path (see `TabBarProps.activeIndex`). */
74
+ activeIndex: number | undefined;
75
+ /** Report a selection made by a button press. */
76
+ selectIndex: (index: number) => void;
77
+ };
78
+
79
+ const BarContext = createContext<BarContextValue | null>(null);
80
+
81
+ interface TabBarBodyProps extends TabBarProps {
82
+ Surface: ComponentType<TabBarSurfaceProps>;
83
+ Blur: ComponentType<ProgressiveBlurProps>;
84
+ }
85
+
86
+ /**
87
+ * Floating tab bar with Revolut-style minimize-on-scroll, a sliding highlight
88
+ * and finger scrubbing.
89
+ */
90
+ function TabBarBody({
91
+ Surface,
92
+ Blur,
93
+ children,
94
+ activeIndex,
95
+ onIndexChange,
96
+ theme: themeOverrides,
97
+ haptics = true,
98
+ style,
99
+ ...viewProps
100
+ }: TabBarBodyProps) {
101
+ const insets = useSafeAreaInsets();
102
+ const { width: windowWidth } = useWindowDimensions();
103
+ const minimized = useMinimizeState();
104
+ const progress = minimized.progress;
105
+ const slideIndex = useSharedValue(0);
106
+ const isDragging = useSharedValue(false);
107
+ const lastTicked = useSharedValue(-1);
108
+ const tabCount = Math.max(Children.count(children), 1);
109
+ const theme = useTabBarTheme(themeOverrides);
110
+ const impact = useHaptics();
111
+
112
+ // Picker-style tick while the highlight crosses tab boundaries mid-drag.
113
+ // `useHaptics` already no-ops on web, when the optional `expo-haptics` peer
114
+ // is absent, and when a `BloomHapticsProvider` has haptics turned off — so
115
+ // the only decision left here is the caller's own `haptics` prop.
116
+ const tick = useCallback(() => {
117
+ if (haptics) impact('light');
118
+ }, [haptics, impact]);
119
+
120
+ // Navigation happens only on release — switching screens live while
121
+ // scrubbing makes the content jump under the finger.
122
+ const selectIndex = useCallback((index: number) => onIndexChange?.(index), [onIndexChange]);
123
+
124
+ // CONTROLLED path: the bar owns the highlight when `activeIndex` is provided,
125
+ // so it tracks the prop even when a consumer renders custom children instead
126
+ // of `TabBarButton`s. Syncing an imperative animation to a controlled prop is
127
+ // a legitimate effect (external-system sync), the same shape `Tabs` uses for
128
+ // its underline. The focus-driven path is handled per-button instead — see
129
+ // `TabBarButtonBody`.
130
+ useEffect(() => {
131
+ if (activeIndex === undefined) return;
132
+ // While scrubbing the finger owns the highlight; never fight it.
133
+ if (isDragging.value) return;
134
+ slideIndex.value = withSpring(activeIndex, SLIDE_SPRING);
135
+ }, [activeIndex, slideIndex, isDragging]);
136
+
137
+ // Scrubbing: the highlight tracks the finger 1:1 while dragging (no spring —
138
+ // it must feel attached), haptic ticks fire on boundary crossings, and
139
+ // navigation happens only on release. Taps are handled by a Tap gesture
140
+ // racing the pan — the detector consumes the bar's touches, so the inner
141
+ // Pressables never receive them.
142
+ const gesture = useMemo(() => {
143
+ const indexAtX = (x: number, minimizedValue: number) => {
144
+ 'worklet';
145
+ const sideInset = interpolate(
146
+ minimizedValue,
147
+ [0, 1],
148
+ [0, MINIMIZED_INSET],
149
+ Extrapolation.CLAMP,
150
+ );
151
+ const barWidth = windowWidth - BAR_MARGIN * 2 - sideInset * 2;
152
+ const itemWidth = (barWidth - ROW_PAD_H * 2) / tabCount;
153
+ const raw = (x - ROW_PAD_H) / itemWidth - 0.5;
154
+ return Math.min(Math.max(raw, 0), tabCount - 1);
155
+ };
156
+
157
+ const pan = Gesture.Pan()
158
+ .activeOffsetX([-6, 6])
159
+ .failOffsetY([-14, 14])
160
+ .onStart(() => {
161
+ isDragging.value = true;
162
+ lastTicked.value = Math.round(slideIndex.value);
163
+ // Scrubbing is a deliberate bar interaction — surface the labels.
164
+ setMinimized(minimized, 0);
165
+ })
166
+ .onUpdate((event) => {
167
+ const index = indexAtX(event.x, progress.value);
168
+ slideIndex.value = index;
169
+
170
+ const rounded = Math.round(index);
171
+ if (rounded !== lastTicked.value) {
172
+ lastTicked.value = rounded;
173
+ runOnJS(tick)();
174
+ }
175
+ })
176
+ .onFinalize(() => {
177
+ // Fires on failure too (e.g. the touch was a tap) — only act when the
178
+ // pan actually activated, or we'd stomp the tap's navigation.
179
+ if (!isDragging.value) {
180
+ return;
181
+ }
182
+ const rounded = Math.round(slideIndex.value);
183
+ slideIndex.value = withSpring(rounded, SLIDE_SPRING);
184
+ runOnJS(selectIndex)(rounded);
185
+ isDragging.value = false;
186
+ });
187
+
188
+ const tap = Gesture.Tap()
189
+ // Real fingers drift a few points — the default tolerance (~2pt) makes
190
+ // ordinary taps fail. Past 6pt horizontal the pan takes over.
191
+ .maxDistance(16)
192
+ .maxDuration(400)
193
+ .onEnd((event, success) => {
194
+ if (!success) {
195
+ return;
196
+ }
197
+ const index = Math.round(indexAtX(event.x, progress.value));
198
+ slideIndex.value = withSpring(index, SLIDE_SPRING);
199
+ setMinimized(minimized, 0);
200
+ runOnJS(selectIndex)(index);
201
+ });
202
+
203
+ return Gesture.Race(pan, tap);
204
+ }, [
205
+ windowWidth,
206
+ tabCount,
207
+ selectIndex,
208
+ tick,
209
+ isDragging,
210
+ lastTicked,
211
+ slideIndex,
212
+ minimized,
213
+ progress,
214
+ ]);
215
+
216
+ // CRITICAL — every shared value and every scalar a mapper READS must appear
217
+ // in its dependency array. On web WITHOUT the react-native-worklets babel
218
+ // plugin (what every Oxy RN-Web app ships) reanimated cannot auto-detect a
219
+ // worklet's reads, so it drives the mapper off the deps array instead: with a
220
+ // missing or incomplete array the mapper runs ONCE and freezes at the first
221
+ // frame while the shared values keep animating underneath — the bar would
222
+ // never minimize and the highlight would never move, with no error anywhere.
223
+ // Native (plugin present) auto-tracks and ignores the extra deps, so listing
224
+ // them is correct on both platforms. Same rule as `BottomSheetBase` and
225
+ // `ZoomableImageGallery`. Do NOT strip these.
226
+ const barStyle = useAnimatedStyle(() => {
227
+ const height = interpolate(
228
+ progress.value,
229
+ [0, 1],
230
+ [EXPANDED_HEIGHT, MINIMIZED_HEIGHT],
231
+ Extrapolation.CLAMP,
232
+ );
233
+ return {
234
+ height,
235
+ // Revolut-style: the pill shrinks in both dimensions.
236
+ marginHorizontal: interpolate(
237
+ progress.value,
238
+ [0, 1],
239
+ [0, MINIMIZED_INSET],
240
+ Extrapolation.CLAMP,
241
+ ),
242
+ };
243
+ }, [progress]);
244
+
245
+ // The capsule shape lives on the surface itself: iOS 26 glass renders its own
246
+ // native corner configuration (true squircle + rim lighting). Clipping a
247
+ // rectangular glass with an RN mask breaks that.
248
+ const shapeStyle = useAnimatedStyle(() => {
249
+ const height = interpolate(
250
+ progress.value,
251
+ [0, 1],
252
+ [EXPANDED_HEIGHT, MINIMIZED_HEIGHT],
253
+ Extrapolation.CLAMP,
254
+ );
255
+ return { borderRadius: height / 2 };
256
+ }, [progress]);
257
+
258
+ // One shared highlight that slides between tabs (transform-only → GPU). All
259
+ // geometry derives from shared values, never from layout callbacks.
260
+ const highlightStyle = useAnimatedStyle(() => {
261
+ const barHeight = interpolate(
262
+ progress.value,
263
+ [0, 1],
264
+ [EXPANDED_HEIGHT, MINIMIZED_HEIGHT],
265
+ Extrapolation.CLAMP,
266
+ );
267
+ const height = interpolate(
268
+ progress.value,
269
+ [0, 1],
270
+ [HIGHLIGHT_EXPANDED, HIGHLIGHT_MINIMIZED],
271
+ Extrapolation.CLAMP,
272
+ );
273
+ const sideInset = interpolate(
274
+ progress.value,
275
+ [0, 1],
276
+ [0, MINIMIZED_INSET],
277
+ Extrapolation.CLAMP,
278
+ );
279
+ const barWidth = windowWidth - BAR_MARGIN * 2 - sideInset * 2;
280
+ const itemWidth = (barWidth - ROW_PAD_H * 2) / tabCount;
281
+ return {
282
+ height,
283
+ width: itemWidth,
284
+ borderRadius: height / 2,
285
+ top: (barHeight - height) / 2,
286
+ transform: [{ translateX: ROW_PAD_H + itemWidth * slideIndex.value }],
287
+ };
288
+ }, [progress, slideIndex, windowWidth, tabCount]);
289
+
290
+ const bottomOffset = Math.max(insets.bottom - 16, 12);
291
+ const barContext = useMemo(
292
+ () => ({ slideIndex, isDragging, theme, activeIndex, selectIndex }),
293
+ [slideIndex, isDragging, theme, activeIndex, selectIndex],
294
+ );
295
+
296
+ return (
297
+ <View {...viewProps} style={[styles.root, style]}>
298
+ {/* Progressive blur rising from the screen's bottom edge behind the pill. */}
299
+ <Blur
300
+ direction="bottom"
301
+ style={{
302
+ position: 'absolute',
303
+ left: 0,
304
+ right: 0,
305
+ bottom: 0,
306
+ height: bottomOffset + EXPANDED_HEIGHT + BLUR_BLEED,
307
+ }}
308
+ />
309
+ <View style={[styles.barWrap, { marginBottom: bottomOffset }]}>
310
+ <GestureDetector gesture={gesture}>
311
+ <Animated.View style={barStyle}>
312
+ <Surface theme={theme} style={shapeStyle} />
313
+ <Animated.View
314
+ style={[styles.highlight, { backgroundColor: theme.highlight }, highlightStyle]}
315
+ />
316
+ <View accessibilityRole="tablist" style={styles.itemRow}>
317
+ <BarContext.Provider value={barContext}>{children}</BarContext.Provider>
318
+ </View>
319
+ </Animated.View>
320
+ </GestureDetector>
321
+ </View>
322
+ </View>
323
+ );
324
+ }
325
+
326
+ interface TabBarButtonBodyProps extends TabBarButtonProps {
327
+ Glyph: ComponentType<TabBarGlyphProps>;
328
+ }
329
+
330
+ /** One tab trigger: icon + label that fades out when the bar minimizes. */
331
+ function TabBarButtonBody({
332
+ Glyph,
333
+ item,
334
+ index,
335
+ isFocused,
336
+ onPress,
337
+ style,
338
+ ...pressableProps
339
+ }: TabBarButtonBodyProps) {
340
+ const minimized = useMinimizeState();
341
+ const progress = minimized.progress;
342
+ const bar = useContext(BarContext);
343
+ // Resolved outside the bar too, so a standalone button still themes itself.
344
+ const standaloneTheme = useTabBarTheme();
345
+ const theme = bar?.theme ?? standaloneTheme;
346
+ const slideIndex = bar?.slideIndex;
347
+ // The two paths meet here: an explicit `isFocused` (router adapter) wins;
348
+ // otherwise focus comes from the bar's controlled `activeIndex`.
349
+ const focused = isFocused ?? (bar?.activeIndex === index);
350
+
351
+ // FOCUS-DRIVEN path only. Covers programmatic navigation too (deep links,
352
+ // back gestures) — the trigger re-renders focused and the highlight follows.
353
+ // While scrubbing, the finger owns the highlight; never fight it with a
354
+ // spring. On the controlled path the BAR drives the highlight instead, so
355
+ // this stays out of the way to avoid two writers on one shared value.
356
+ useEffect(() => {
357
+ if (isFocused === undefined || !isFocused || !bar) return;
358
+ if (bar.isDragging.value) return;
359
+ bar.slideIndex.value = withSpring(index, SLIDE_SPRING);
360
+ }, [isFocused, index, bar]);
361
+
362
+ // Tint follows the sliding highlight, not navigation focus: whatever the pill
363
+ // is over lights up — live while scrubbing, traveling on taps. Without a bar
364
+ // there is nothing to follow, so it falls back to plain focus.
365
+ // (Deps: see the CRITICAL note in `TabBarBody`.)
366
+ const activeGlyphStyle = useAnimatedStyle(
367
+ () => ({
368
+ opacity: slideIndex ? 1 - Math.min(Math.abs(slideIndex.value - index), 1) : focused ? 1 : 0,
369
+ }),
370
+ [slideIndex, index, focused],
371
+ );
372
+
373
+ const labelStyle = useAnimatedStyle(
374
+ () => ({
375
+ opacity: interpolate(progress.value, [0, 0.4], [1, 0], Extrapolation.CLAMP),
376
+ color: slideIndex
377
+ ? interpolateColor(
378
+ Math.min(Math.abs(slideIndex.value - index), 1),
379
+ [0, 1],
380
+ [theme.activeTint, theme.inactiveTint],
381
+ )
382
+ : focused
383
+ ? theme.activeTint
384
+ : theme.inactiveTint,
385
+ }),
386
+ [progress, slideIndex, index, focused, theme],
387
+ );
388
+
389
+ // Height is animated EXPLICITLY (not derived from children) so the icon stays
390
+ // perfectly centered every frame — layout-driven sizing lags a frame behind
391
+ // UI-thread animation.
392
+ const boxStyle = useAnimatedStyle(
393
+ () => ({
394
+ height: interpolate(
395
+ progress.value,
396
+ [0, 1],
397
+ [HIGHLIGHT_EXPANDED, HIGHLIGHT_MINIMIZED],
398
+ Extrapolation.CLAMP,
399
+ ),
400
+ }),
401
+ [progress],
402
+ );
403
+
404
+ return (
405
+ <Pressable
406
+ // Accessibility defaults come BEFORE the spread so an explicit prop — or
407
+ // one injected by a router trigger — still wins.
408
+ accessibilityRole="tab"
409
+ accessibilityState={{ selected: focused }}
410
+ accessibilityLabel={item.label}
411
+ {...pressableProps}
412
+ onPress={(event) => {
413
+ // The bar's GestureDetector normally consumes touches; this still fires
414
+ // for assistive-technology activation (VoiceOver) and keyboard focus.
415
+ if (bar) bar.slideIndex.value = withSpring(index, SLIDE_SPRING);
416
+ setMinimized(minimized, 0);
417
+ // Controlled path only. On the focus-driven path the trigger's own
418
+ // `onPress` below performs the navigation, so reporting the selection
419
+ // here as well would navigate twice.
420
+ if (isFocused === undefined) bar?.selectIndex(index);
421
+ onPress?.(event);
422
+ }}
423
+ // `Pressable`'s `style` also accepts a function of the press state; both
424
+ // forms are composed on top of the flex-share base so a caller can tint
425
+ // or scale a tab on press without losing the layout.
426
+ style={
427
+ typeof style === 'function'
428
+ ? (state) => [styles.button, style(state)]
429
+ : [styles.button, style]
430
+ }
431
+ >
432
+ <Animated.View style={[styles.itemBox, boxStyle]}>
433
+ {/* Inactive glyph underneath, active glyph crossfading on top. */}
434
+ <View>
435
+ <Glyph item={item} tint={theme.inactiveTint} size={ICON_SIZE} />
436
+ <Animated.View style={[StyleSheet.absoluteFill, styles.glyphLayer, activeGlyphStyle]}>
437
+ <Glyph item={item} tint={theme.activeTint} size={ICON_SIZE} />
438
+ </Animated.View>
439
+ </View>
440
+ {/* Fades out and is clipped by the shrinking box — no layout anim. */}
441
+ <Animated.Text numberOfLines={1} style={[styles.label, labelStyle]}>
442
+ {item.label}
443
+ </Animated.Text>
444
+ </Animated.View>
445
+ </Pressable>
446
+ );
447
+ }
448
+
449
+ /**
450
+ * Bind the platform `Surface` + `Blur` to the shared body, once per entry
451
+ * module. The returned component is created at module scope, so its identity is
452
+ * stable across renders. `index.ts` binds the native/neutral pieces and
453
+ * `index.web.tsx` binds the web pieces explicitly — the same split
454
+ * `BottomSheet` makes with its `Shell`.
455
+ */
456
+ export function createTabBar(
457
+ Surface: ComponentType<TabBarSurfaceProps>,
458
+ Blur: ComponentType<ProgressiveBlurProps>,
459
+ ) {
460
+ const TabBar = (props: TabBarProps) => <TabBarBody {...props} Surface={Surface} Blur={Blur} />;
461
+ TabBar.displayName = 'TabBar';
462
+ return TabBar;
463
+ }
464
+
465
+ /** Bind the platform `Glyph` to the shared button body. See `createTabBar`. */
466
+ export function createTabBarButton(Glyph: ComponentType<TabBarGlyphProps>) {
467
+ const TabBarButton = (props: TabBarButtonProps) => <TabBarButtonBody {...props} Glyph={Glyph} />;
468
+ TabBarButton.displayName = 'TabBarButton';
469
+ return TabBarButton;
470
+ }
471
+
472
+ const styles = StyleSheet.create({
473
+ root: {
474
+ position: 'absolute',
475
+ left: 0,
476
+ right: 0,
477
+ bottom: 0,
478
+ // In the style object, not as a prop: RN-Web deprecated the `pointerEvents`
479
+ // prop and warns on every render when it is used.
480
+ pointerEvents: 'box-none',
481
+ },
482
+ barWrap: {
483
+ marginHorizontal: BAR_MARGIN,
484
+ pointerEvents: 'box-none',
485
+ },
486
+ highlight: {
487
+ position: 'absolute',
488
+ left: 0,
489
+ borderCurve: 'continuous',
490
+ },
491
+ itemRow: {
492
+ flex: 1,
493
+ flexDirection: 'row',
494
+ alignItems: 'center',
495
+ paddingHorizontal: ROW_PAD_H,
496
+ },
497
+ button: {
498
+ flex: 1,
499
+ alignItems: 'center',
500
+ justifyContent: 'center',
501
+ },
502
+ itemBox: {
503
+ alignSelf: 'stretch',
504
+ alignItems: 'center',
505
+ paddingTop: ITEM_PAD_V,
506
+ overflow: 'hidden',
507
+ },
508
+ glyphLayer: {
509
+ alignItems: 'center',
510
+ justifyContent: 'center',
511
+ },
512
+ label: {
513
+ fontSize: LABEL_FONT_SIZE,
514
+ fontWeight: '600',
515
+ marginTop: ITEM_GAP,
516
+ },
517
+ });
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Ported from expo-glass-tabs v0.1.1 — src/glass-tab-bar.tsx
3
+ * (MIT © 2026 David Mokos). See the top-level NOTICE.
4
+ *
5
+ * expo-router bindings for the tab bar. This subpath
6
+ * (`@oxyhq/bloom/tab-bar/expo-router`) is the ONLY place in Bloom that may
7
+ * import `expo-router` or `react-native-screens`, which is why it is a separate
8
+ * entry: the core `@oxyhq/bloom/tab-bar` stays usable in an app with no router
9
+ * at all, and neither optional peer is pulled into a bundle that never asks for
10
+ * it.
11
+ */
12
+ import type { TabListProps, TabTriggerSlotProps } from 'expo-router/ui';
13
+
14
+ import { TabBar, TabBarButton } from '../index';
15
+ import type { TabBarItem, TabBarProps } from '../types';
16
+
17
+ /**
18
+ * `activeIndex` is omitted deliberately: with a router the highlight is driven
19
+ * by each trigger's own focus (see `RouterTabBarButton`), which is what keeps it
20
+ * correct through deep links, back gestures and any other programmatic
21
+ * navigation. Setting both would put two writers on one shared value.
22
+ */
23
+ export type RouterTabBarProps = TabListProps & Omit<TabBarProps, 'activeIndex'>;
24
+
25
+ export type RouterTabBarButtonProps = TabTriggerSlotProps & {
26
+ item: TabBarItem;
27
+ /** Position in the bar — must match the trigger's order in the `TabList`. */
28
+ index: number;
29
+ };
30
+
31
+ /**
32
+ * The bar, as expo-router's `<TabList asChild>` child.
33
+ *
34
+ * Navigation happens through `onIndexChange`, not through the triggers: the
35
+ * bar's gesture detector consumes the touches (that is what makes scrubbing
36
+ * possible), so a tap never reaches the trigger's own `Pressable`.
37
+ *
38
+ * ```tsx
39
+ * <TabList asChild>
40
+ * <RouterTabBar onIndexChange={(i) => router.navigate(TABS[i].href)}>
41
+ * {TABS.map(({ href, ...item }, index) => (
42
+ * <TabTrigger key={item.name} name={item.name} href={href} asChild>
43
+ * <RouterTabBarButton item={item} index={index} />
44
+ * </TabTrigger>
45
+ * ))}
46
+ * </RouterTabBar>
47
+ * </TabList>
48
+ * ```
49
+ */
50
+ export function RouterTabBar({
51
+ // `asChild` is `TabList`'s own instruction to forward its props to this
52
+ // component instead of wrapping them in a `<View>`. It is consumed there and
53
+ // is meaningless below, so it is dropped rather than passed to a real view.
54
+ asChild: _asChild,
55
+ ...props
56
+ }: RouterTabBarProps) {
57
+ return <TabBar {...props} />;
58
+ }
59
+
60
+ RouterTabBar.displayName = 'RouterTabBar';
61
+
62
+ /**
63
+ * One trigger, as expo-router's `<TabTrigger asChild>` child. The trigger
64
+ * supplies `isFocused` and `onPress`; the button uses the first to drive the
65
+ * highlight and the second to navigate on keyboard / assistive-technology
66
+ * activation.
67
+ */
68
+ export function RouterTabBarButton({
69
+ item,
70
+ index,
71
+ // The trigger's resolved path, injected for react-native-web's anchor
72
+ // rendering. `Pressable` has no such prop, and navigation already runs
73
+ // through the bar's `onIndexChange`, so it stops here.
74
+ href: _href,
75
+ ...props
76
+ }: RouterTabBarButtonProps) {
77
+ return <TabBarButton {...props} item={item} index={index} />;
78
+ }
79
+
80
+ RouterTabBarButton.displayName = 'RouterTabBarButton';
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Ported from expo-glass-tabs v0.1.1 — src/fading-tab-slot.tsx
3
+ * (MIT © 2026 David Mokos). See the top-level NOTICE.
4
+ */
5
+ import { useEffect, useRef, type PropsWithChildren } from 'react';
6
+ import { StyleSheet } from 'react-native';
7
+ import Animated, {
8
+ Easing,
9
+ interpolate,
10
+ useAnimatedStyle,
11
+ useSharedValue,
12
+ withTiming,
13
+ } from 'react-native-reanimated';
14
+ import { Screen } from 'react-native-screens';
15
+ import type { TabsDescriptor, TabsSlotRenderOptions } from 'expo-router/ui';
16
+
17
+ /** Strong ease-out — entering content should feel instant, then settle. */
18
+ const EASE_OUT = Easing.bezier(0.23, 1, 0.32, 1);
19
+ const ENTER_DURATION = 220;
20
+ /** Never enter from nothing: a whisper of depth, no zoom. */
21
+ const ENTER_SCALE = 0.985;
22
+
23
+ function FadeIn({ focused, children }: PropsWithChildren<{ focused: boolean }>) {
24
+ const progress = useSharedValue(1);
25
+ const isFirstRender = useRef(true);
26
+
27
+ useEffect(() => {
28
+ // Don't animate the very first screen on app launch.
29
+ if (isFirstRender.current) {
30
+ isFirstRender.current = false;
31
+ return;
32
+ }
33
+ if (focused) {
34
+ progress.value = 0;
35
+ progress.value = withTiming(1, { duration: ENTER_DURATION, easing: EASE_OUT });
36
+ } else {
37
+ // Outgoing screen hides instantly (display: none) — only entries animate.
38
+ progress.value = 0;
39
+ }
40
+ }, [focused, progress]);
41
+
42
+ // `progress` must stay in the deps array — see the CRITICAL note in
43
+ // `TabBarBase`: without the worklets babel plugin (web) an omitted array
44
+ // freezes the mapper at the first frame, and every tab would enter invisible.
45
+ const style = useAnimatedStyle(
46
+ () => ({
47
+ opacity: progress.value,
48
+ transform: [{ scale: interpolate(progress.value, [0, 1], [ENTER_SCALE, 1]) }],
49
+ }),
50
+ [progress],
51
+ );
52
+
53
+ return <Animated.View style={[styles.fade, style]}>{children}</Animated.View>;
54
+ }
55
+
56
+ /**
57
+ * Drop-in for `TabSlot`'s `renderFn`: identical to expo-router's default render,
58
+ * plus a subtle fade + micro-scale on the screen becoming focused.
59
+ *
60
+ * ```tsx
61
+ * <TabSlot style={{ height: '100%' }} renderFn={renderFadingTabScreen} />
62
+ * ```
63
+ */
64
+ export function renderFadingTabScreen(
65
+ descriptor: TabsDescriptor,
66
+ { isFocused, loaded, detachInactiveScreens }: TabsSlotRenderOptions,
67
+ ) {
68
+ const { lazy = true, unmountOnBlur, freezeOnBlur } = descriptor.options;
69
+ if (unmountOnBlur && !isFocused) {
70
+ return null;
71
+ }
72
+ if (lazy && !loaded && !isFocused) {
73
+ return null;
74
+ }
75
+ return (
76
+ <Screen
77
+ key={descriptor.route.key}
78
+ enabled={detachInactiveScreens}
79
+ activityState={isFocused ? 2 : 0}
80
+ freezeOnBlur={freezeOnBlur}
81
+ style={[styles.screen, isFocused ? styles.focused : styles.unfocused]}
82
+ >
83
+ <FadeIn focused={isFocused}>{descriptor.render()}</FadeIn>
84
+ </Screen>
85
+ );
86
+ }
87
+
88
+ const styles = StyleSheet.create({
89
+ fade: {
90
+ flex: 1,
91
+ },
92
+ screen: {
93
+ flex: 1,
94
+ position: 'relative',
95
+ height: '100%',
96
+ },
97
+ focused: {
98
+ zIndex: 1,
99
+ display: 'flex',
100
+ flexShrink: 0,
101
+ flexGrow: 1,
102
+ },
103
+ unfocused: {
104
+ zIndex: -1,
105
+ display: 'none',
106
+ flexShrink: 1,
107
+ flexGrow: 0,
108
+ },
109
+ });