@oxyhq/bloom 1.0.6 → 1.2.0

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 (220) hide show
  1. package/docs/level-picker.mdx +105 -0
  2. package/docs/media-flight.mdx +272 -0
  3. package/docs/migrating-the-media-gallery.mdx +103 -0
  4. package/docs/migrating-to-1.0.mdx +1 -1
  5. package/docs/slider.mdx +3 -1
  6. package/docs/zoomable-media-gallery.mdx +116 -0
  7. package/lib/commonjs/floating/index.js.map +1 -1
  8. package/lib/commonjs/image-aspect-ratio-cache/aspect-ratio-cache.js +1 -1
  9. package/lib/commonjs/index.js +8 -0
  10. package/lib/commonjs/index.js.map +1 -1
  11. package/lib/commonjs/index.web.js +33 -25
  12. package/lib/commonjs/index.web.js.map +1 -1
  13. package/lib/commonjs/level-picker/LevelPicker.js +349 -0
  14. package/lib/commonjs/level-picker/LevelPicker.js.map +1 -0
  15. package/lib/commonjs/level-picker/LevelPicker.web.js +346 -0
  16. package/lib/commonjs/level-picker/LevelPicker.web.js.map +1 -0
  17. package/lib/commonjs/level-picker/constants.js +137 -0
  18. package/lib/commonjs/level-picker/constants.js.map +1 -0
  19. package/lib/commonjs/level-picker/index.js +13 -0
  20. package/lib/commonjs/level-picker/index.js.map +1 -0
  21. package/lib/commonjs/level-picker/index.web.js +13 -0
  22. package/lib/commonjs/level-picker/index.web.js.map +1 -0
  23. package/lib/commonjs/level-picker/types.js +6 -0
  24. package/lib/commonjs/level-picker/types.js.map +1 -0
  25. package/lib/commonjs/media-flight/MediaFlightLayer.js +151 -0
  26. package/lib/commonjs/media-flight/MediaFlightLayer.js.map +1 -0
  27. package/lib/commonjs/media-flight/MediaSurface.js +188 -0
  28. package/lib/commonjs/media-flight/MediaSurface.js.map +1 -0
  29. package/lib/commonjs/media-flight/constants.js +39 -0
  30. package/lib/commonjs/media-flight/constants.js.map +1 -0
  31. package/lib/commonjs/media-flight/expo-video-module.js +148 -0
  32. package/lib/commonjs/media-flight/expo-video-module.js.map +1 -0
  33. package/lib/commonjs/media-flight/index.js +102 -0
  34. package/lib/commonjs/media-flight/index.js.map +1 -0
  35. package/lib/commonjs/media-flight/store.js +457 -0
  36. package/lib/commonjs/media-flight/store.js.map +1 -0
  37. package/lib/commonjs/media-flight/types.js +6 -0
  38. package/lib/commonjs/media-flight/types.js.map +1 -0
  39. package/lib/commonjs/media-flight/use-media-flight.js +41 -0
  40. package/lib/commonjs/media-flight/use-media-flight.js.map +1 -0
  41. package/lib/commonjs/tab-bar/TabBarBase.js +1 -1
  42. package/lib/commonjs/{zoomable-image-gallery/ZoomableImageGallery.js → zoomable-media-gallery/ZoomableMediaGallery.js} +185 -131
  43. package/lib/commonjs/zoomable-media-gallery/ZoomableMediaGallery.js.map +1 -0
  44. package/lib/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/constants.js.map +1 -1
  45. package/lib/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/index.js +5 -5
  46. package/lib/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/index.js.map +1 -1
  47. package/lib/commonjs/zoomable-media-gallery/types.js +6 -0
  48. package/lib/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/types.js.map +1 -1
  49. package/lib/module/floating/index.js +5 -0
  50. package/lib/module/floating/index.js.map +1 -1
  51. package/lib/module/image-aspect-ratio-cache/aspect-ratio-cache.js +1 -1
  52. package/lib/module/index.js +3 -1
  53. package/lib/module/index.js.map +1 -1
  54. package/lib/module/index.web.js +3 -1
  55. package/lib/module/index.web.js.map +1 -1
  56. package/lib/module/level-picker/LevelPicker.js +343 -0
  57. package/lib/module/level-picker/LevelPicker.js.map +1 -0
  58. package/lib/module/level-picker/LevelPicker.web.js +340 -0
  59. package/lib/module/level-picker/LevelPicker.web.js.map +1 -0
  60. package/lib/module/level-picker/constants.js +131 -0
  61. package/lib/module/level-picker/constants.js.map +1 -0
  62. package/lib/module/level-picker/index.js +4 -0
  63. package/lib/module/level-picker/index.js.map +1 -0
  64. package/lib/module/level-picker/index.web.js +4 -0
  65. package/lib/module/level-picker/index.web.js.map +1 -0
  66. package/lib/module/level-picker/types.js +4 -0
  67. package/lib/module/level-picker/types.js.map +1 -0
  68. package/lib/module/media-flight/MediaFlightLayer.js +146 -0
  69. package/lib/module/media-flight/MediaFlightLayer.js.map +1 -0
  70. package/lib/module/media-flight/MediaSurface.js +180 -0
  71. package/lib/module/media-flight/MediaSurface.js.map +1 -0
  72. package/lib/module/media-flight/constants.js +35 -0
  73. package/lib/module/media-flight/constants.js.map +1 -0
  74. package/lib/module/media-flight/expo-video-module.js +142 -0
  75. package/lib/module/media-flight/expo-video-module.js.map +1 -0
  76. package/lib/module/media-flight/index.js +9 -0
  77. package/lib/module/media-flight/index.js.map +1 -0
  78. package/lib/module/media-flight/store.js +439 -0
  79. package/lib/module/media-flight/store.js.map +1 -0
  80. package/lib/module/media-flight/types.js +4 -0
  81. package/lib/module/media-flight/types.js.map +1 -0
  82. package/lib/module/media-flight/use-media-flight.js +36 -0
  83. package/lib/module/media-flight/use-media-flight.js.map +1 -0
  84. package/lib/module/tab-bar/TabBarBase.js +1 -1
  85. package/lib/module/{zoomable-image-gallery/ZoomableImageGallery.js → zoomable-media-gallery/ZoomableMediaGallery.js} +184 -130
  86. package/lib/module/zoomable-media-gallery/ZoomableMediaGallery.js.map +1 -0
  87. package/lib/module/{zoomable-image-gallery → zoomable-media-gallery}/constants.js.map +1 -1
  88. package/lib/module/zoomable-media-gallery/index.js +5 -0
  89. package/lib/module/zoomable-media-gallery/index.js.map +1 -0
  90. package/lib/module/zoomable-media-gallery/types.js +4 -0
  91. package/lib/module/{zoomable-image-gallery → zoomable-media-gallery}/types.js.map +1 -1
  92. package/lib/typescript/commonjs/floating/index.d.ts +5 -0
  93. package/lib/typescript/commonjs/floating/index.d.ts.map +1 -1
  94. package/lib/typescript/commonjs/index.d.ts +2 -0
  95. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  96. package/lib/typescript/commonjs/index.web.d.ts +2 -0
  97. package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
  98. package/lib/typescript/commonjs/level-picker/LevelPicker.d.ts +6 -0
  99. package/lib/typescript/commonjs/level-picker/LevelPicker.d.ts.map +1 -0
  100. package/lib/typescript/commonjs/level-picker/LevelPicker.web.d.ts +6 -0
  101. package/lib/typescript/commonjs/level-picker/LevelPicker.web.d.ts.map +1 -0
  102. package/lib/typescript/commonjs/level-picker/constants.d.ts +93 -0
  103. package/lib/typescript/commonjs/level-picker/constants.d.ts.map +1 -0
  104. package/lib/typescript/commonjs/level-picker/index.d.ts +3 -0
  105. package/lib/typescript/commonjs/level-picker/index.d.ts.map +1 -0
  106. package/lib/typescript/commonjs/level-picker/index.web.d.ts +3 -0
  107. package/lib/typescript/commonjs/level-picker/index.web.d.ts.map +1 -0
  108. package/lib/typescript/commonjs/level-picker/types.d.ts +63 -0
  109. package/lib/typescript/commonjs/level-picker/types.d.ts.map +1 -0
  110. package/lib/typescript/commonjs/media-flight/MediaFlightLayer.d.ts +11 -0
  111. package/lib/typescript/commonjs/media-flight/MediaFlightLayer.d.ts.map +1 -0
  112. package/lib/typescript/commonjs/media-flight/MediaSurface.d.ts +106 -0
  113. package/lib/typescript/commonjs/media-flight/MediaSurface.d.ts.map +1 -0
  114. package/lib/typescript/commonjs/media-flight/constants.d.ts +18 -0
  115. package/lib/typescript/commonjs/media-flight/constants.d.ts.map +1 -0
  116. package/lib/typescript/commonjs/media-flight/expo-video-module.d.ts +103 -0
  117. package/lib/typescript/commonjs/media-flight/expo-video-module.d.ts.map +1 -0
  118. package/lib/typescript/commonjs/media-flight/index.d.ts +9 -0
  119. package/lib/typescript/commonjs/media-flight/index.d.ts.map +1 -0
  120. package/lib/typescript/commonjs/media-flight/store.d.ts +132 -0
  121. package/lib/typescript/commonjs/media-flight/store.d.ts.map +1 -0
  122. package/lib/typescript/commonjs/media-flight/types.d.ts +195 -0
  123. package/lib/typescript/commonjs/media-flight/types.d.ts.map +1 -0
  124. package/lib/typescript/commonjs/media-flight/use-media-flight.d.ts +4 -0
  125. package/lib/typescript/commonjs/media-flight/use-media-flight.d.ts.map +1 -0
  126. package/lib/typescript/commonjs/zoomable-media-gallery/ZoomableMediaGallery.d.ts +5 -0
  127. package/lib/typescript/commonjs/zoomable-media-gallery/ZoomableMediaGallery.d.ts.map +1 -0
  128. package/lib/typescript/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/constants.d.ts.map +1 -1
  129. package/lib/typescript/commonjs/zoomable-media-gallery/index.d.ts +4 -0
  130. package/lib/typescript/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/index.d.ts.map +1 -1
  131. package/lib/typescript/commonjs/zoomable-media-gallery/types.d.ts +90 -0
  132. package/lib/typescript/commonjs/zoomable-media-gallery/types.d.ts.map +1 -0
  133. package/lib/typescript/module/floating/index.d.ts +5 -0
  134. package/lib/typescript/module/floating/index.d.ts.map +1 -1
  135. package/lib/typescript/module/index.d.ts +2 -0
  136. package/lib/typescript/module/index.d.ts.map +1 -1
  137. package/lib/typescript/module/index.web.d.ts +2 -0
  138. package/lib/typescript/module/index.web.d.ts.map +1 -1
  139. package/lib/typescript/module/level-picker/LevelPicker.d.ts +6 -0
  140. package/lib/typescript/module/level-picker/LevelPicker.d.ts.map +1 -0
  141. package/lib/typescript/module/level-picker/LevelPicker.web.d.ts +6 -0
  142. package/lib/typescript/module/level-picker/LevelPicker.web.d.ts.map +1 -0
  143. package/lib/typescript/module/level-picker/constants.d.ts +93 -0
  144. package/lib/typescript/module/level-picker/constants.d.ts.map +1 -0
  145. package/lib/typescript/module/level-picker/index.d.ts +3 -0
  146. package/lib/typescript/module/level-picker/index.d.ts.map +1 -0
  147. package/lib/typescript/module/level-picker/index.web.d.ts +3 -0
  148. package/lib/typescript/module/level-picker/index.web.d.ts.map +1 -0
  149. package/lib/typescript/module/level-picker/types.d.ts +63 -0
  150. package/lib/typescript/module/level-picker/types.d.ts.map +1 -0
  151. package/lib/typescript/module/media-flight/MediaFlightLayer.d.ts +11 -0
  152. package/lib/typescript/module/media-flight/MediaFlightLayer.d.ts.map +1 -0
  153. package/lib/typescript/module/media-flight/MediaSurface.d.ts +106 -0
  154. package/lib/typescript/module/media-flight/MediaSurface.d.ts.map +1 -0
  155. package/lib/typescript/module/media-flight/constants.d.ts +18 -0
  156. package/lib/typescript/module/media-flight/constants.d.ts.map +1 -0
  157. package/lib/typescript/module/media-flight/expo-video-module.d.ts +103 -0
  158. package/lib/typescript/module/media-flight/expo-video-module.d.ts.map +1 -0
  159. package/lib/typescript/module/media-flight/index.d.ts +9 -0
  160. package/lib/typescript/module/media-flight/index.d.ts.map +1 -0
  161. package/lib/typescript/module/media-flight/store.d.ts +132 -0
  162. package/lib/typescript/module/media-flight/store.d.ts.map +1 -0
  163. package/lib/typescript/module/media-flight/types.d.ts +195 -0
  164. package/lib/typescript/module/media-flight/types.d.ts.map +1 -0
  165. package/lib/typescript/module/media-flight/use-media-flight.d.ts +4 -0
  166. package/lib/typescript/module/media-flight/use-media-flight.d.ts.map +1 -0
  167. package/lib/typescript/module/zoomable-media-gallery/ZoomableMediaGallery.d.ts +5 -0
  168. package/lib/typescript/module/zoomable-media-gallery/ZoomableMediaGallery.d.ts.map +1 -0
  169. package/lib/typescript/module/{zoomable-image-gallery → zoomable-media-gallery}/constants.d.ts.map +1 -1
  170. package/lib/typescript/module/zoomable-media-gallery/index.d.ts +4 -0
  171. package/lib/typescript/module/{zoomable-image-gallery → zoomable-media-gallery}/index.d.ts.map +1 -1
  172. package/lib/typescript/module/zoomable-media-gallery/types.d.ts +90 -0
  173. package/lib/typescript/module/zoomable-media-gallery/types.d.ts.map +1 -0
  174. package/package.json +61 -8
  175. package/src/floating/index.ts +5 -0
  176. package/src/image-aspect-ratio-cache/aspect-ratio-cache.ts +1 -1
  177. package/src/index.ts +4 -1
  178. package/src/index.web.ts +4 -1
  179. package/src/level-picker/LevelPicker.tsx +365 -0
  180. package/src/level-picker/LevelPicker.web.tsx +374 -0
  181. package/src/level-picker/constants.ts +131 -0
  182. package/src/level-picker/index.ts +2 -0
  183. package/src/level-picker/index.web.ts +2 -0
  184. package/src/level-picker/types.ts +63 -0
  185. package/src/media-flight/MediaFlightLayer.tsx +144 -0
  186. package/src/media-flight/MediaSurface.tsx +233 -0
  187. package/src/media-flight/constants.ts +32 -0
  188. package/src/media-flight/expo-video-module.ts +181 -0
  189. package/src/media-flight/index.ts +33 -0
  190. package/src/media-flight/store.ts +497 -0
  191. package/src/media-flight/types.ts +210 -0
  192. package/src/media-flight/use-media-flight.ts +42 -0
  193. package/src/tab-bar/TabBarBase.tsx +1 -1
  194. package/src/{zoomable-image-gallery/ZoomableImageGallery.tsx → zoomable-media-gallery/ZoomableMediaGallery.tsx} +192 -117
  195. package/src/zoomable-media-gallery/index.ts +11 -0
  196. package/src/zoomable-media-gallery/types.ts +100 -0
  197. package/docs/zoomable-image-gallery.mdx +0 -66
  198. package/lib/commonjs/zoomable-image-gallery/ZoomableImageGallery.js.map +0 -1
  199. package/lib/commonjs/zoomable-image-gallery/types.js +0 -2
  200. package/lib/module/zoomable-image-gallery/ZoomableImageGallery.js.map +0 -1
  201. package/lib/module/zoomable-image-gallery/index.js +0 -5
  202. package/lib/module/zoomable-image-gallery/index.js.map +0 -1
  203. package/lib/module/zoomable-image-gallery/types.js +0 -2
  204. package/lib/typescript/commonjs/zoomable-image-gallery/ZoomableImageGallery.d.ts +0 -5
  205. package/lib/typescript/commonjs/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +0 -1
  206. package/lib/typescript/commonjs/zoomable-image-gallery/index.d.ts +0 -4
  207. package/lib/typescript/commonjs/zoomable-image-gallery/types.d.ts +0 -56
  208. package/lib/typescript/commonjs/zoomable-image-gallery/types.d.ts.map +0 -1
  209. package/lib/typescript/module/zoomable-image-gallery/ZoomableImageGallery.d.ts +0 -5
  210. package/lib/typescript/module/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +0 -1
  211. package/lib/typescript/module/zoomable-image-gallery/index.d.ts +0 -4
  212. package/lib/typescript/module/zoomable-image-gallery/types.d.ts +0 -56
  213. package/lib/typescript/module/zoomable-image-gallery/types.d.ts.map +0 -1
  214. package/src/zoomable-image-gallery/index.ts +0 -9
  215. package/src/zoomable-image-gallery/types.ts +0 -59
  216. /package/lib/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/constants.js +0 -0
  217. /package/lib/module/{zoomable-image-gallery → zoomable-media-gallery}/constants.js +0 -0
  218. /package/lib/typescript/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/constants.d.ts +0 -0
  219. /package/lib/typescript/module/{zoomable-image-gallery → zoomable-media-gallery}/constants.d.ts +0 -0
  220. /package/src/{zoomable-image-gallery → zoomable-media-gallery}/constants.ts +0 -0
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * The layer that survives navigation.
5
+ *
6
+ * ## The problem it exists for
7
+ *
8
+ * A shared-element transition normally assumes the ORIGIN screen is still
9
+ * mounted while the element travels — which is why `react-native-teleport` needs
10
+ * `presentation: 'transparentModal'` and has no web story at all. Under
11
+ * expo-router on web the origin route is UNMOUNTED the moment the URL changes,
12
+ * so anything the origin was rendering (a `VideoView`, a decoded image) is gone
13
+ * before the first frame of the transition.
14
+ *
15
+ * The fix is to move the surface OUT of both screens for the duration of the
16
+ * flight. `<MediaFlightLayer>` is mounted ONCE at the app root and renders
17
+ * through Bloom's `Portal`, whose outlet lives above the router on both
18
+ * platforms — so the surface it paints belongs to neither route and neither
19
+ * route can take it down. Origin and destination only DECLARE where they want
20
+ * it (`registerAnchor` + `flyTo`); the layer is what actually paints it.
21
+ *
22
+ * ## One surface per id
23
+ *
24
+ * That is the contract, and for video it is the whole feature. expo-video keeps
25
+ * the `VideoPlayer` OBJECT separate from the `VideoView` that shows it, and one
26
+ * player may feed several views — so moving a video is a matter of mounting ONE
27
+ * view in the right place, never of creating a second player. A second surface
28
+ * for the same id would mean two views mounted over one another and a visible
29
+ * swap; the store enforces one by RETARGETING an existing flight rather than
30
+ * adding to it.
31
+ *
32
+ * ## It never takes a click
33
+ *
34
+ * Every node here is `pointerEvents="none"` (or `box-none` on the root, via
35
+ * `OverlayRoot`). A flying surface is a picture of something the app is already
36
+ * showing: the controls underneath it stay the ones the user is pressing, and a
37
+ * layer mounted for the whole life of the app that swallowed presses would be
38
+ * indistinguishable from a frozen UI.
39
+ */
40
+ import { useEffect, useSyncExternalStore } from 'react';
41
+ import { StyleSheet } from 'react-native';
42
+ import { interpolate, useAnimatedStyle } from 'react-native-reanimated';
43
+ import { OverlayRoot } from "../overlay/index.js";
44
+ import { Portal } from '../portal';
45
+ import { MediaSurface } from "./MediaSurface.js";
46
+ import { getFlights, notifySurfaceMounted, subscribeToFlights } from "./store.js";
47
+ import { jsx as _jsx } from "react/jsx-runtime";
48
+ /**
49
+ * Mount ONCE, at the app root, above the router. Renders nothing at all until a
50
+ * flight is live, so it costs a subscription and no view while idle — and takes
51
+ * an overlay rank only while it is actually painting, which is what keeps the
52
+ * overlay stack's counter able to reset (see `overlay/stack.ts`).
53
+ */
54
+ export function MediaFlightLayer() {
55
+ const flights = useSyncExternalStore(subscribeToFlights, getFlights, getFlights);
56
+ if (flights.length === 0) return null;
57
+ return /*#__PURE__*/_jsx(Portal, {
58
+ children: /*#__PURE__*/_jsx(OverlayRoot, {
59
+ children: flights.map(flight => /*#__PURE__*/_jsx(MediaFlightSurface, {
60
+ flight: flight
61
+ }, flight.id))
62
+ })
63
+ });
64
+ }
65
+ MediaFlightLayer.displayName = 'MediaFlightLayer';
66
+
67
+ /**
68
+ * One flying surface.
69
+ *
70
+ * ## Why the size is animated rather than scaled
71
+ *
72
+ * The media gallery flies its images with a uniform `scale`, which is right
73
+ * there: it opens from a thumbnail into a box of the SAME aspect ratio, so one
74
+ * factor describes the whole move. A flight does not have that luxury — it
75
+ * routinely goes from a cropped square tile to a 16:9 player — and a uniform
76
+ * scale would leave the first frame the wrong height, i.e. visibly not the
77
+ * thumbnail it is supposed to be replacing. Interpolating `width`/`height` is
78
+ * exact at both ends; the position still rides a transform, so the only layout
79
+ * work per frame is one absolutely-positioned node resizing.
80
+ */
81
+ function MediaFlightSurface({
82
+ flight
83
+ }) {
84
+ const {
85
+ id,
86
+ from,
87
+ to,
88
+ progress,
89
+ content,
90
+ cornerRadius,
91
+ contentFit,
92
+ surfaceType
93
+ } = flight;
94
+
95
+ // The COMMIT signal `flyTo`'s promise waits on, and the reason it is an effect
96
+ // rather than anything derived: what the caller needs to know is that React
97
+ // has actually put this surface in the tree, and an effect is the only thing
98
+ // in React that means exactly that. On web it is also the moment the
99
+ // `<video>` element joined expo-video's mounted set — which is what carries
100
+ // `currentTime` across from the origin, and what stops working the instant
101
+ // the caller navigates first.
102
+ useEffect(() => {
103
+ notifySurfaceMounted(id);
104
+ }, [id]);
105
+
106
+ // Deltas rather than absolute rects, so the worklet closes over four numbers.
107
+ const originX = from.x - to.x;
108
+ const originY = from.y - to.y;
109
+
110
+ // CRITICAL — every shared value a mapper READS must be listed in its deps.
111
+ // On web WITHOUT the react-native-worklets babel plugin, reanimated cannot
112
+ // auto-detect the reads and drives the mapper off the deps array instead:
113
+ // with none, it runs ONCE and freezes at the opening frame while `progress`
114
+ // animates underneath it. Same rule as `ZoomableMediaGallery` and
115
+ // `BottomSheetBase`. Do NOT strip these.
116
+ const boxStyle = useAnimatedStyle(() => ({
117
+ transform: [{
118
+ translateX: interpolate(progress.value, [0, 1], [originX, 0])
119
+ }, {
120
+ translateY: interpolate(progress.value, [0, 1], [originY, 0])
121
+ }],
122
+ width: interpolate(progress.value, [0, 1], [from.width, to.width]),
123
+ height: interpolate(progress.value, [0, 1], [from.height, to.height])
124
+ }), [progress, originX, originY, from.width, from.height, to.width, to.height]);
125
+ return /*#__PURE__*/_jsx(MediaSurface, {
126
+ content: content,
127
+ contentFit: contentFit,
128
+ surfaceType: surfaceType
129
+ // A flying surface is a picture, never a control: it must not intercept
130
+ // the press that is already travelling to whatever is underneath it.
131
+ ,
132
+ pointerEvents: "none",
133
+ style: [styles.box, {
134
+ left: to.x,
135
+ top: to.y,
136
+ borderRadius: cornerRadius
137
+ }, boxStyle]
138
+ });
139
+ }
140
+ const styles = StyleSheet.create({
141
+ box: {
142
+ position: 'absolute',
143
+ overflow: 'hidden'
144
+ }
145
+ });
146
+ //# sourceMappingURL=MediaFlightLayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useEffect","useSyncExternalStore","StyleSheet","interpolate","useAnimatedStyle","OverlayRoot","Portal","MediaSurface","getFlights","notifySurfaceMounted","subscribeToFlights","jsx","_jsx","MediaFlightLayer","flights","length","children","map","flight","MediaFlightSurface","id","displayName","from","to","progress","content","cornerRadius","contentFit","surfaceType","originX","x","originY","y","boxStyle","transform","translateX","value","translateY","width","height","pointerEvents","style","styles","box","left","top","borderRadius","create","position","overflow"],"sourceRoot":"../../../src","sources":["media-flight/MediaFlightLayer.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * ONE renderer for "an image or a video, painted into a box".
5
+ *
6
+ * Both the flight layer and the media gallery need exactly this, and they need
7
+ * it to be the same code: a flight that lands inside the gallery hands its
8
+ * surface over frame-for-frame, so two renderers that disagree by a pixel of
9
+ * `contentFit` or a corner radius show the swap.
10
+ *
11
+ * BOTH ARMS RENDER THE SAME BOX — an `Animated.View` with the media filling it —
12
+ * rather than the image arm rendering an animated `Image` directly. That is the
13
+ * property that makes an image and a video interchangeable at a call site: the
14
+ * caller's style means the same thing either way, the corner radius clips a
15
+ * platform video surface the way it rounds an image, and the transform lands on
16
+ * a node reanimated is allowed to drive (expo-video's own host is not one).
17
+ */
18
+ import { memo, useCallback, useState } from 'react';
19
+ import { Platform, StyleSheet, View } from 'react-native';
20
+ import { Image } from 'expo-image';
21
+ import Animated from 'react-native-reanimated';
22
+ import { handOffFlight } from "./store.js";
23
+ import { loadExpoVideo, warnExpoVideoUnavailable } from "./expo-video-module.js";
24
+
25
+ /**
26
+ * Exactly what `Animated.View` accepts, taken from the component rather than
27
+ * restated: a caller hands this component the output of `useAnimatedStyle` and a
28
+ * hand-written `StyleProp<ViewStyle>` would reject it.
29
+ */
30
+
31
+ /**
32
+ * The style a STILL accepts. The intersection is what lets one value reach both
33
+ * an `Image` and a `View`: `ViewStyle` and `ImageStyle` disagree on exactly one
34
+ * key (`overflow`, which `ViewStyle` also allows to be `'scroll'`), and the
35
+ * intersection narrows it to the two values both accept.
36
+ */
37
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
38
+ // Web-only: a media surface is never a drag source. Written as an inline
39
+ // conditional SPREAD rather than a `Platform.select` returning `undefined` —
40
+ // spreading a `T | undefined` into JSX crashes tsc 5.9 outright
41
+ // (`getIntersectionTypeFacts: type.types is not iterable`), and the gallery
42
+ // already wrote it this way for the same reason.
43
+ const webDraggableProps = Platform.OS === 'web' ? {
44
+ draggable: false
45
+ } : {};
46
+ /**
47
+ * A still image, or a video fed by a player the CONSUMER owns.
48
+ *
49
+ * The video arm mounts a `VideoView` around the caller's `player`. Bloom never
50
+ * creates, replaces or releases that player — handing one player to a new view
51
+ * is what moves a playing video between surfaces without restarting it, and it
52
+ * is the reason this component takes a player object rather than a source URL.
53
+ */
54
+ export const MediaSurface = /*#__PURE__*/memo(function MediaSurface({
55
+ content,
56
+ style,
57
+ contentFit = 'contain',
58
+ surfaceType = 'textureView',
59
+ nativeControls = false,
60
+ accessibilityLabel,
61
+ pointerEvents,
62
+ flightId
63
+ }) {
64
+ // Captured once — see `surfaceType` above. A consumer changing it later gets
65
+ // the value the view was mounted with, which is the only value expo-video
66
+ // supports.
67
+ const [mountedSurfaceType] = useState(surfaceType);
68
+
69
+ // Both arms report the same fact — "there is a picture here now" — because the
70
+ // destination of a flight can be either, and a caller should not have to know
71
+ // which one it wired. expo-video raises `onFirstFrameRender` from `loadeddata`
72
+ // on web; expo-image raises `onLoad` once the source is decoded and displayed.
73
+ const reportLive = useCallback(() => {
74
+ if (flightId !== undefined) handOffFlight(flightId);
75
+ }, [flightId]);
76
+ const still = content.kind === 'video' ? content.poster : content.uri;
77
+ // Loaded for the video arm only, and only when there is one — an image
78
+ // surface must never make an app resolve an optional native peer.
79
+ const expoVideo = content.kind === 'video' ? loadExpoVideo() : null;
80
+ if (content.kind === 'video' && expoVideo === null) {
81
+ // Degrade to the poster rather than to nothing: a black hole where a video
82
+ // should be reads as a broken app, a still frame reads as a video that has
83
+ // not started. The warning is what makes the difference visible to the
84
+ // developer, once, in dev.
85
+ warnExpoVideoUnavailable();
86
+ }
87
+ return /*#__PURE__*/_jsxs(Animated.View, {
88
+ style: [styles.box, style],
89
+ pointerEvents: pointerEvents,
90
+ children: [still === undefined ? null :
91
+ /*#__PURE__*/
92
+ // Behind the video (and the whole picture on the image arm), so the box
93
+ // is never empty while a first frame decodes and a flight that starts
94
+ // before playback still carries a picture. This is also why a flight
95
+ // never has to wait for a decode: an unpainted `<video>` sets no
96
+ // `poster` attribute and an Android TextureView runs with the ExoPlayer
97
+ // shutter off, so neither draws anything opaque over this.
98
+ _jsx(Image, {
99
+ source: {
100
+ uri: still
101
+ },
102
+ contentFit: contentFit,
103
+ style: StyleSheet.absoluteFill,
104
+ transition: 0,
105
+ accessibilityLabel: accessibilityLabel
106
+ // Only the arm that IS the picture reports being live. On the video
107
+ // arm the poster is scenery: handing off on it would release the
108
+ // flying surface while the destination still had no video.
109
+ ,
110
+ onLoad: content.kind === 'video' ? undefined : reportLive,
111
+ ...webDraggableProps
112
+ }), content.kind === 'video' && expoVideo !== null ? /*#__PURE__*/_jsx(expoVideo.VideoView, {
113
+ player: content.player,
114
+ contentFit: contentFit,
115
+ surfaceType: mountedSurfaceType,
116
+ nativeControls: nativeControls,
117
+ style: StyleSheet.absoluteFill,
118
+ accessibilityLabel: accessibilityLabel,
119
+ onFirstFrameRender: reportLive
120
+ }) : null]
121
+ });
122
+ });
123
+ MediaSurface.displayName = 'MediaSurface';
124
+
125
+ /**
126
+ * The STILL of a media item — a video's poster, or the image itself — and never
127
+ * a video view.
128
+ *
129
+ * This is what every surface that is not the live one renders: an off-screen
130
+ * gallery page, a thumbnail-strip tile, an origin placeholder while its media is
131
+ * in flight. Mounting a `MediaSurface` there instead would put a second
132
+ * `VideoView` on the same player, which is precisely what the "one live surface
133
+ * per id" contract forbids — and on a thumbnail strip it would mean one decoder
134
+ * per tile.
135
+ */
136
+ export function MediaPoster({
137
+ content,
138
+ style,
139
+ contentFit = 'cover',
140
+ accessibilityLabel
141
+ }) {
142
+ const uri = content.kind === 'video' ? content.poster : content.uri;
143
+ if (uri === undefined) return /*#__PURE__*/_jsx(EmptyMediaSurface, {
144
+ style: style
145
+ });
146
+ return /*#__PURE__*/_jsx(Image, {
147
+ source: {
148
+ uri
149
+ },
150
+ contentFit: contentFit,
151
+ style: style,
152
+ transition: 0,
153
+ accessibilityLabel: accessibilityLabel,
154
+ ...webDraggableProps
155
+ });
156
+ }
157
+
158
+ /**
159
+ * A box with no media at all — what a gallery page renders for a video item
160
+ * whose poster is unknown, so the layout never collapses.
161
+ */
162
+ export function EmptyMediaSurface({
163
+ style
164
+ }) {
165
+ return /*#__PURE__*/_jsx(View, {
166
+ style: [styles.empty, style],
167
+ pointerEvents: "none"
168
+ });
169
+ }
170
+ const styles = StyleSheet.create({
171
+ box: {
172
+ // What makes the box's corner radius actually clip a video, and the other
173
+ // half of why the Android surface has to be a `textureView`.
174
+ overflow: 'hidden'
175
+ },
176
+ empty: {
177
+ backgroundColor: 'rgba(255,255,255,0.08)'
178
+ }
179
+ });
180
+ //# sourceMappingURL=MediaSurface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["memo","useCallback","useState","Platform","StyleSheet","View","Image","Animated","handOffFlight","loadExpoVideo","warnExpoVideoUnavailable","jsx","_jsx","jsxs","_jsxs","webDraggableProps","OS","draggable","MediaSurface","content","style","contentFit","surfaceType","nativeControls","accessibilityLabel","pointerEvents","flightId","mountedSurfaceType","reportLive","undefined","still","kind","poster","uri","expoVideo","styles","box","children","source","absoluteFill","transition","onLoad","VideoView","player","onFirstFrameRender","displayName","MediaPoster","EmptyMediaSurface","empty","create","overflow","backgroundColor"],"sourceRoot":"../../../src","sources":["media-flight/MediaSurface.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * How long `flyTo` will wait for `<MediaFlightLayer>` to commit the surface
5
+ * before letting the caller carry on regardless (ms).
6
+ *
7
+ * The wait is a COMMIT, not a network round-trip: the surface only has to be
8
+ * mounted, because that is what puts it in expo-video's `_mountedVideos` set
9
+ * while the origin is still there — which is the whole mechanism that carries
10
+ * `currentTime` across. One React commit is a frame or two. Painting is a
11
+ * separate, slower thing that the poster covers (see `MediaSurface`), so it is
12
+ * deliberately NOT waited on here: blocking a tap on a decode would trade a
13
+ * problem nobody can see for one everybody can feel.
14
+ *
15
+ * The timeout exists for the case where no layer is mounted at all. Without it
16
+ * the promise never settles and the consumer never navigates — an app that
17
+ * forgot one line at its root would appear to have a dead feed.
18
+ */
19
+ export const SURFACE_MOUNT_TIMEOUT_MS = 250;
20
+
21
+ /*
22
+ * There is deliberately NO hand-off timeout.
23
+ *
24
+ * The obvious one — release the flying surface after N seconds if no destination
25
+ * ever claims it — would have to be wrong in one direction or the other, because
26
+ * the layer cannot tell "the destination failed" from "the caller meant the
27
+ * layer to keep painting this". And the failure it would guard against is not
28
+ * actually bad: a destination that never loads leaves the flying surface
29
+ * showing the video, playing, at exactly the rect the destination wanted, over a
30
+ * destination showing its poster. Going back calls `flyBack`, which releases it.
31
+ *
32
+ * `flyBack(id)` and `releaseFlight(id)` are the escape hatches, and they are
33
+ * the caller's to use.
34
+ */
35
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["SURFACE_MOUNT_TIMEOUT_MS"],"sourceRoot":"../../../src","sources":["media-flight/constants.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,wBAAwB,GAAG,GAAG;;AAE3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","ignoreList":[]}
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * The optional-peer boundary for `expo-video`.
5
+ *
6
+ * Bloom ships no native code and never will, so `expo-video` cannot be a hard
7
+ * dependency: an app that renders no video must not be made to install a native
8
+ * module. It is therefore an OPTIONAL peer, and a static `import` contradicts
9
+ * that — Metro resolves every static import in the eager graph, so an omitted
10
+ * "optional" peer does not degrade, it aborts the whole bundle with `Unable to
11
+ * resolve module expo-video`, naming a package the app never mentions.
12
+ *
13
+ * The load has to be dynamic in the ONE shape Metro understands: a `require()`
14
+ * of a STRING LITERAL as a DIRECT STATEMENT of a `try` block, which Metro
15
+ * collects as an optional dependency (resolving the real module when installed,
16
+ * writing `null` into the dependency map when it is not, so the failure lands in
17
+ * the `catch` below at evaluation time instead of at build time). One `if` of
18
+ * nesting loses that — `isOptionalDependency` returns at the FIRST BlockStatement
19
+ * it meets — hence the `typeof require` guard sits OUTSIDE the try.
20
+ *
21
+ * `require` may also not exist at all (this file backs the `import` condition
22
+ * too, i.e. an ESM build under Node), hence that guard.
23
+ *
24
+ * A missing video module is invisible — a poster where a video should be looks
25
+ * exactly like a video that has not started — so {@link warnExpoVideoUnavailable}
26
+ * names the package once, in dev.
27
+ *
28
+ * @see connection-status/netinfo.ts — the same boundary for netinfo.
29
+ * @see hooks/haptics-module.ts — the same boundary for expo-haptics.
30
+ */
31
+
32
+ /**
33
+ * Declared locally rather than taken from the ambient `NodeRequire`, which
34
+ * returns `any`: `unknown` forces the module handle to be narrowed below instead
35
+ * of leaking an untyped value into the caller.
36
+ */
37
+
38
+ /**
39
+ * The slice of `expo-video`'s `VideoPlayer` Bloom depends on.
40
+ *
41
+ * Hand-written rather than `typeof import('expo-video')` so no expo-video type
42
+ * reaches Bloom's emitted declarations — a consumer that skips the optional peer
43
+ * must not inherit a TS7016 from Bloom's own `.d.ts`. The two are kept in step by
44
+ * the assignability check in `__tests__/MediaFlight.test.tsx`, which is excluded
45
+ * from the build and so may name the real package.
46
+ *
47
+ * Bloom never CALLS any of this. **The consumer creates the player, owns it and
48
+ * destroys it**; Bloom only hands the object back to a `VideoView`, which is the
49
+ * whole mechanism that lets a video move between surfaces without restarting
50
+ * (expo-video's own docs: "when the same player is playing in multiple video
51
+ * views"). The three members below exist so the type is not `object` — a
52
+ * structural minimum the real `VideoPlayer` satisfies, and that an arbitrary
53
+ * object does not.
54
+ *
55
+ * `play`/`pause` are declared in METHOD syntax deliberately: `strictFunctionTypes`
56
+ * exempts method parameters from contravariance, which keeps a real
57
+ * `VideoPlayer` assignable here across `@types/react` copies.
58
+ */
59
+
60
+ /** How a video is scaled inside its box. Mirrors expo-video's `VideoContentFit`. */
61
+
62
+ /**
63
+ * Android's rendering surface for a video view.
64
+ *
65
+ * `textureView` is what Bloom asks for everywhere, because a `SurfaceView` is
66
+ * composited by the system OUTSIDE the app's view hierarchy: it ignores the
67
+ * parent's clip, corner radius and transform, so a video flying between two
68
+ * rects would paint as an un-rounded rectangle at the wrong place. It also
69
+ * cannot be changed at runtime (expo-video: "This prop should not be changed at
70
+ * runtime"), which is why {@link MediaSurfaceProps.surfaceType} is captured on
71
+ * first render.
72
+ */
73
+
74
+ /** The slice of `VideoViewProps` Bloom passes. */
75
+
76
+ /** The slice of expo-video's module surface Bloom renders. */
77
+
78
+ /** `undefined` until the first load attempt, then the module or `null`. */
79
+ let videoModule;
80
+ /** Why the load failed, quoted verbatim in the dev warning. */
81
+ let unavailableReason = '';
82
+ let hasWarned = false;
83
+
84
+ /** The expo-video module, or `null` when the optional peer is not installed. */
85
+ export function loadExpoVideo() {
86
+ if (videoModule !== undefined) return videoModule;
87
+ videoModule = null;
88
+
89
+ // The `typeof require` guard sits OUTSIDE the try on purpose — see the header.
90
+ // Nested one `if`/`else` deeper, the require below is no longer a direct
91
+ // statement of the try block, Metro stops marking it optional, and an app
92
+ // without expo-video fails to BUILD instead of losing the video surface.
93
+ if (typeof require === 'undefined') {
94
+ unavailableReason = 'this bundle has no CommonJS `require`';
95
+ return videoModule;
96
+ }
97
+ try {
98
+ const loaded = require('expo-video');
99
+ // `VideoView` is a class component upstream, so `typeof` is `'function'`
100
+ // either way; a memo/forwardRef build would be an object carrying
101
+ // `$$typeof`. Both are accepted, nothing else is.
102
+ const resolved = isComponentBearing(loaded) ? loaded : loaded?.default;
103
+ if (isComponentBearing(resolved)) {
104
+ videoModule = {
105
+ VideoView: resolved.VideoView
106
+ };
107
+ } else {
108
+ unavailableReason = 'the module resolved without a `VideoView` export';
109
+ }
110
+ } catch (error) {
111
+ unavailableReason = error instanceof Error ? error.message : String(error);
112
+ }
113
+ return videoModule;
114
+ }
115
+ function isComponentBearing(candidate) {
116
+ const view = candidate?.VideoView;
117
+ if (typeof view === 'function') return true;
118
+ return typeof view === 'object' && view !== null && '$$typeof' in view;
119
+ }
120
+
121
+ /**
122
+ * One warning per module lifetime, and none in production — the same mechanism
123
+ * as `connection-status/netinfo.ts` and `hooks/haptics-module.ts`. Metro and
124
+ * Vite/Rolldown both fold the `NODE_ENV` check statically, so a production
125
+ * bundle keeps neither the branch nor the message.
126
+ */
127
+ export function warnExpoVideoUnavailable() {
128
+ if (process.env.NODE_ENV === 'production' || hasWarned) return;
129
+ hasWarned = true;
130
+ // Internal Bloom diagnostic: only the consumer's package.json can fix this,
131
+ // so it names the package, the install command and what is lost.
132
+ // eslint-disable-next-line no-console
133
+ console.warn('[Bloom] A video media surface fell back to its poster: the optional peer ' + '`expo-video` could not be loaded, so no video is rendered and the shared ' + 'media transition carries a still frame instead. Install it ' + '(`npx expo install expo-video`) or pass image content only. ' + `Reason: ${unavailableReason}`);
134
+ }
135
+
136
+ /** Test seam — drops the cached module handle so a suite can load it again. */
137
+ export function resetExpoVideoModule() {
138
+ videoModule = undefined;
139
+ unavailableReason = '';
140
+ hasWarned = false;
141
+ }
142
+ //# sourceMappingURL=expo-video-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["videoModule","unavailableReason","hasWarned","loadExpoVideo","undefined","require","loaded","resolved","isComponentBearing","default","VideoView","error","Error","message","String","candidate","view","warnExpoVideoUnavailable","process","env","NODE_ENV","console","warn","resetExpoVideoModule"],"sourceRoot":"../../../src","sources":["media-flight/expo-video-module.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAOA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;;AAkBA;;AAKA;AACA,IAAIA,WAA6C;AACjD;AACA,IAAIC,iBAAiB,GAAG,EAAE;AAC1B,IAAIC,SAAS,GAAG,KAAK;;AAErB;AACA,OAAO,SAASC,aAAaA,CAAA,EAAyB;EACpD,IAAIH,WAAW,KAAKI,SAAS,EAAE,OAAOJ,WAAW;EACjDA,WAAW,GAAG,IAAI;;EAElB;EACA;EACA;EACA;EACA,IAAI,OAAOK,OAAO,KAAK,WAAW,EAAE;IAClCJ,iBAAiB,GAAG,uCAAuC;IAC3D,OAAOD,WAAW;EACpB;EAEA,IAAI;IACF,MAAMM,MAAM,GAAGD,OAAO,CAAC,YAAY,CAGtB;IACb;IACA;IACA;IACA,MAAME,QAAQ,GAAGC,kBAAkB,CAACF,MAAM,CAAC,GAAGA,MAAM,GAAGA,MAAM,EAAEG,OAAO;IAEtE,IAAID,kBAAkB,CAACD,QAAQ,CAAC,EAAE;MAChCP,WAAW,GAAG;QAAEU,SAAS,EAAEH,QAAQ,CAACG;MAA+C,CAAC;IACtF,CAAC,MAAM;MACLT,iBAAiB,GAAG,kDAAkD;IACxE;EACF,CAAC,CAAC,OAAOU,KAAK,EAAE;IACdV,iBAAiB,GAAGU,KAAK,YAAYC,KAAK,GAAGD,KAAK,CAACE,OAAO,GAAGC,MAAM,CAACH,KAAK,CAAC;EAC5E;EAEA,OAAOX,WAAW;AACpB;AAEA,SAASQ,kBAAkBA,CACzBO,SAA8E,EACU;EACxF,MAAMC,IAAI,GAAGD,SAAS,EAAEL,SAAS;EACjC,IAAI,OAAOM,IAAI,KAAK,UAAU,EAAE,OAAO,IAAI;EAC3C,OAAO,OAAOA,IAAI,KAAK,QAAQ,IAAIA,IAAI,KAAK,IAAI,IAAI,UAAU,IAAIA,IAAI;AACxE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,wBAAwBA,CAAA,EAAS;EAC/C,IAAIC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,IAAIlB,SAAS,EAAE;EACxDA,SAAS,GAAG,IAAI;EAChB;EACA;EACA;EACAmB,OAAO,CAACC,IAAI,CACV,2EAA2E,GACzE,2EAA2E,GAC3E,6DAA6D,GAC7D,8DAA8D,GAC9D,WAAWrB,iBAAiB,EAChC,CAAC;AACH;;AAEA;AACA,OAAO,SAASsB,oBAAoBA,CAAA,EAAS;EAC3CvB,WAAW,GAAGI,SAAS;EACvBH,iBAAiB,GAAG,EAAE;EACtBC,SAAS,GAAG,KAAK;AACnB","ignoreList":[]}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ export { MediaFlightLayer } from "./MediaFlightLayer.js";
4
+ export { MediaSurface, MediaPoster, EmptyMediaSurface } from "./MediaSurface.js";
5
+ export { useMediaFlight } from "./use-media-flight.js";
6
+ export { DEFAULT_FLIGHT_CORNER_RADIUS, flightProgress, handOffFlight, hasFlight, releaseFlight, resetMediaFlight } from "./store.js";
7
+ export { SURFACE_MOUNT_TIMEOUT_MS } from "./constants.js";
8
+ export { loadExpoVideo, warnExpoVideoUnavailable, resetExpoVideoModule } from "./expo-video-module.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["MediaFlightLayer","MediaSurface","MediaPoster","EmptyMediaSurface","useMediaFlight","DEFAULT_FLIGHT_CORNER_RADIUS","flightProgress","handOffFlight","hasFlight","releaseFlight","resetMediaFlight","SURFACE_MOUNT_TIMEOUT_MS","loadExpoVideo","warnExpoVideoUnavailable","resetExpoVideoModule"],"sourceRoot":"../../../src","sources":["media-flight/index.ts"],"mappings":";;AAAA,SAASA,gBAAgB,QAAQ,uBAAoB;AACrD,SAASC,YAAY,EAAEC,WAAW,EAAEC,iBAAiB,QAAQ,mBAAgB;AAC7E,SAASC,cAAc,QAAQ,uBAAoB;AACnD,SACEC,4BAA4B,EAC5BC,cAAc,EACdC,aAAa,EACbC,SAAS,EACTC,aAAa,EACbC,gBAAgB,QACX,YAAS;AAChB,SAASC,wBAAwB,QAAQ,gBAAa;AACtD,SACEC,aAAa,EACbC,wBAAwB,EACxBC,oBAAoB,QAMf,wBAAqB","ignoreList":[]}