@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,103 @@
1
+ /**
2
+ * The optional-peer boundary for `expo-video`.
3
+ *
4
+ * Bloom ships no native code and never will, so `expo-video` cannot be a hard
5
+ * dependency: an app that renders no video must not be made to install a native
6
+ * module. It is therefore an OPTIONAL peer, and a static `import` contradicts
7
+ * that — Metro resolves every static import in the eager graph, so an omitted
8
+ * "optional" peer does not degrade, it aborts the whole bundle with `Unable to
9
+ * resolve module expo-video`, naming a package the app never mentions.
10
+ *
11
+ * The load has to be dynamic in the ONE shape Metro understands: a `require()`
12
+ * of a STRING LITERAL as a DIRECT STATEMENT of a `try` block, which Metro
13
+ * collects as an optional dependency (resolving the real module when installed,
14
+ * writing `null` into the dependency map when it is not, so the failure lands in
15
+ * the `catch` below at evaluation time instead of at build time). One `if` of
16
+ * nesting loses that — `isOptionalDependency` returns at the FIRST BlockStatement
17
+ * it meets — hence the `typeof require` guard sits OUTSIDE the try.
18
+ *
19
+ * `require` may also not exist at all (this file backs the `import` condition
20
+ * too, i.e. an ESM build under Node), hence that guard.
21
+ *
22
+ * A missing video module is invisible — a poster where a video should be looks
23
+ * exactly like a video that has not started — so {@link warnExpoVideoUnavailable}
24
+ * names the package once, in dev.
25
+ *
26
+ * @see connection-status/netinfo.ts — the same boundary for netinfo.
27
+ * @see hooks/haptics-module.ts — the same boundary for expo-haptics.
28
+ */
29
+ import type { ComponentType } from 'react';
30
+ import type { StyleProp, ViewStyle } from 'react-native';
31
+ /**
32
+ * The slice of `expo-video`'s `VideoPlayer` Bloom depends on.
33
+ *
34
+ * Hand-written rather than `typeof import('expo-video')` so no expo-video type
35
+ * reaches Bloom's emitted declarations — a consumer that skips the optional peer
36
+ * must not inherit a TS7016 from Bloom's own `.d.ts`. The two are kept in step by
37
+ * the assignability check in `__tests__/MediaFlight.test.tsx`, which is excluded
38
+ * from the build and so may name the real package.
39
+ *
40
+ * Bloom never CALLS any of this. **The consumer creates the player, owns it and
41
+ * destroys it**; Bloom only hands the object back to a `VideoView`, which is the
42
+ * whole mechanism that lets a video move between surfaces without restarting
43
+ * (expo-video's own docs: "when the same player is playing in multiple video
44
+ * views"). The three members below exist so the type is not `object` — a
45
+ * structural minimum the real `VideoPlayer` satisfies, and that an arbitrary
46
+ * object does not.
47
+ *
48
+ * `play`/`pause` are declared in METHOD syntax deliberately: `strictFunctionTypes`
49
+ * exempts method parameters from contravariance, which keeps a real
50
+ * `VideoPlayer` assignable here across `@types/react` copies.
51
+ */
52
+ export interface VideoPlayerLike {
53
+ readonly playing: boolean;
54
+ play(): void;
55
+ pause(): void;
56
+ }
57
+ /** How a video is scaled inside its box. Mirrors expo-video's `VideoContentFit`. */
58
+ export type VideoSurfaceContentFit = 'contain' | 'cover' | 'fill';
59
+ /**
60
+ * Android's rendering surface for a video view.
61
+ *
62
+ * `textureView` is what Bloom asks for everywhere, because a `SurfaceView` is
63
+ * composited by the system OUTSIDE the app's view hierarchy: it ignores the
64
+ * parent's clip, corner radius and transform, so a video flying between two
65
+ * rects would paint as an un-rounded rectangle at the wrong place. It also
66
+ * cannot be changed at runtime (expo-video: "This prop should not be changed at
67
+ * runtime"), which is why {@link MediaSurfaceProps.surfaceType} is captured on
68
+ * first render.
69
+ */
70
+ export type VideoSurfaceType = 'textureView' | 'surfaceView';
71
+ /** The slice of `VideoViewProps` Bloom passes. */
72
+ export interface VideoViewLikeProps {
73
+ player?: VideoPlayerLike | null;
74
+ contentFit?: VideoSurfaceContentFit;
75
+ surfaceType?: VideoSurfaceType;
76
+ nativeControls?: boolean;
77
+ style?: StyleProp<ViewStyle>;
78
+ pointerEvents?: 'auto' | 'none' | 'box-none' | 'box-only';
79
+ accessibilityLabel?: string;
80
+ /**
81
+ * Raised once the mounted player has rendered its first frame into this view.
82
+ * On web expo-video raises it from the element's `loadeddata` event; it is the
83
+ * only OBSERVABLE "this surface is live now" the package offers, and the media
84
+ * flight layer's hand-off depends on it rather than on a timer.
85
+ */
86
+ onFirstFrameRender?: () => void;
87
+ }
88
+ /** The slice of expo-video's module surface Bloom renders. */
89
+ export interface ExpoVideoLike {
90
+ VideoView: ComponentType<VideoViewLikeProps>;
91
+ }
92
+ /** The expo-video module, or `null` when the optional peer is not installed. */
93
+ export declare function loadExpoVideo(): ExpoVideoLike | null;
94
+ /**
95
+ * One warning per module lifetime, and none in production — the same mechanism
96
+ * as `connection-status/netinfo.ts` and `hooks/haptics-module.ts`. Metro and
97
+ * Vite/Rolldown both fold the `NODE_ENV` check statically, so a production
98
+ * bundle keeps neither the branch nor the message.
99
+ */
100
+ export declare function warnExpoVideoUnavailable(): void;
101
+ /** Test seam — drops the cached module handle so a suite can load it again. */
102
+ export declare function resetExpoVideoModule(): void;
103
+ //# sourceMappingURL=expo-video-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expo-video-module.d.ts","sourceRoot":"","sources":["../../../../src/media-flight/expo-video-module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AASzD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,IAAI,IAAI,IAAI,CAAC;IACb,KAAK,IAAI,IAAI,CAAC;CACf;AAED,oFAAoF;AACpF,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAElE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,aAAa,CAAC;AAE7D,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,sBAAsB,CAAC;IACpC,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,CAAC;IAC1D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;CACjC;AAED,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CAC9C;AAQD,gFAAgF;AAChF,wBAAgB,aAAa,IAAI,aAAa,GAAG,IAAI,CAiCpD;AAUD;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAa/C;AAED,+EAA+E;AAC/E,wBAAgB,oBAAoB,IAAI,IAAI,CAI3C"}
@@ -0,0 +1,9 @@
1
+ export { MediaFlightLayer } from './MediaFlightLayer';
2
+ export { MediaSurface, MediaPoster, EmptyMediaSurface } from './MediaSurface';
3
+ export { useMediaFlight } from './use-media-flight';
4
+ export { DEFAULT_FLIGHT_CORNER_RADIUS, flightProgress, handOffFlight, hasFlight, releaseFlight, resetMediaFlight, } from './store';
5
+ export { SURFACE_MOUNT_TIMEOUT_MS } from './constants';
6
+ export { loadExpoVideo, warnExpoVideoUnavailable, resetExpoVideoModule, type ExpoVideoLike, type VideoPlayerLike, type VideoSurfaceContentFit, type VideoSurfaceType, type VideoViewLikeProps, } from './expo-video-module';
7
+ export type { MediaFlight, MediaFlightAnchorNode, MediaFlightController, MediaFlightOptions, MediaSurfaceContent, MediaSurfaceImage, MediaSurfaceVideo, MeasuredRect, } from './types';
8
+ export type { MediaSurfaceProps } from './MediaSurface';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/media-flight/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EACL,4BAA4B,EAC5B,cAAc,EACd,aAAa,EACb,SAAS,EACT,aAAa,EACb,gBAAgB,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACL,aAAa,EACb,wBAAwB,EACxB,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,132 @@
1
+ import { type SharedValue } from 'react-native-reanimated';
2
+ import type { MediaFlight, MediaFlightAnchorNode, MediaFlightOptions, MediaSurfaceContent, MeasuredRect } from './types';
3
+ /**
4
+ * Default corner radius of a flying box — Bloom's `radius-12`, the same value
5
+ * the media gallery fits its media at, so a flight that lands in the gallery
6
+ * lands on an identical shape.
7
+ */
8
+ export declare const DEFAULT_FLIGHT_CORNER_RADIUS: 12;
9
+ /**
10
+ * Bookkeeping the layer does not RENDER, kept out of the `MediaFlight` record
11
+ * on purpose.
12
+ *
13
+ * The record is replaced on every visual change so its identity tells React the
14
+ * leg moved; folding these flags into it would churn that identity on events
15
+ * nobody paints, and folding the record into these would put mutable state back
16
+ * in a rendered position. They are separate because they answer to different
17
+ * consumers.
18
+ */
19
+ interface FlightStatus {
20
+ /** The layer has committed a surface for this id. */
21
+ mounted: boolean;
22
+ /** The current leg's animation has finished. */
23
+ settled: boolean;
24
+ /** A destination surface has reported that it is live. */
25
+ handedOff: boolean;
26
+ /** Waiters on `flyTo`'s promise, resolved once `mounted` turns true. */
27
+ mountWaiters: Array<() => void>;
28
+ mountTimer: ReturnType<typeof setTimeout> | null;
29
+ }
30
+ interface Registry {
31
+ anchors: Map<string, MediaFlightAnchorNode>;
32
+ flights: Map<string, MediaFlight>;
33
+ status: Map<string, FlightStatus>;
34
+ listeners: Set<() => void>;
35
+ /**
36
+ * The array handed to `useSyncExternalStore`. Cached because that hook
37
+ * compares snapshots by IDENTITY: rebuilding it per call renders the layer
38
+ * forever (and React throws "getSnapshot should be cached" in development).
39
+ */
40
+ snapshot: readonly MediaFlight[];
41
+ progress: SharedValue<number>;
42
+ }
43
+ declare global {
44
+ var __oxyhq_bloom_media_flight__: Registry | undefined;
45
+ }
46
+ /** Subscribe to the live-surface set. The layer's `useSyncExternalStore` half. */
47
+ export declare function subscribeToFlights(listener: () => void): () => void;
48
+ /** The live surfaces, oldest first. Stable identity between changes. */
49
+ export declare function getFlights(): readonly MediaFlight[];
50
+ /** The shared progress value of the most recent leg. */
51
+ export declare function flightProgress(): SharedValue<number>;
52
+ /**
53
+ * Register (or clear) the node that anchors `id`.
54
+ *
55
+ * A `Map` re-insertion moves the key to the end, which is what makes "the most
56
+ * recently registered node is the anchor" true even when an origin screen's
57
+ * callback ref fires again after the destination has registered.
58
+ */
59
+ export declare function registerAnchor(id: string, node: MediaFlightAnchorNode | null): void;
60
+ export declare function measureAnchor(id: string): Promise<MeasuredRect | null>;
61
+ /** Whether a surface is currently live for `id`. */
62
+ export declare function hasFlight(id: string): boolean;
63
+ /**
64
+ * Take the surface for `id` live (if it is not already) and move it to `rect`.
65
+ *
66
+ * Retargeting mid-flight keeps the SAME `MediaFlight` record — and therefore the
67
+ * same mounted `VideoView` — which is the whole point. A second record would be
68
+ * a second surface for one id, and swapping between them is exactly the remount
69
+ * that restarts playback.
70
+ *
71
+ * ## Why it returns a promise, and what the promise means
72
+ *
73
+ * It resolves once the layer has COMMITTED a surface for this id — not once
74
+ * that surface has painted.
75
+ *
76
+ * The distinction is the whole ordering contract. expo-video's web player keeps
77
+ * a `Set` of mounted `<video>` elements and, on each mount, copies
78
+ * `currentTime`, play state, volume, muted and rate from `[...set][0]`. If the
79
+ * set is EMPTY when the new element mounts, it returns early and the element
80
+ * starts at zero — a restart. So the layer's surface has to enter that set while
81
+ * the origin's is still in it, which means the caller must not tear the origin
82
+ * down (on web: must not navigate) until this promise resolves.
83
+ *
84
+ * That knowledge lives here rather than in the caller, which is the point: a
85
+ * consumer that has to know the mount order is a consumer that will get it wrong
86
+ * once and produce an intermittent restart nobody can reproduce locally.
87
+ *
88
+ * Painting is deliberately NOT waited on. `MediaSurface` renders the poster
89
+ * BEHIND the video on both platforms, and neither an unpainted `<video>` (no
90
+ * `poster` attribute is set) nor an Android `TextureView` with the ExoPlayer
91
+ * shutter off draws anything opaque — so the still shows through until the first
92
+ * frame lands, and there is no black box to hide. Waiting for a decode would
93
+ * trade an invisible problem for a laggy tap.
94
+ */
95
+ export declare function flyTo(id: string, rect: MeasuredRect, content: MediaSurfaceContent, options?: MediaFlightOptions): Promise<void>;
96
+ /**
97
+ * The layer calls this from the surface's mount effect. It is the commit signal
98
+ * `flyTo` waits on, and the only thing that makes the ordering contract above
99
+ * true rather than hopeful.
100
+ */
101
+ export declare function notifySurfaceMounted(id: string): void;
102
+ /** The layer calls this when a leg's animation finishes. */
103
+ export declare function notifySurfaceSettled(id: string): void;
104
+ /**
105
+ * A destination surface reporting that it is LIVE — it has presented a frame of
106
+ * its own, so the flying copy is now redundant and can go.
107
+ *
108
+ * This is the release condition, and it is deliberately not the animation's
109
+ * clock. Measured against production, a fullscreen video route needs ~1 s from
110
+ * tap to first presented frame; releasing when a ~300 ms animation ends would
111
+ * leave ~700 ms with nothing live on screen — the hole the transition exists to
112
+ * cover, made longer.
113
+ *
114
+ * Wire it by giving the destination's `<MediaSurface>` a `flightId`; it calls
115
+ * this itself on its first frame. A destination that renders something other
116
+ * than a Bloom surface can call it directly.
117
+ */
118
+ export declare function handOffFlight(id: string): void;
119
+ /**
120
+ * Aim the live surface at its anchor and release it once it lands.
121
+ *
122
+ * With no measurable anchor there is nothing to fly to, so the surface is
123
+ * released immediately — whoever owns the media renders its own copy again at
124
+ * that point, and holding a flying copy over it would double the video.
125
+ */
126
+ export declare function flyBack(id: string): void;
127
+ /** Drop the surface for `id`. Called when a landing leg settles, and on teardown. */
128
+ export declare function releaseFlight(id: string): void;
129
+ /** Test seam — drops every anchor and surface. */
130
+ export declare function resetMediaFlight(): void;
131
+ export {};
132
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/media-flight/store.ts"],"names":[],"mappings":"AA2BA,OAAO,EAML,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAUjC,OAAO,KAAK,EACV,WAAW,EACX,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,IAAsB,CAAC;AAEhE;;;;;;;;;GASG;AACH,UAAU,YAAY;IACpB,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,wEAAwE;IACxE,YAAY,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAChC,UAAU,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC;CAClD;AAED,UAAU,QAAQ;IAChB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC5C,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAClC,SAAS,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IACjC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,4BAA4B,EAAE,QAAQ,GAAG,SAAS,CAAC;CACxD;AAsDD,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAMnE;AAED,wEAAwE;AACxE,wBAAgB,UAAU,IAAI,SAAS,WAAW,EAAE,CAEnD;AAED,wDAAwD;AACxD,wBAAgB,cAAc,IAAI,WAAW,CAAC,MAAM,CAAC,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,GAAG,IAAI,GAAG,IAAI,CAInF;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAWtE;AAED,oDAAoD;AACpD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,KAAK,CACnB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,mBAAmB,EAC5B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,IAAI,CAAC,CA0Df;AAuBD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAIrD;AAED,4DAA4D;AAC5D,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAIrD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAQ9C;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAyBxC;AAED,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAY9C;AAED,kDAAkD;AAClD,wBAAgB,gBAAgB,IAAI,IAAI,CAOvC"}
@@ -0,0 +1,195 @@
1
+ import type { SharedValue } from 'react-native-reanimated';
2
+ import type { VideoPlayerLike, VideoSurfaceType } from './expo-video-module';
3
+ /**
4
+ * On-screen rectangle of a media anchor, in WINDOW coordinates (what
5
+ * `measureInWindow` reports). Bloom-owned so consumers don't depend on an
6
+ * app-local shape.
7
+ */
8
+ export interface MeasuredRect {
9
+ x: number;
10
+ y: number;
11
+ width: number;
12
+ height: number;
13
+ }
14
+ /**
15
+ * Anything that can report its own window rect. This is exactly react-native's
16
+ * `View` instance shape (and react-native-web's), narrowed to the one method
17
+ * the flight layer calls — so a consumer passes its host node straight through
18
+ * without Bloom naming `View` in its public API.
19
+ */
20
+ export interface MediaFlightAnchorNode {
21
+ measureInWindow(callback: (x: number, y: number, width: number, height: number) => void): void;
22
+ }
23
+ /** A still image painted into a media surface. */
24
+ export interface MediaSurfaceImage {
25
+ /**
26
+ * Present so the union discriminates. Optional on the image arm so an image
27
+ * literal stays `{ uri }` — the shape every existing gallery caller writes.
28
+ */
29
+ kind?: 'image';
30
+ /** Source URI rendered as the image. */
31
+ uri: string;
32
+ }
33
+ /**
34
+ * A video painted into a media surface.
35
+ *
36
+ * **Bloom neither creates nor destroys the player.** The consumer owns it (via
37
+ * expo-video's `useVideoPlayer`, a store, whatever it likes) and hands the same
38
+ * object to every surface that should show that video. That is the entire
39
+ * mechanism behind "the video does not restart": expo-video separates the
40
+ * `VideoPlayer` OBJECT from the `VideoView` that displays it, and one player may
41
+ * feed several views. Swapping which view is mounted therefore moves the picture
42
+ * without touching playback — whereas re-creating the player would seek back to
43
+ * zero and re-open the network stream.
44
+ */
45
+ export interface MediaSurfaceVideo {
46
+ kind: 'video';
47
+ /** The expo-video `VideoPlayer` the CONSUMER created and owns. */
48
+ player: VideoPlayerLike;
49
+ /**
50
+ * Still frame shown behind the video surface. It is what the user sees before
51
+ * the first video frame renders, and the only thing rendered at all when the
52
+ * optional `expo-video` peer is absent.
53
+ */
54
+ poster?: string;
55
+ }
56
+ /** What a media surface paints: a still image, or a consumer-owned video. */
57
+ export type MediaSurfaceContent = MediaSurfaceImage | MediaSurfaceVideo;
58
+ /**
59
+ * A media surface currently owned by the flight layer.
60
+ *
61
+ * One per id, ever — that is the contract. `flyTo` on an id that is already in
62
+ * flight RETARGETS this record rather than adding a second surface, which is
63
+ * what keeps a single `VideoView` alive across the whole transition.
64
+ */
65
+ export interface MediaFlight {
66
+ id: string;
67
+ content: MediaSurfaceContent;
68
+ /** Rect the current leg starts from. */
69
+ from: MeasuredRect;
70
+ /** Rect the current leg ends at. */
71
+ to: MeasuredRect;
72
+ cornerRadius: number;
73
+ contentFit: 'contain' | 'cover';
74
+ /** See {@link MediaFlightOptions.surfaceType}. Fixed for the surface's life. */
75
+ surfaceType: VideoSurfaceType;
76
+ /**
77
+ * The leg's progress, 0 at `from` and 1 at `to`. Owned by the store (created
78
+ * with `makeMutable`, not a hook) because the animation is STARTED by an
79
+ * imperative call and only READ by the layer — an effect in the layer would
80
+ * have to re-derive from a prop and would fire a frame late.
81
+ */
82
+ progress: SharedValue<number>;
83
+ /**
84
+ * True once `flyBack` has aimed this surface at its anchor: when the leg
85
+ * settles, the surface is released instead of parked.
86
+ */
87
+ landing: boolean;
88
+ /** Bumped on every retarget, so React remounts nothing but the layer re-reads. */
89
+ generation: number;
90
+ }
91
+ /** Options for a single `flyTo` leg. */
92
+ export interface MediaFlightOptions {
93
+ /**
94
+ * Rect the surface starts from, used only when nothing is live for the id
95
+ * yet. This is the origin thumbnail's measured rect — `measureAnchor(id)` is
96
+ * what produces it. Omitted, the surface appears at its destination instead
97
+ * of flying in from a corner, which is the right degradation when the origin
98
+ * could not be measured (virtualised away, already unmounted).
99
+ *
100
+ * It is ignored on a retarget: a surface already in flight resumes from where
101
+ * it currently IS, never from where it once started.
102
+ */
103
+ from?: MeasuredRect;
104
+ /**
105
+ * Corner radius of the flying box. Defaults to Bloom's `radius-12`, the same
106
+ * default the media gallery uses for its fitted media.
107
+ */
108
+ cornerRadius?: number;
109
+ /**
110
+ * How the media fills the flying box. `'cover'` matches a cropped feed
111
+ * thumbnail; `'contain'` matches a fitted fullscreen view. Defaults to
112
+ * `'cover'`, because a flight almost always STARTS at a cropped thumbnail.
113
+ */
114
+ contentFit?: 'contain' | 'cover';
115
+ /**
116
+ * Android's rendering surface for the FLYING video view.
117
+ *
118
+ * Defaults to `'textureView'` because a `SurfaceView` is composited by the
119
+ * system outside the view hierarchy: it ignores its parent's clip, corner
120
+ * radius and transform, which is every property a flying box depends on.
121
+ *
122
+ * **This means a flight crosses a surface-type boundary at hand-off whenever
123
+ * the destination uses expo-video's own `'surfaceView'` default.** Whether
124
+ * that boundary is visible is a device question, not a code question, and it
125
+ * is the reason this is a knob rather than a constant: with it you can fly as
126
+ * `'surfaceView'` and match a destination that has not changed, or leave it
127
+ * and change the destination instead. Measure before choosing — the flight
128
+ * may not flicker at all, in which case the right answer is to do nothing.
129
+ */
130
+ surfaceType?: VideoSurfaceType;
131
+ }
132
+ /**
133
+ * The imperative surface of the flight layer, returned by `useMediaFlight()`.
134
+ *
135
+ * Origin and destination only DECLARE where they want the surface; the layer is
136
+ * what paints it. Neither renders the media itself while a flight is live, so
137
+ * there is never a second copy to keep in sync.
138
+ */
139
+ export interface MediaFlightController {
140
+ /**
141
+ * Register (or, with `null`, clear) the node that anchors `id` on screen.
142
+ * Wire it as a callback ref on the host view the media would otherwise
143
+ * occupy. The most recently registered node for an id is the current anchor,
144
+ * which is what makes a destination screen mounting over an origin screen
145
+ * take over as the fly-back target.
146
+ */
147
+ registerAnchor: (id: string, node: MediaFlightAnchorNode | null) => void;
148
+ /**
149
+ * Measure the current anchor for `id` in window coordinates. Resolves `null`
150
+ * when no anchor is registered (unmounted / virtualised) or it has no area,
151
+ * which is the signal to skip the transition rather than fly to nowhere.
152
+ */
153
+ measureAnchor: (id: string) => Promise<MeasuredRect | null>;
154
+ /**
155
+ * Take the surface for `id` live (if it is not already) and move it to
156
+ * `rect`. The first call flies in from {@link MediaFlightOptions.from} when
157
+ * the caller measured an origin, and appears in place when it did not. A call
158
+ * for an id already in flight RETARGETS the same surface — one surface per
159
+ * id, always.
160
+ *
161
+ * **Await it before tearing the origin down** (on web: before navigating).
162
+ * The promise resolves once the layer has committed its surface, which is what
163
+ * puts it in expo-video's mounted set while the origin is still there — the
164
+ * mechanism that carries `currentTime` across instead of restarting at zero.
165
+ * It resolves on a short timeout if no layer is mounted, so a missing root
166
+ * component degrades to "no transition" rather than to a dead feed.
167
+ */
168
+ flyTo: (id: string, rect: MeasuredRect, content: MediaSurfaceContent, options?: MediaFlightOptions) => Promise<void>;
169
+ /**
170
+ * Fly the live surface for `id` back to its current anchor and release it
171
+ * once it lands. With no measurable anchor the surface is released at once —
172
+ * the caller is expected to render its own copy again at that point.
173
+ */
174
+ flyBack: (id: string) => void;
175
+ /**
176
+ * Tell the layer a destination surface is LIVE, so the flying copy can go.
177
+ *
178
+ * Usually you do not call this: give the destination's `<MediaSurface>` a
179
+ * `flightId` and it reports its own first frame. It is here for a destination
180
+ * that renders something other than a Bloom surface.
181
+ *
182
+ * Called mid-flight it is remembered, not obeyed — the surface finishes
183
+ * travelling first, or it would vanish between the two rects.
184
+ */
185
+ handOff: (id: string) => void;
186
+ /**
187
+ * Progress of the most recent leg, 0 → 1. Read it from a worklet to fade an
188
+ * origin placeholder out and a destination's chrome in, in lockstep with the
189
+ * flight. Shared by every flight: concurrent flights (which the one-surface-
190
+ * per-id contract permits across DIFFERENT ids) overwrite each other here,
191
+ * and each surface's own geometry is driven by its own value regardless.
192
+ */
193
+ progress: SharedValue<number>;
194
+ }
195
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/media-flight/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE7E;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,eAAe,CACb,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GACtE,IAAI,CAAC;CACT;AAED,kDAAkD;AAClD,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,kEAAkE;IAClE,MAAM,EAAE,eAAe,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,6EAA6E;AAC7E,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAExE;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,mBAAmB,CAAC;IAC7B,wCAAwC;IACxC,IAAI,EAAE,YAAY,CAAC;IACnB,oCAAoC;IACpC,EAAE,EAAE,YAAY,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC;IAChC,gFAAgF;IAChF,WAAW,EAAE,gBAAgB,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9B;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wCAAwC;AACxC,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IACjC;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC;CAChC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,GAAG,IAAI,KAAK,IAAI,CAAC;IACzE;;;;OAIG;IACH,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC5D;;;;;;;;;;;;;OAaG;IACH,KAAK,EAAE,CACL,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,mBAAmB,EAC5B,OAAO,CAAC,EAAE,kBAAkB,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB;;;;OAIG;IACH,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B;;;;;;;;;OASG;IACH,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B;;;;;;OAMG;IACH,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/B"}
@@ -0,0 +1,4 @@
1
+ import type { MediaFlightController } from './types';
2
+ /** The media-flight controller. Stable for the life of the bundle. */
3
+ export declare function useMediaFlight(): MediaFlightController;
4
+ //# sourceMappingURL=use-media-flight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-media-flight.d.ts","sourceRoot":"","sources":["../../../../src/media-flight/use-media-flight.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAsBrD,sEAAsE;AACtE,wBAAgB,cAAc,IAAI,qBAAqB,CAEtD"}
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import type { ZoomableMediaGalleryHandle, ZoomableMediaGalleryProps } from './types';
3
+ export declare const ZoomableMediaGallery: React.ForwardRefExoticComponent<ZoomableMediaGalleryProps & React.RefAttributes<ZoomableMediaGalleryHandle>>;
4
+ export default ZoomableMediaGallery;
5
+ //# sourceMappingURL=ZoomableMediaGallery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ZoomableMediaGallery.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-media-gallery/ZoomableMediaGallery.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6E,MAAM,OAAO,CAAC;AAkElG,OAAO,KAAK,EAGV,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAkkCjB,eAAO,MAAM,oBAAoB,8GAA4B,CAAC;AAgL9D,eAAe,oBAAoB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-image-gallery/constants.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,eAAO,MAAM,YAAY,MAAM,CAAC;AAChC,oFAAoF;AACpF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,uDAAuD;AACvD,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,kFAAkF;AAClF,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,0FAA0F;AAC1F,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,eAAO,MAAM,WAAW;;;;CAAsD,CAAC;AAC/E,eAAO,MAAM,YAAY;;;;CAAuD,CAAC;AACjF,eAAO,MAAM,gBAAgB;;;;CAAsD,CAAC;AAEpF,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,IAAsB,CAAC;AAEzD,yEAAyE;AACzE,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,oDAAoD;AACpD,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,mFAAmF;AACnF,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,2EAA2E;AAC3E,eAAO,MAAM,yBAAyB,KAAK,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-media-gallery/constants.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,eAAO,MAAM,YAAY,MAAM,CAAC;AAChC,oFAAoF;AACpF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,uDAAuD;AACvD,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,kFAAkF;AAClF,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,0FAA0F;AAC1F,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,eAAO,MAAM,WAAW;;;;CAAsD,CAAC;AAC/E,eAAO,MAAM,YAAY;;;;CAAuD,CAAC;AACjF,eAAO,MAAM,gBAAgB;;;;CAAsD,CAAC;AAEpF,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,IAAsB,CAAC;AAEzD,yEAAyE;AACzE,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,oDAAoD;AACpD,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,mFAAmF;AACnF,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,2EAA2E;AAC3E,eAAO,MAAM,yBAAyB,KAAK,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { ZoomableMediaGallery, ZoomableMediaGallery as default } from './ZoomableMediaGallery';
2
+ export type { ZoomableMediaGalleryHandle, ZoomableMediaGalleryProps, GalleryImage, GalleryVideo, GalleryMedia, MeasureThumb, MeasuredRect, } from './types';
3
+ export * from './constants';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-image-gallery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,IAAI,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC/F,YAAY,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-media-gallery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,IAAI,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC/F,YAAY,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,cAAc,aAAa,CAAC"}
@@ -0,0 +1,90 @@
1
+ import type { MeasuredRect, MediaSurfaceImage, MediaSurfaceVideo } from '../media-flight/types';
2
+ /**
3
+ * A still image page.
4
+ *
5
+ * `kind` is optional on this arm so an image literal stays `{ uri }` — the shape
6
+ * every caller already writes, and the reason adding video to this gallery is
7
+ * not a breaking change for image consumers.
8
+ */
9
+ export interface GalleryImage extends MediaSurfaceImage {
10
+ /**
11
+ * Author-authored accessibility description (Bluesky-style "ALT"). When present,
12
+ * shown as a caption at the bottom of the fullscreen viewer for the active item.
13
+ */
14
+ alt?: string;
15
+ /**
16
+ * Optional intrinsic aspect ratio (width / height) supplied by the consumer.
17
+ * When known ahead of time it avoids a first-frame `Image.getSize` round-trip.
18
+ */
19
+ aspectRatio?: number;
20
+ }
21
+ /**
22
+ * A video page, fed by a `VideoPlayer` the CONSUMER created and owns.
23
+ *
24
+ * Bloom neither creates nor destroys players — see `MediaSurfaceVideo`. That is
25
+ * what lets the same video keep playing as it moves from a feed thumbnail into
26
+ * this gallery and back out again: one player, a different view.
27
+ */
28
+ export interface GalleryVideo extends MediaSurfaceVideo {
29
+ /**
30
+ * Stable identity for this video. Used as the React key (a video has no `uri`
31
+ * to key on) and as the media-flight id when the consumer flies it in.
32
+ */
33
+ id: string;
34
+ /** See {@link GalleryImage.alt}. */
35
+ alt?: string;
36
+ /**
37
+ * Intrinsic aspect ratio. Strongly recommended for video: unlike an image
38
+ * there is nothing to probe for it, so without one the page opens at the
39
+ * gallery's default ratio and resizes when the first frame arrives.
40
+ */
41
+ aspectRatio?: number;
42
+ /**
43
+ * URL handed to the share sheet. The poster is not what a user means by
44
+ * "share this video", so the two are separate; with neither, the share button
45
+ * is inert for that page.
46
+ */
47
+ shareUrl?: string;
48
+ }
49
+ /** One page of the gallery: a still image, or a consumer-owned video. */
50
+ export type GalleryMedia = GalleryImage | GalleryVideo;
51
+ export type { MeasuredRect };
52
+ /**
53
+ * Resolve the on-screen rect of the thumbnail at `index` within the SAME
54
+ * media subset the gallery opens/pages in, so the close animation can fly
55
+ * back to the item currently being viewed. Resolves `null` when the thumbnail
56
+ * ref is missing (unmounted/virtualized), in which case the gallery falls back
57
+ * to a plain center fade-out.
58
+ */
59
+ export type MeasureThumb = (index: number) => Promise<MeasuredRect | null>;
60
+ export interface ZoomableMediaGalleryHandle {
61
+ /**
62
+ * Open the gallery at `index` within `items`, animating the zoom from the
63
+ * tapped thumbnail's measured screen rect (when provided).
64
+ */
65
+ open: (items: GalleryMedia[], index: number, rect?: MeasuredRect) => void;
66
+ }
67
+ export interface ZoomableMediaGalleryProps {
68
+ /** Measures any thumbnail by its media subset index, used on dismiss. */
69
+ measureThumb?: MeasureThumb;
70
+ /**
71
+ * Corner radius applied to the zoomed media. `'circle'` rounds each item to
72
+ * a full circle at whatever size it is fitted to — what an avatar needs, and
73
+ * the reason avatars don't need their own viewer.
74
+ */
75
+ cornerRadius?: number | 'circle';
76
+ /**
77
+ * Bottom page indicator for multi-item galleries. `'dots'` (default) renders the
78
+ * compact dot row; `'thumbnails'` renders a horizontal strip of tappable media
79
+ * tiles. The counter pill shows in both. Ignored for single-item galleries.
80
+ */
81
+ indicatorVariant?: 'dots' | 'thumbnails';
82
+ /**
83
+ * Whether video pages show expo-video's own transport controls. Off by
84
+ * default, so a video opens as a picture that happens to move — the same
85
+ * gesture vocabulary (tap to dismiss, drag to dismiss) as an image. Turn it
86
+ * on for a viewer whose job is watching rather than glancing.
87
+ */
88
+ videoControls?: boolean;
89
+ }
90
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/zoomable-media-gallery/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,WAAW,YAAa,SAAQ,iBAAiB;IACrD;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAa,SAAQ,iBAAiB;IACrD;;;OAGG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,oCAAoC;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,YAAY,CAAC;AAEvD,YAAY,EAAE,YAAY,EAAE,CAAC;AAE7B;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;AAE3E,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,IAAI,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,KAAK,IAAI,CAAC;CAC3E;AAED,MAAM,WAAW,yBAAyB;IACxC,yEAAyE;IACzE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IACjC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IACzC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB"}
@@ -3,6 +3,11 @@
3
3
  * `select` sit on: one trigger slot, one panel, one row vocabulary, one anchor
4
4
  * measurement, instead of five copies.
5
5
  *
6
+ * `level-picker` is the sixth, and it takes only the ROW half — `MenuRowShell`
7
+ * and the chevron slot for its disclosure row, plus the motion constants — so
8
+ * the row that reveals a menu's details region cannot disagree with the rows it
9
+ * reveals about an inset, a highlight or a height.
10
+ *
6
11
  * INTERNAL. This barrel is the family's surface to the five families INSIDE
7
12
  * Bloom that build on it — it is deliberately absent from `package.json#exports`
8
13
  * and from `src/index.ts`, and `family-layout.test.ts` records that in
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/floating/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,UAAU,GACX,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,uBAAuB,EACvB,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAK7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,mBAAmB,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/floating/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,UAAU,GACX,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,uBAAuB,EACvB,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAK7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,mBAAmB,SAAS,CAAC"}
@@ -77,6 +77,8 @@ export { InputGroup, InputGroupAddon } from './input-group';
77
77
  export type { InputGroupProps, InputGroupAddonProps } from './input-group';
78
78
  export { Slider } from './slider';
79
79
  export type { SliderProps } from './slider';
80
+ export { LevelPicker } from './level-picker';
81
+ export type { LevelPickerProps } from './level-picker';
80
82
  export { Combobox } from './combobox';
81
83
  export type { ComboboxProps, ComboboxOption } from './combobox';
82
84
  export { BottomSheet } from './bottom-sheet';