@yahoo/uds-mobile 2.3.4 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/android/build.gradle +39 -0
  2. package/android/src/main/AndroidManifest.xml +1 -0
  3. package/android/src/main/java/com/yahoo/uds/screencornerradius/UDSScreenCornerRadiusModule.kt +44 -0
  4. package/dist/bin/generateTheme.mjs +10 -0
  5. package/dist/bin/mobile/scripts/utils/configToRNMappings.mjs +4 -1
  6. package/dist/components/AndroidBackHandler.cjs +31 -0
  7. package/dist/components/AndroidBackHandler.d.cts +21 -0
  8. package/dist/components/AndroidBackHandler.d.cts.map +1 -0
  9. package/dist/components/AndroidBackHandler.d.ts +21 -0
  10. package/dist/components/AndroidBackHandler.d.ts.map +1 -0
  11. package/dist/components/AndroidBackHandler.js +30 -0
  12. package/dist/components/AndroidBackHandler.js.map +1 -0
  13. package/dist/components/Avatar.cjs +1 -1
  14. package/dist/components/Avatar.js +1 -1
  15. package/dist/components/Badge.cjs +1 -1
  16. package/dist/components/Badge.js +1 -1
  17. package/dist/components/BottomSheet/BottomSheet.cjs +336 -0
  18. package/dist/components/BottomSheet/BottomSheet.d.cts +33 -0
  19. package/dist/components/BottomSheet/BottomSheet.d.cts.map +1 -0
  20. package/dist/components/BottomSheet/BottomSheet.d.ts +33 -0
  21. package/dist/components/BottomSheet/BottomSheet.d.ts.map +1 -0
  22. package/dist/components/BottomSheet/BottomSheet.js +334 -0
  23. package/dist/components/BottomSheet/BottomSheet.js.map +1 -0
  24. package/dist/components/BottomSheet/BottomSheetContent.cjs +65 -0
  25. package/dist/components/BottomSheet/BottomSheetContent.d.cts +22 -0
  26. package/dist/components/BottomSheet/BottomSheetContent.d.cts.map +1 -0
  27. package/dist/components/BottomSheet/BottomSheetContent.d.ts +22 -0
  28. package/dist/components/BottomSheet/BottomSheetContent.d.ts.map +1 -0
  29. package/dist/components/BottomSheet/BottomSheetContent.js +63 -0
  30. package/dist/components/BottomSheet/BottomSheetContent.js.map +1 -0
  31. package/dist/components/BottomSheet/BottomSheetDismiss.cjs +28 -0
  32. package/dist/components/BottomSheet/BottomSheetDismiss.d.cts +25 -0
  33. package/dist/components/BottomSheet/BottomSheetDismiss.d.cts.map +1 -0
  34. package/dist/components/BottomSheet/BottomSheetDismiss.d.ts +25 -0
  35. package/dist/components/BottomSheet/BottomSheetDismiss.d.ts.map +1 -0
  36. package/dist/components/BottomSheet/BottomSheetDismiss.js +27 -0
  37. package/dist/components/BottomSheet/BottomSheetDismiss.js.map +1 -0
  38. package/dist/components/BottomSheet/BottomSheetHandle.cjs +56 -0
  39. package/dist/components/BottomSheet/BottomSheetHandle.d.cts +14 -0
  40. package/dist/components/BottomSheet/BottomSheetHandle.d.cts.map +1 -0
  41. package/dist/components/BottomSheet/BottomSheetHandle.d.ts +14 -0
  42. package/dist/components/BottomSheet/BottomSheetHandle.d.ts.map +1 -0
  43. package/dist/components/BottomSheet/BottomSheetHandle.js +55 -0
  44. package/dist/components/BottomSheet/BottomSheetHandle.js.map +1 -0
  45. package/dist/components/BottomSheet/BottomSheetHeader.cjs +69 -0
  46. package/dist/components/BottomSheet/BottomSheetHeader.d.cts +16 -0
  47. package/dist/components/BottomSheet/BottomSheetHeader.d.cts.map +1 -0
  48. package/dist/components/BottomSheet/BottomSheetHeader.d.ts +16 -0
  49. package/dist/components/BottomSheet/BottomSheetHeader.d.ts.map +1 -0
  50. package/dist/components/BottomSheet/BottomSheetHeader.js +68 -0
  51. package/dist/components/BottomSheet/BottomSheetHeader.js.map +1 -0
  52. package/dist/components/BottomSheet/BottomSheetInternalProvider.cjs +26 -0
  53. package/dist/components/BottomSheet/BottomSheetInternalProvider.d.cts +23 -0
  54. package/dist/components/BottomSheet/BottomSheetInternalProvider.d.cts.map +1 -0
  55. package/dist/components/BottomSheet/BottomSheetInternalProvider.d.ts +23 -0
  56. package/dist/components/BottomSheet/BottomSheetInternalProvider.d.ts.map +1 -0
  57. package/dist/components/BottomSheet/BottomSheetInternalProvider.js +24 -0
  58. package/dist/components/BottomSheet/BottomSheetInternalProvider.js.map +1 -0
  59. package/dist/components/BottomSheet/BottomSheetProvider.cjs +33 -0
  60. package/dist/components/BottomSheet/BottomSheetProvider.d.cts +24 -0
  61. package/dist/components/BottomSheet/BottomSheetProvider.d.cts.map +1 -0
  62. package/dist/components/BottomSheet/BottomSheetProvider.d.ts +24 -0
  63. package/dist/components/BottomSheet/BottomSheetProvider.d.ts.map +1 -0
  64. package/dist/components/BottomSheet/BottomSheetProvider.js +31 -0
  65. package/dist/components/BottomSheet/BottomSheetProvider.js.map +1 -0
  66. package/dist/components/BottomSheet/BottomSheetTrigger.cjs +28 -0
  67. package/dist/components/BottomSheet/BottomSheetTrigger.d.cts +25 -0
  68. package/dist/components/BottomSheet/BottomSheetTrigger.d.cts.map +1 -0
  69. package/dist/components/BottomSheet/BottomSheetTrigger.d.ts +25 -0
  70. package/dist/components/BottomSheet/BottomSheetTrigger.d.ts.map +1 -0
  71. package/dist/components/BottomSheet/BottomSheetTrigger.js +27 -0
  72. package/dist/components/BottomSheet/BottomSheetTrigger.js.map +1 -0
  73. package/dist/components/BottomSheet/index.cjs +19 -0
  74. package/dist/components/BottomSheet/index.d.cts +11 -0
  75. package/dist/components/BottomSheet/index.d.ts +11 -0
  76. package/dist/components/BottomSheet/index.js +11 -0
  77. package/dist/components/BottomSheet/types.cjs +1 -0
  78. package/dist/components/BottomSheet/types.d.cts +173 -0
  79. package/dist/components/BottomSheet/types.d.cts.map +1 -0
  80. package/dist/components/BottomSheet/types.d.ts +173 -0
  81. package/dist/components/BottomSheet/types.d.ts.map +1 -0
  82. package/dist/components/BottomSheet/types.js +1 -0
  83. package/dist/components/BottomSheet/useBottomSheetDrag.cjs +191 -0
  84. package/dist/components/BottomSheet/useBottomSheetDrag.d.cts +69 -0
  85. package/dist/components/BottomSheet/useBottomSheetDrag.d.cts.map +1 -0
  86. package/dist/components/BottomSheet/useBottomSheetDrag.d.ts +69 -0
  87. package/dist/components/BottomSheet/useBottomSheetDrag.d.ts.map +1 -0
  88. package/dist/components/BottomSheet/useBottomSheetDrag.js +190 -0
  89. package/dist/components/BottomSheet/useBottomSheetDrag.js.map +1 -0
  90. package/dist/components/BottomSheet/useBottomSheetScroll.cjs +61 -0
  91. package/dist/components/BottomSheet/useBottomSheetScroll.d.cts +48 -0
  92. package/dist/components/BottomSheet/useBottomSheetScroll.d.cts.map +1 -0
  93. package/dist/components/BottomSheet/useBottomSheetScroll.d.ts +48 -0
  94. package/dist/components/BottomSheet/useBottomSheetScroll.d.ts.map +1 -0
  95. package/dist/components/BottomSheet/useBottomSheetScroll.js +60 -0
  96. package/dist/components/BottomSheet/useBottomSheetScroll.js.map +1 -0
  97. package/dist/components/BottomSheet/useBottomSheetSnapModel.cjs +142 -0
  98. package/dist/components/BottomSheet/useBottomSheetSnapModel.d.cts +79 -0
  99. package/dist/components/BottomSheet/useBottomSheetSnapModel.d.cts.map +1 -0
  100. package/dist/components/BottomSheet/useBottomSheetSnapModel.d.ts +79 -0
  101. package/dist/components/BottomSheet/useBottomSheetSnapModel.d.ts.map +1 -0
  102. package/dist/components/BottomSheet/useBottomSheetSnapModel.js +140 -0
  103. package/dist/components/BottomSheet/useBottomSheetSnapModel.js.map +1 -0
  104. package/dist/components/BottomSheet/useBottomSheetStore.cjs +79 -0
  105. package/dist/components/BottomSheet/useBottomSheetStore.d.cts +45 -0
  106. package/dist/components/BottomSheet/useBottomSheetStore.d.cts.map +1 -0
  107. package/dist/components/BottomSheet/useBottomSheetStore.d.ts +45 -0
  108. package/dist/components/BottomSheet/useBottomSheetStore.d.ts.map +1 -0
  109. package/dist/components/BottomSheet/useBottomSheetStore.js +77 -0
  110. package/dist/components/BottomSheet/useBottomSheetStore.js.map +1 -0
  111. package/dist/components/BottomSheet/useExpansionMargins.cjs +57 -0
  112. package/dist/components/BottomSheet/useExpansionMargins.d.cts +59 -0
  113. package/dist/components/BottomSheet/useExpansionMargins.d.cts.map +1 -0
  114. package/dist/components/BottomSheet/useExpansionMargins.d.ts +59 -0
  115. package/dist/components/BottomSheet/useExpansionMargins.d.ts.map +1 -0
  116. package/dist/components/BottomSheet/useExpansionMargins.js +56 -0
  117. package/dist/components/BottomSheet/useExpansionMargins.js.map +1 -0
  118. package/dist/components/BottomSheet/useKeyboardAvoidance.cjs +53 -0
  119. package/dist/components/BottomSheet/useKeyboardAvoidance.d.cts +31 -0
  120. package/dist/components/BottomSheet/useKeyboardAvoidance.d.cts.map +1 -0
  121. package/dist/components/BottomSheet/useKeyboardAvoidance.d.ts +31 -0
  122. package/dist/components/BottomSheet/useKeyboardAvoidance.d.ts.map +1 -0
  123. package/dist/components/BottomSheet/useKeyboardAvoidance.js +52 -0
  124. package/dist/components/BottomSheet/useKeyboardAvoidance.js.map +1 -0
  125. package/dist/components/BottomSheet/utils.cjs +77 -0
  126. package/dist/components/BottomSheet/utils.d.cts +50 -0
  127. package/dist/components/BottomSheet/utils.d.cts.map +1 -0
  128. package/dist/components/BottomSheet/utils.d.ts +50 -0
  129. package/dist/components/BottomSheet/utils.d.ts.map +1 -0
  130. package/dist/components/BottomSheet/utils.js +72 -0
  131. package/dist/components/BottomSheet/utils.js.map +1 -0
  132. package/dist/components/Box.cjs +1 -1
  133. package/dist/components/Box.js +1 -1
  134. package/dist/components/Button.cjs +1 -1
  135. package/dist/components/Button.js +1 -1
  136. package/dist/components/Checkbox.cjs +1 -1
  137. package/dist/components/Checkbox.js +1 -1
  138. package/dist/components/Chip.cjs +1 -1
  139. package/dist/components/Chip.js +1 -1
  140. package/dist/components/Icon.cjs +1 -1
  141. package/dist/components/Icon.js +1 -1
  142. package/dist/components/IconButton.cjs +1 -1
  143. package/dist/components/IconButton.js +1 -1
  144. package/dist/components/Image.cjs +1 -1
  145. package/dist/components/Image.js +1 -1
  146. package/dist/components/Input.cjs +1 -1
  147. package/dist/components/Input.js +1 -1
  148. package/dist/components/Link.cjs +1 -1
  149. package/dist/components/Link.js +1 -1
  150. package/dist/components/Pressable.cjs +1 -1
  151. package/dist/components/Pressable.js +1 -1
  152. package/dist/components/Radio.cjs +1 -1
  153. package/dist/components/Radio.js +1 -1
  154. package/dist/components/Screen.cjs +1 -1
  155. package/dist/components/Screen.js +1 -1
  156. package/dist/components/Scrim.cjs +73 -0
  157. package/dist/components/Scrim.d.cts +43 -0
  158. package/dist/components/Scrim.d.cts.map +1 -0
  159. package/dist/components/Scrim.d.ts +43 -0
  160. package/dist/components/Scrim.d.ts.map +1 -0
  161. package/dist/components/Scrim.js +71 -0
  162. package/dist/components/Scrim.js.map +1 -0
  163. package/dist/components/Switch.cjs +1 -1
  164. package/dist/components/Switch.js +1 -1
  165. package/dist/components/Text.cjs +1 -1
  166. package/dist/components/Text.js +1 -1
  167. package/dist/components/UDSProvider.cjs +38 -0
  168. package/dist/components/UDSProvider.d.cts +30 -0
  169. package/dist/components/UDSProvider.d.cts.map +1 -0
  170. package/dist/components/UDSProvider.d.ts +30 -0
  171. package/dist/components/UDSProvider.d.ts.map +1 -0
  172. package/dist/components/UDSProvider.js +37 -0
  173. package/dist/components/UDSProvider.js.map +1 -0
  174. package/dist/native/UDSScreenCornerRadiusModule.cjs +12 -0
  175. package/dist/native/UDSScreenCornerRadiusModule.d.cts +12 -0
  176. package/dist/native/UDSScreenCornerRadiusModule.d.cts.map +1 -0
  177. package/dist/native/UDSScreenCornerRadiusModule.d.ts +12 -0
  178. package/dist/native/UDSScreenCornerRadiusModule.d.ts.map +1 -0
  179. package/dist/native/UDSScreenCornerRadiusModule.js +9 -0
  180. package/dist/native/UDSScreenCornerRadiusModule.js.map +1 -0
  181. package/dist/portal.cjs +81 -0
  182. package/dist/portal.d.cts +18 -0
  183. package/dist/portal.d.cts.map +1 -0
  184. package/dist/portal.d.ts +18 -0
  185. package/dist/portal.d.ts.map +1 -0
  186. package/dist/portal.js +79 -0
  187. package/dist/portal.js.map +1 -0
  188. package/expo-module.config.json +9 -0
  189. package/generated/styles.cjs +10 -0
  190. package/generated/styles.d.ts +15 -2
  191. package/generated/styles.mjs +10 -0
  192. package/generated/unistyles.d.ts +21 -0
  193. package/ios/UDSMobile.podspec +25 -0
  194. package/ios/UDSScreenCornerRadiusModule.swift +218 -0
  195. package/package.json +40 -1
@@ -0,0 +1,33 @@
1
+
2
+ import { BottomSheetProps } from "./types.js";
3
+ import * as react from "react";
4
+
5
+ //#region src/components/BottomSheet/BottomSheet.d.ts
6
+ /**
7
+ * The core bottom sheet component for React Native.
8
+ *
9
+ * Renders a draggable, spring-animated sheet that snaps to configurable height
10
+ * positions. Supports modal (with scrim, blocks background interaction) and
11
+ * non-modal (no scrim, background remains interactive) modes, scroll coordination,
12
+ * keyboard avoidance, and optional edge-to-edge expansion at the max snap point.
13
+ *
14
+ * Must be wrapped in a {@link BottomSheetProvider} or provided a `controller` prop
15
+ * created via {@link useBottomSheetStore}.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * const store = useBottomSheetStore();
20
+ *
21
+ * <BottomSheetProvider controller={store}>
22
+ * <BottomSheetTrigger render={<Button>Open</Button>} />
23
+ * <BottomSheet snapPoints={['30%', '80%']}>
24
+ * <BottomSheetHeader>Title</BottomSheetHeader>
25
+ * <BottomSheetContent>...</BottomSheetContent>
26
+ * </BottomSheet>
27
+ * </BottomSheetProvider>
28
+ * ```
29
+ */
30
+ declare const BottomSheet: react.NamedExoticComponent<BottomSheetProps>;
31
+ //#endregion
32
+ export { BottomSheet };
33
+ //# sourceMappingURL=BottomSheet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BottomSheet.d.ts","names":[],"sources":["../../../src/components/BottomSheet/BottomSheet.tsx"],"mappings":";;;;;;;;AAwBiB;;;;;;;;;;;;;;;;;;;;;cA0DX,WAAA,EAAW,KAAA,CAAA,oBAAA,CAAA,gBAAA"}
@@ -0,0 +1,334 @@
1
+ /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
+ import { Portal } from "../../portal.js";
3
+ import { AndroidBackHandler } from "../AndroidBackHandler.js";
4
+ import { Box } from "../Box.js";
5
+ import { Scrim } from "../Scrim.js";
6
+ import { loadListeners, loadState, nativeModule } from "../../native/UDSScreenCornerRadiusModule.js";
7
+ import { BottomSheetInternalProvider } from "./BottomSheetInternalProvider.js";
8
+ import { BottomSheetProvider, useBottomSheetContext } from "./BottomSheetProvider.js";
9
+ import { BottomSheetHandle } from "./BottomSheetHandle.js";
10
+ import { resolveHeightToPx } from "./utils.js";
11
+ import { useBottomSheetDrag } from "./useBottomSheetDrag.js";
12
+ import { useBottomSheetSnapModel } from "./useBottomSheetSnapModel.js";
13
+ import { useExpansionMargins } from "./useExpansionMargins.js";
14
+ import { useKeyboardAvoidance } from "./useKeyboardAvoidance.js";
15
+ import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
16
+ import { Dimensions, Platform, StyleSheet, View } from "react-native";
17
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
18
+ import { bottomSheetStyles } from "../../../generated/styles";
19
+ import Animated, { interpolate, useAnimatedStyle, useSharedValue } from "react-native-reanimated";
20
+ import { GestureDetector, GestureHandlerRootView } from "react-native-gesture-handler";
21
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
22
+ import { FullWindowOverlay } from "react-native-screens";
23
+
24
+ //#region src/components/BottomSheet/BottomSheet.tsx
25
+ function useScreenCornerRadius() {
26
+ const [, forceUpdate] = useState(0);
27
+ useEffect(() => {
28
+ if (loadState === "pending") {
29
+ const listener = () => forceUpdate((n) => n + 1);
30
+ loadListeners.push(listener);
31
+ return () => {
32
+ const idx = loadListeners.indexOf(listener);
33
+ if (idx >= 0) loadListeners.splice(idx, 1);
34
+ };
35
+ }
36
+ }, []);
37
+ return {
38
+ module: nativeModule,
39
+ isLoaded: loadState === "loaded",
40
+ isFailed: loadState === "failed"
41
+ };
42
+ }
43
+ /**
44
+ * The core bottom sheet component for React Native.
45
+ *
46
+ * Renders a draggable, spring-animated sheet that snaps to configurable height
47
+ * positions. Supports modal (with scrim, blocks background interaction) and
48
+ * non-modal (no scrim, background remains interactive) modes, scroll coordination,
49
+ * keyboard avoidance, and optional edge-to-edge expansion at the max snap point.
50
+ *
51
+ * Must be wrapped in a {@link BottomSheetProvider} or provided a `controller` prop
52
+ * created via {@link useBottomSheetStore}.
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * const store = useBottomSheetStore();
57
+ *
58
+ * <BottomSheetProvider controller={store}>
59
+ * <BottomSheetTrigger render={<Button>Open</Button>} />
60
+ * <BottomSheet snapPoints={['30%', '80%']}>
61
+ * <BottomSheetHeader>Title</BottomSheetHeader>
62
+ * <BottomSheetContent>...</BottomSheetContent>
63
+ * </BottomSheet>
64
+ * </BottomSheetProvider>
65
+ * ```
66
+ */
67
+ const BottomSheet = memo(function BottomSheet({ children, controller: controllerProp, snapPoints: snapPointsProp, height, defaultSnapPointIndex = 0, snapPointIndex: snapPointIndexProp, onSnapPointChange, onClose, dismissible = true, enableDrag = true, modal = true, showHandleIndicator = true, fullWidthAtMaxSnap = false, enableOverstretch = true, blurTarget, shouldMatchDeviceCornerRadius = true }) {
68
+ const controller = useBottomSheetContext() ?? controllerProp;
69
+ const { module: screenCornerRadiusModule, isFailed: cornerRadiusFailed } = useScreenCornerRadius();
70
+ if (!controller) throw new Error("BottomSheet must be wrapped in BottomSheetProvider or provided a controller prop.");
71
+ if (cornerRadiusFailed) throw new Error("BottomSheet requires `expo-modules-core` to be installed.\nInstall it with: npx expo install expo-modules-core");
72
+ const { isOpen } = controller;
73
+ bottomSheetStyles.useVariants({});
74
+ const flatRoot = StyleSheet.flatten(bottomSheetStyles.root);
75
+ const marginHorizontal = flatRoot.marginHorizontal ?? 0;
76
+ const marginBottom = flatRoot.marginBottom ?? 0;
77
+ const blurIntensity = flatRoot.backgroundBlurRadius ?? 0;
78
+ const showBlurBox = blurIntensity > 0 && (Platform.OS === "ios" || blurTarget != null);
79
+ const opaqueBackground = flatRoot.backgroundColor ?? "#fff";
80
+ const sheetBackground = showBlurBox ? "transparent" : blurIntensity > 0 ? flatRoot.backgroundBlurColor ?? opaqueBackground : opaqueBackground;
81
+ const { top: safeTop, bottom: safeBottom } = useSafeAreaInsets();
82
+ const isDetached = marginBottom > 0 || marginHorizontal > 0;
83
+ const bottomInsetPx = isDetached ? marginBottom : 0;
84
+ const expandedBottomInsetPx = fullWidthAtMaxSnap ? 0 : bottomInsetPx;
85
+ const tokenBorderRadius = flatRoot.borderRadius ?? 16;
86
+ const screenCornerRadius = shouldMatchDeviceCornerRadius ? screenCornerRadiusModule?.getCornerRadiusSync() ?? 0 : 0;
87
+ const bottomCornerGap = isDetached ? Math.min(marginHorizontal, marginBottom + safeBottom) : 0;
88
+ const bottomCornerRadius = screenCornerRadius > 0 ? Math.max(0, screenCornerRadius - bottomCornerGap) : tokenBorderRadius;
89
+ const containerHeight = useSharedValue(Dimensions.get("window").height);
90
+ useEffect(() => {
91
+ const subscription = Dimensions.addEventListener("change", ({ window }) => {
92
+ containerHeight.value = window.height;
93
+ });
94
+ return () => subscription.remove();
95
+ }, [containerHeight]);
96
+ const { translateY, activeSnapIndex, isAnimating, resolvedSnapPoints, animateToSnap, animateToClose, animateToSnapWorklet, animateToCloseWorklet, getClosedTranslateY, getTranslateYForSnap } = useBottomSheetSnapModel({
97
+ snapPointsProp,
98
+ height,
99
+ defaultSnapPointIndex,
100
+ snapPointIndexProp,
101
+ onSnapPointChange,
102
+ containerHeight,
103
+ bottomInsetPx,
104
+ topInsetPx: safeTop,
105
+ sideInsetPx: marginHorizontal,
106
+ fullWidthAtMaxSnap,
107
+ expandedBottomInsetPx
108
+ });
109
+ const scrollOffsetY = useSharedValue(0);
110
+ const scrollLocked = useSharedValue(true);
111
+ const handleDismiss = useCallback(() => {
112
+ controller.close();
113
+ }, [controller]);
114
+ const { panGesture, panGestureRef, openTimeSV } = useBottomSheetDrag({
115
+ enableDrag,
116
+ dismissible,
117
+ enableOverstretch,
118
+ resolvedSnapPoints,
119
+ containerHeight,
120
+ bottomInsetPx,
121
+ translateY,
122
+ activeSnapIndex,
123
+ isAnimating,
124
+ animateToSnapWorklet,
125
+ animateToCloseWorklet,
126
+ onDismiss: handleDismiss,
127
+ scrollLocked,
128
+ scrollOffsetY,
129
+ getTranslateYForSnap
130
+ });
131
+ useKeyboardAvoidance({
132
+ isOpen,
133
+ translateY,
134
+ isAnimating
135
+ });
136
+ const { animatedMarginStyle: expansionMarginStyle, maxSnapTranslateY: expansionMaxSnapTranslateY, thresholdTranslateY: expansionThresholdTranslateY } = useExpansionMargins({
137
+ enabled: fullWidthAtMaxSnap,
138
+ baseMarginHorizontal: marginHorizontal,
139
+ baseMarginBottom: marginBottom,
140
+ resolvedSnapPoints,
141
+ containerHeight,
142
+ bottomInsetPx,
143
+ expandedBottomInsetPx,
144
+ translateY
145
+ });
146
+ const expansionEdgeStyle = useAnimatedStyle(() => {
147
+ if (!fullWidthAtMaxSnap) return {};
148
+ const bottomRadius = interpolate(translateY.value, [expansionMaxSnapTranslateY, expansionThresholdTranslateY], [0, bottomCornerRadius], "clamp");
149
+ return {
150
+ borderBottomLeftRadius: bottomRadius,
151
+ borderBottomRightRadius: bottomRadius,
152
+ paddingBottom: interpolate(translateY.value, [expansionMaxSnapTranslateY, expansionThresholdTranslateY], [safeBottom, 0], "clamp")
153
+ };
154
+ });
155
+ const internalContextValue = useMemo(() => ({
156
+ panGestureRef,
157
+ activeSnapIndex,
158
+ snapCount: resolvedSnapPoints.length,
159
+ scrollOffsetY,
160
+ scrollLocked
161
+ }), [
162
+ panGestureRef,
163
+ activeSnapIndex,
164
+ resolvedSnapPoints.length,
165
+ scrollOffsetY,
166
+ scrollLocked
167
+ ]);
168
+ const wasOpen = useRef(false);
169
+ const [isRendered, setIsRendered] = useState(false);
170
+ useEffect(() => {
171
+ if (isOpen && !wasOpen.current) {
172
+ const initialIndex = snapPointIndexProp ?? defaultSnapPointIndex;
173
+ scrollOffsetY.value = 0;
174
+ scrollLocked.value = initialIndex !== resolvedSnapPoints.length - 1;
175
+ setIsRendered(true);
176
+ translateY.value = getClosedTranslateY();
177
+ openTimeSV.value = Date.now();
178
+ const timeout = setTimeout(() => {
179
+ animateToSnap(initialIndex);
180
+ }, 50);
181
+ wasOpen.current = true;
182
+ return () => clearTimeout(timeout);
183
+ }
184
+ if (!isOpen && wasOpen.current) {
185
+ animateToClose(() => {
186
+ setIsRendered(false);
187
+ });
188
+ onClose?.();
189
+ wasOpen.current = false;
190
+ }
191
+ }, [
192
+ isOpen,
193
+ snapPointIndexProp,
194
+ defaultSnapPointIndex,
195
+ translateY,
196
+ getClosedTranslateY,
197
+ animateToSnap,
198
+ animateToClose,
199
+ onClose,
200
+ openTimeSV,
201
+ scrollOffsetY,
202
+ scrollLocked,
203
+ resolvedSnapPoints.length
204
+ ]);
205
+ useEffect(() => {
206
+ if (!isOpen || snapPointIndexProp === void 0) return;
207
+ animateToSnap(snapPointIndexProp);
208
+ }, [
209
+ isOpen,
210
+ snapPointIndexProp,
211
+ animateToSnap
212
+ ]);
213
+ const animatedSheetStyle = useAnimatedStyle(() => {
214
+ let effectiveBottom = 0;
215
+ if (isDetached) {
216
+ effectiveBottom = bottomInsetPx;
217
+ if (fullWidthAtMaxSnap) effectiveBottom = interpolate(translateY.value, [expansionMaxSnapTranslateY, expansionThresholdTranslateY], [expandedBottomInsetPx, bottomInsetPx], "clamp");
218
+ }
219
+ return {
220
+ transform: [{ translateY: translateY.value }],
221
+ height: Math.max(100, containerHeight.value - translateY.value - effectiveBottom)
222
+ };
223
+ });
224
+ const initialIndex = snapPointIndexProp ?? defaultSnapPointIndex;
225
+ const windowH = modal ? Dimensions.get("window").height : 0;
226
+ const openSnapHeight = resolvedSnapPoints[initialIndex] ? resolveHeightToPx(resolvedSnapPoints[initialIndex], windowH) : 0;
227
+ const openTranslateY = windowH - Math.min(openSnapHeight, windowH - bottomInsetPx) - bottomInsetPx;
228
+ const closedTranslateY = windowH + bottomInsetPx;
229
+ if (!isOpen && !isRendered) return null;
230
+ const borderWidth = flatRoot.borderWidth ?? 0;
231
+ const sheetView = /* @__PURE__ */ jsx(GestureDetector, {
232
+ gesture: panGesture,
233
+ children: /* @__PURE__ */ jsxs(Animated.View, {
234
+ style: [
235
+ internalStyles.sheet,
236
+ {
237
+ backgroundColor: sheetBackground,
238
+ borderTopLeftRadius: tokenBorderRadius,
239
+ borderTopRightRadius: tokenBorderRadius,
240
+ borderBottomLeftRadius: bottomCornerRadius,
241
+ borderBottomRightRadius: bottomCornerRadius,
242
+ paddingTop: 8,
243
+ marginHorizontal,
244
+ overflow: "hidden"
245
+ },
246
+ animatedSheetStyle,
247
+ fullWidthAtMaxSnap ? expansionMarginStyle : void 0,
248
+ fullWidthAtMaxSnap ? expansionEdgeStyle : void 0
249
+ ],
250
+ accessibilityRole: "none",
251
+ children: [
252
+ showBlurBox && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Box, {
253
+ style: StyleSheet.absoluteFill,
254
+ blur: blurIntensity,
255
+ blurTarget
256
+ }), /* @__PURE__ */ jsx(View, {
257
+ style: [StyleSheet.absoluteFill, { backgroundColor: flatRoot.backgroundBlurColor }],
258
+ pointerEvents: "none"
259
+ })] }),
260
+ showHandleIndicator && enableDrag && /* @__PURE__ */ jsx(BottomSheetHandle, {}),
261
+ /* @__PURE__ */ jsx(View, {
262
+ style: {
263
+ paddingHorizontal: flatRoot.paddingHorizontal ?? 16,
264
+ paddingBottom: flatRoot.paddingVertical ?? 8,
265
+ flex: 1
266
+ },
267
+ children: /* @__PURE__ */ jsx(BottomSheetInternalProvider, {
268
+ value: internalContextValue,
269
+ children
270
+ })
271
+ }),
272
+ borderWidth > 0 && /* @__PURE__ */ jsx(Animated.View, {
273
+ style: [
274
+ StyleSheet.absoluteFill,
275
+ {
276
+ borderColor: flatRoot.borderColor ?? "transparent",
277
+ borderWidth,
278
+ borderTopLeftRadius: tokenBorderRadius,
279
+ borderTopRightRadius: tokenBorderRadius,
280
+ borderBottomLeftRadius: bottomCornerRadius,
281
+ borderBottomRightRadius: bottomCornerRadius
282
+ },
283
+ fullWidthAtMaxSnap ? expansionEdgeStyle : void 0
284
+ ],
285
+ pointerEvents: "none"
286
+ })
287
+ ]
288
+ })
289
+ });
290
+ const modalOverlay = /* @__PURE__ */ jsxs(GestureHandlerRootView, {
291
+ style: internalStyles.modalRoot,
292
+ pointerEvents: isOpen ? "auto" : "none",
293
+ children: [/* @__PURE__ */ jsx(Scrim, {
294
+ translateY,
295
+ openTranslateY,
296
+ closedTranslateY,
297
+ dismissible,
298
+ onDismiss: handleDismiss,
299
+ blurTarget
300
+ }), sheetView]
301
+ });
302
+ const nonModalOverlay = /* @__PURE__ */ jsx(View, {
303
+ style: StyleSheet.absoluteFill,
304
+ pointerEvents: isOpen ? "box-none" : "none",
305
+ children: /* @__PURE__ */ jsx(GestureHandlerRootView, {
306
+ style: internalStyles.sheet,
307
+ pointerEvents: "auto",
308
+ children: sheetView
309
+ })
310
+ });
311
+ if (Platform.OS === "ios") return /* @__PURE__ */ jsx(FullWindowOverlay, { children: modal ? modalOverlay : nonModalOverlay });
312
+ return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsxs(BottomSheetProvider, {
313
+ controller,
314
+ children: [modal && /* @__PURE__ */ jsx(AndroidBackHandler, {
315
+ dismissible,
316
+ onDismiss: handleDismiss,
317
+ isOpen
318
+ }), modal ? modalOverlay : nonModalOverlay]
319
+ }) });
320
+ });
321
+ const internalStyles = StyleSheet.create({
322
+ modalRoot: { flex: 1 },
323
+ sheet: {
324
+ position: "absolute",
325
+ left: 0,
326
+ right: 0,
327
+ top: 0,
328
+ minHeight: 100
329
+ }
330
+ });
331
+
332
+ //#endregion
333
+ export { BottomSheet };
334
+ //# sourceMappingURL=BottomSheet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BottomSheet.js","names":["cornerRadiusLoadState","cornerRadiusListeners","cornerRadiusModule"],"sources":["../../../src/components/BottomSheet/BottomSheet.tsx"],"sourcesContent":["import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Dimensions, Platform, StyleSheet, View } from 'react-native';\nimport { GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler';\nimport Animated, { interpolate, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { FullWindowOverlay } from 'react-native-screens';\n\nimport { bottomSheetStyles } from '../../../generated/styles';\nimport {\n loadListeners as cornerRadiusListeners,\n loadState as cornerRadiusLoadState,\n nativeModule as cornerRadiusModule,\n} from '../../native/UDSScreenCornerRadiusModule';\nimport { Portal } from '../../portal';\nimport { AndroidBackHandler } from '../AndroidBackHandler';\nimport { Box } from '../Box';\nimport { Scrim } from '../Scrim';\nimport { BottomSheetHandle } from './BottomSheetHandle';\nimport { BottomSheetInternalProvider } from './BottomSheetInternalProvider';\nimport { BottomSheetProvider, useBottomSheetContext } from './BottomSheetProvider';\nimport type {\n BottomSheetInternalContextValue,\n BottomSheetProps,\n BottomSheetRootTokens,\n} from './types';\nimport { useBottomSheetDrag } from './useBottomSheetDrag';\nimport { useBottomSheetSnapModel } from './useBottomSheetSnapModel';\nimport { useExpansionMargins } from './useExpansionMargins';\nimport { useKeyboardAvoidance } from './useKeyboardAvoidance';\nimport { resolveHeightToPx } from './utils';\n\nfunction useScreenCornerRadius(): {\n module: typeof cornerRadiusModule;\n isLoaded: boolean;\n isFailed: boolean;\n} {\n const [, forceUpdate] = useState(0);\n\n useEffect(() => {\n if (cornerRadiusLoadState === 'pending') {\n const listener = () => forceUpdate((n) => n + 1);\n cornerRadiusListeners.push(listener);\n return () => {\n const idx = cornerRadiusListeners.indexOf(listener);\n if (idx >= 0) {\n cornerRadiusListeners.splice(idx, 1);\n }\n };\n }\n }, []);\n\n return {\n module: cornerRadiusModule,\n isLoaded: cornerRadiusLoadState === 'loaded',\n isFailed: cornerRadiusLoadState === 'failed',\n };\n}\n\n/**\n * The core bottom sheet component for React Native.\n *\n * Renders a draggable, spring-animated sheet that snaps to configurable height\n * positions. Supports modal (with scrim, blocks background interaction) and\n * non-modal (no scrim, background remains interactive) modes, scroll coordination,\n * keyboard avoidance, and optional edge-to-edge expansion at the max snap point.\n *\n * Must be wrapped in a {@link BottomSheetProvider} or provided a `controller` prop\n * created via {@link useBottomSheetStore}.\n *\n * @example\n * ```tsx\n * const store = useBottomSheetStore();\n *\n * <BottomSheetProvider controller={store}>\n * <BottomSheetTrigger render={<Button>Open</Button>} />\n * <BottomSheet snapPoints={['30%', '80%']}>\n * <BottomSheetHeader>Title</BottomSheetHeader>\n * <BottomSheetContent>...</BottomSheetContent>\n * </BottomSheet>\n * </BottomSheetProvider>\n * ```\n */\nconst BottomSheet = memo(function BottomSheet({\n children,\n controller: controllerProp,\n snapPoints: snapPointsProp,\n height,\n defaultSnapPointIndex = 0,\n snapPointIndex: snapPointIndexProp,\n onSnapPointChange,\n onClose,\n dismissible = true,\n enableDrag = true,\n modal = true,\n showHandleIndicator = true,\n fullWidthAtMaxSnap = false,\n enableOverstretch = true,\n blurTarget,\n shouldMatchDeviceCornerRadius = true,\n}: BottomSheetProps) {\n // Resolve controller: context first, fallback to prop.\n const contextController = useBottomSheetContext();\n const controller = contextController ?? controllerProp;\n\n const { module: screenCornerRadiusModule, isFailed: cornerRadiusFailed } =\n useScreenCornerRadius();\n\n if (!controller) {\n throw new Error(\n 'BottomSheet must be wrapped in BottomSheetProvider or provided a controller prop.',\n );\n }\n\n if (cornerRadiusFailed) {\n throw new Error(\n 'BottomSheet requires `expo-modules-core` to be installed.\\n' +\n 'Install it with: npx expo install expo-modules-core',\n );\n }\n\n const { isOpen } = controller;\n\n // Activate variant styles — must be called in this component so the\n // stylesheet is reactive for all reads below.\n bottomSheetStyles.useVariants({});\n\n const flatRoot = StyleSheet.flatten(bottomSheetStyles.root) as BottomSheetRootTokens;\n const marginHorizontal = flatRoot.marginHorizontal ?? 0;\n const marginBottom = flatRoot.marginBottom ?? 0;\n const blurIntensity = flatRoot.backgroundBlurRadius ?? 0;\n // iOS: real blur via Box BlurView (no target needed).\n // Android: real blur only when a blurTarget is provided.\n // Android fallback: semi-transparent background from the elevation token.\n const showBlurBox = blurIntensity > 0 && (Platform.OS === 'ios' || blurTarget != null);\n const opaqueBackground = flatRoot.backgroundColor ?? '#fff';\n const sheetBackground = showBlurBox\n ? 'transparent'\n : blurIntensity > 0\n ? (flatRoot.backgroundBlurColor ?? opaqueBackground)\n : opaqueBackground;\n\n // When detached (has margins), offset by safe area so the sheet sits above\n // the home indicator rather than overlapping it.\n const { top: safeTop, bottom: safeBottom } = useSafeAreaInsets();\n const isDetached = marginBottom > 0 || marginHorizontal > 0;\n const bottomInsetPx = isDetached ? marginBottom : 0;\n // When fullWidthAtMaxSnap, the sheet extends to the physical screen edge (past safe area).\n const expandedBottomInsetPx = fullWidthAtMaxSnap ? 0 : bottomInsetPx;\n\n // Concentric bottom corner radius: matches the device's screen corner curve.\n // inner radius = screen radius - gap (distance from screen edge to sheet edge).\n const tokenBorderRadius = flatRoot.borderRadius ?? 16;\n const screenCornerRadius = shouldMatchDeviceCornerRadius\n ? (screenCornerRadiusModule?.getCornerRadiusSync() ?? 0)\n : 0;\n const bottomCornerGap = isDetached ? Math.min(marginHorizontal, marginBottom + safeBottom) : 0;\n const bottomCornerRadius =\n screenCornerRadius > 0 ? Math.max(0, screenCornerRadius - bottomCornerGap) : tokenBorderRadius;\n\n // Container height: always use window dimensions (both modal and non-modal render full-screen).\n const containerHeight = useSharedValue(Dimensions.get('window').height);\n\n // Listen for window dimension changes (orientation, resize).\n useEffect(() => {\n const subscription = Dimensions.addEventListener('change', ({ window }) => {\n containerHeight.value = window.height;\n });\n return () => subscription.remove();\n }, [containerHeight]);\n\n // Snap model.\n const snapModel = useBottomSheetSnapModel({\n snapPointsProp,\n height,\n defaultSnapPointIndex,\n snapPointIndexProp,\n onSnapPointChange,\n containerHeight,\n bottomInsetPx,\n topInsetPx: safeTop,\n sideInsetPx: marginHorizontal,\n fullWidthAtMaxSnap,\n expandedBottomInsetPx,\n });\n\n const {\n translateY,\n activeSnapIndex,\n isAnimating,\n resolvedSnapPoints,\n animateToSnap,\n animateToClose,\n animateToSnapWorklet,\n animateToCloseWorklet,\n getClosedTranslateY,\n getTranslateYForSnap,\n } = snapModel;\n\n // Scroll coordination shared values.\n const scrollOffsetY = useSharedValue(0);\n const scrollLocked = useSharedValue(true);\n\n // Dismiss handler: close the controller from the JS thread.\n // Note: onClose is fired from the close effect to avoid double-calling.\n const handleDismiss = useCallback(() => {\n controller.close();\n }, [controller]);\n\n // Drag engine.\n const { panGesture, panGestureRef, openTimeSV } = useBottomSheetDrag({\n enableDrag,\n dismissible,\n enableOverstretch,\n resolvedSnapPoints,\n containerHeight,\n bottomInsetPx,\n translateY,\n activeSnapIndex,\n isAnimating,\n animateToSnapWorklet,\n animateToCloseWorklet,\n onDismiss: handleDismiss,\n scrollLocked,\n scrollOffsetY,\n getTranslateYForSnap,\n });\n\n // Keyboard avoidance — offsets sheet when keyboard opens.\n useKeyboardAvoidance({ isOpen, translateY, isAnimating });\n\n // Expansion margins — animate margins to 0 at max snap.\n const {\n animatedMarginStyle: expansionMarginStyle,\n maxSnapTranslateY: expansionMaxSnapTranslateY,\n thresholdTranslateY: expansionThresholdTranslateY,\n } = useExpansionMargins({\n enabled: fullWidthAtMaxSnap,\n baseMarginHorizontal: marginHorizontal,\n baseMarginBottom: marginBottom,\n resolvedSnapPoints,\n containerHeight,\n bottomInsetPx,\n expandedBottomInsetPx,\n translateY,\n });\n\n // When the sheet extends to the screen edge at max snap, animate the bottom\n // border radius to 0 (physical screen corners handle rounding) and add bottom\n // padding equal to the safe area so content stays above the home indicator.\n const expansionEdgeStyle = useAnimatedStyle(() => {\n if (!fullWidthAtMaxSnap) {\n return {};\n }\n const bottomRadius = interpolate(\n translateY.value,\n [expansionMaxSnapTranslateY, expansionThresholdTranslateY],\n [0, bottomCornerRadius],\n 'clamp',\n );\n const pb = interpolate(\n translateY.value,\n [expansionMaxSnapTranslateY, expansionThresholdTranslateY],\n [safeBottom, 0],\n 'clamp',\n );\n return {\n borderBottomLeftRadius: bottomRadius,\n borderBottomRightRadius: bottomRadius,\n paddingBottom: pb,\n };\n });\n\n // Internal context for BottomSheetContent and useBottomSheetScroll.\n const internalContextValue: BottomSheetInternalContextValue = useMemo(\n () => ({\n panGestureRef,\n activeSnapIndex,\n snapCount: resolvedSnapPoints.length,\n scrollOffsetY,\n scrollLocked,\n }),\n [panGestureRef, activeSnapIndex, resolvedSnapPoints.length, scrollOffsetY, scrollLocked],\n );\n\n // Track previous isOpen to detect transitions.\n const wasOpen = useRef(false);\n // Whether the sheet tree should remain rendered (stays true during close animation).\n const [isRendered, setIsRendered] = useState(false);\n\n useEffect(() => {\n if (isOpen && !wasOpen.current) {\n // Reset scroll state before mounting children so animatedProps reads\n // the correct scrollLocked value on the very first UI frame.\n const initialIndex = snapPointIndexProp ?? defaultSnapPointIndex;\n scrollOffsetY.value = 0;\n scrollLocked.value = initialIndex !== resolvedSnapPoints.length - 1;\n // Opening: mount the tree, then animate to initial snap.\n setIsRendered(true);\n // Start from closed position, then animate in.\n translateY.value = getClosedTranslateY();\n // Set open time for fresh-open lock.\n openTimeSV.value = Date.now();\n // Small delay to ensure layout is ready (mirrors web's 50ms enter delay).\n const timeout = setTimeout(() => {\n animateToSnap(initialIndex);\n }, 50);\n wasOpen.current = true;\n return () => clearTimeout(timeout);\n }\n\n if (!isOpen && wasOpen.current) {\n // Closing: animate to closed, then unmount.\n // If the drag engine already started the close animation, this restarts\n // the spring to the same target — Reanimated cancels the old one (finished=false)\n // and the new one's callback fires when it settles.\n animateToClose(() => {\n setIsRendered(false);\n });\n onClose?.();\n wasOpen.current = false;\n }\n }, [\n isOpen,\n snapPointIndexProp,\n defaultSnapPointIndex,\n translateY,\n getClosedTranslateY,\n animateToSnap,\n animateToClose,\n onClose,\n openTimeSV,\n scrollOffsetY,\n scrollLocked,\n resolvedSnapPoints.length,\n ]);\n\n // Sync controlled snap index changes while open.\n useEffect(() => {\n if (!isOpen || snapPointIndexProp === undefined) {\n return;\n }\n animateToSnap(snapPointIndexProp);\n }, [isOpen, snapPointIndexProp, animateToSnap]);\n\n // Animated sheet style.\n // For detached sheets (with margins), constrain height so the bottom margin\n // is visible. When fullWidthAtMaxSnap, the effective bottom inset interpolates\n // from bottomInsetPx to expandedBottomInsetPx as the sheet reaches max snap.\n const animatedSheetStyle = useAnimatedStyle(() => {\n let effectiveBottom = 0;\n if (isDetached) {\n effectiveBottom = bottomInsetPx;\n if (fullWidthAtMaxSnap) {\n effectiveBottom = interpolate(\n translateY.value,\n [expansionMaxSnapTranslateY, expansionThresholdTranslateY],\n [expandedBottomInsetPx, bottomInsetPx],\n 'clamp',\n );\n }\n }\n return {\n transform: [{ translateY: translateY.value }],\n height: Math.max(100, containerHeight.value - translateY.value - effectiveBottom),\n };\n });\n\n // Compute scrim interpolation positions (JS thread, for Scrim props).\n const initialIndex = snapPointIndexProp ?? defaultSnapPointIndex;\n const windowH = modal ? Dimensions.get('window').height : 0;\n const openSnapHeight = resolvedSnapPoints[initialIndex]\n ? resolveHeightToPx(resolvedSnapPoints[initialIndex], windowH)\n : 0;\n const openTranslateY =\n windowH - Math.min(openSnapHeight, windowH - bottomInsetPx) - bottomInsetPx;\n const closedTranslateY = windowH + bottomInsetPx;\n\n // Don't render anything if not open and close animation has completed.\n if (!isOpen && !isRendered) {\n return null;\n }\n\n const borderWidth = flatRoot.borderWidth ?? 0;\n\n const sheetView = (\n <GestureDetector gesture={panGesture}>\n <Animated.View\n style={[\n internalStyles.sheet,\n {\n backgroundColor: sheetBackground,\n borderTopLeftRadius: tokenBorderRadius,\n borderTopRightRadius: tokenBorderRadius,\n borderBottomLeftRadius: bottomCornerRadius,\n borderBottomRightRadius: bottomCornerRadius,\n paddingTop: 8,\n marginHorizontal,\n overflow: 'hidden',\n },\n animatedSheetStyle,\n fullWidthAtMaxSnap ? expansionMarginStyle : undefined,\n fullWidthAtMaxSnap ? expansionEdgeStyle : undefined,\n ]}\n accessibilityRole=\"none\"\n >\n {showBlurBox && (\n <>\n <Box style={StyleSheet.absoluteFill} blur={blurIntensity} blurTarget={blurTarget} />\n <View\n style={[StyleSheet.absoluteFill, { backgroundColor: flatRoot.backgroundBlurColor }]}\n pointerEvents=\"none\"\n />\n </>\n )}\n {showHandleIndicator && enableDrag && <BottomSheetHandle />}\n <View\n style={{\n paddingHorizontal: flatRoot.paddingHorizontal ?? 16,\n paddingBottom: flatRoot.paddingVertical ?? 8,\n flex: 1,\n }}\n >\n <BottomSheetInternalProvider value={internalContextValue}>\n {children}\n </BottomSheetInternalProvider>\n </View>\n {borderWidth > 0 && (\n <Animated.View\n style={[\n StyleSheet.absoluteFill,\n {\n borderColor: flatRoot.borderColor ?? 'transparent',\n borderWidth,\n borderTopLeftRadius: tokenBorderRadius,\n borderTopRightRadius: tokenBorderRadius,\n borderBottomLeftRadius: bottomCornerRadius,\n borderBottomRightRadius: bottomCornerRadius,\n },\n fullWidthAtMaxSnap ? expansionEdgeStyle : undefined,\n ]}\n pointerEvents=\"none\"\n />\n )}\n </Animated.View>\n </GestureDetector>\n );\n\n // Modal: full-screen gesture root with scrim blocks background interaction.\n const modalOverlay = (\n <GestureHandlerRootView\n style={internalStyles.modalRoot}\n pointerEvents={isOpen ? 'auto' : 'none'}\n >\n <Scrim\n translateY={translateY}\n openTranslateY={openTranslateY}\n closedTranslateY={closedTranslateY}\n dismissible={dismissible}\n onDismiss={handleDismiss}\n blurTarget={blurTarget}\n />\n {sheetView}\n </GestureHandlerRootView>\n );\n\n // Non-modal: gesture root wraps only the sheet so background stays interactive.\n const nonModalOverlay = (\n <View style={StyleSheet.absoluteFill} pointerEvents={isOpen ? 'box-none' : 'none'}>\n <GestureHandlerRootView style={internalStyles.sheet} pointerEvents=\"auto\">\n {sheetView}\n </GestureHandlerRootView>\n </View>\n );\n\n // iOS: FullWindowOverlay renders above all content at the window level.\n if (Platform.OS === 'ios') {\n return <FullWindowOverlay>{modal ? modalOverlay : nonModalOverlay}</FullWindowOverlay>;\n }\n\n // Android: Portal renders above all content via PortalHost. Re-provides\n // BottomSheetProvider since Portal re-parents outside the original tree.\n return (\n <Portal>\n <BottomSheetProvider controller={controller}>\n {modal && (\n <AndroidBackHandler dismissible={dismissible} onDismiss={handleDismiss} isOpen={isOpen} />\n )}\n {modal ? modalOverlay : nonModalOverlay}\n </BottomSheetProvider>\n </Portal>\n );\n});\n\nconst internalStyles = StyleSheet.create({\n modalRoot: {\n flex: 1,\n },\n sheet: {\n position: 'absolute',\n left: 0,\n right: 0,\n top: 0,\n minHeight: 100,\n },\n});\n\nexport { BottomSheet };\n"],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
+ const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
4
+ const require_components_BottomSheet_BottomSheetInternalProvider = require('./BottomSheetInternalProvider.cjs');
5
+ let react = require("react");
6
+ let react_native = require("react-native");
7
+ let react_jsx_runtime = require("react/jsx-runtime");
8
+ let react_native_reanimated = require("react-native-reanimated");
9
+ react_native_reanimated = require_runtime.__toESM(react_native_reanimated);
10
+ let react_native_gesture_handler = require("react-native-gesture-handler");
11
+ let react_native_safe_area_context = require("react-native-safe-area-context");
12
+
13
+ //#region src/components/BottomSheet/BottomSheetContent.tsx
14
+ /**
15
+ * Scrollable content area for the bottom sheet.
16
+ *
17
+ * Renders an `Animated.ScrollView` that coordinates with the sheet's pan gesture:
18
+ *
19
+ * 1. `scrollEnabled` disables touch handling when locked; `decelerationRate`
20
+ * prevents residual momentum.
21
+ * 2. The scroll handler tracks `contentOffset.y` for the drag gesture.
22
+ * 3. A `Gesture.Native()` links to the sheet's pan gesture via
23
+ * `simultaneousWithExternalGesture` for gesture handoff.
24
+ *
25
+ * Automatically adds bottom safe-area padding to the content container.
26
+ */
27
+ const BottomSheetContent = (0, react.memo)(function BottomSheetContent({ children }) {
28
+ const internalCtx = require_components_BottomSheet_BottomSheetInternalProvider.useBottomSheetInternalContext();
29
+ const scrollRef = (0, react_native_reanimated.useAnimatedRef)();
30
+ const { bottom: safeBottom } = (0, react_native_safe_area_context.useSafeAreaInsets)();
31
+ const contentContainerStyle = (0, react.useMemo)(() => ({ paddingBottom: safeBottom }), [safeBottom]);
32
+ const animatedScrollProps = (0, react_native_reanimated.useAnimatedProps)(() => ({
33
+ scrollEnabled: !internalCtx?.scrollLocked.value,
34
+ decelerationRate: internalCtx?.scrollLocked.value ? 0 : .998
35
+ }));
36
+ const scrollHandler = (0, react_native_reanimated.useAnimatedScrollHandler)({ onScroll: (event) => {
37
+ if (!internalCtx) return;
38
+ internalCtx.scrollOffsetY.value = event.contentOffset.y;
39
+ } });
40
+ if (!internalCtx) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.ScrollView, {
41
+ style: internalStyles.container,
42
+ contentContainerStyle,
43
+ children
44
+ });
45
+ const { panGestureRef } = internalCtx;
46
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureDetector, {
47
+ gesture: react_native_gesture_handler.Gesture.Native().simultaneousWithExternalGesture(panGestureRef),
48
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.ScrollView, {
49
+ ref: scrollRef,
50
+ style: internalStyles.container,
51
+ contentContainerStyle,
52
+ onScroll: scrollHandler,
53
+ scrollEventThrottle: 16,
54
+ animatedProps: animatedScrollProps,
55
+ bounces: false,
56
+ overScrollMode: "never",
57
+ nestedScrollEnabled: react_native.Platform.OS === "android",
58
+ children
59
+ })
60
+ });
61
+ });
62
+ const internalStyles = react_native.StyleSheet.create({ container: { flex: 1 } });
63
+
64
+ //#endregion
65
+ exports.BottomSheetContent = BottomSheetContent;
@@ -0,0 +1,22 @@
1
+
2
+ import { BottomSheetContentProps } from "./types.cjs";
3
+ import * as react from "react";
4
+
5
+ //#region src/components/BottomSheet/BottomSheetContent.d.ts
6
+ /**
7
+ * Scrollable content area for the bottom sheet.
8
+ *
9
+ * Renders an `Animated.ScrollView` that coordinates with the sheet's pan gesture:
10
+ *
11
+ * 1. `scrollEnabled` disables touch handling when locked; `decelerationRate`
12
+ * prevents residual momentum.
13
+ * 2. The scroll handler tracks `contentOffset.y` for the drag gesture.
14
+ * 3. A `Gesture.Native()` links to the sheet's pan gesture via
15
+ * `simultaneousWithExternalGesture` for gesture handoff.
16
+ *
17
+ * Automatically adds bottom safe-area padding to the content container.
18
+ */
19
+ declare const BottomSheetContent: react.NamedExoticComponent<BottomSheetContentProps>;
20
+ //#endregion
21
+ export { BottomSheetContent };
22
+ //# sourceMappingURL=BottomSheetContent.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BottomSheetContent.d.cts","names":[],"sources":["../../../src/components/BottomSheet/BottomSheetContent.tsx"],"mappings":";;;;;;;;AAWuD;;;;;;;;;;cAejD,kBAAA,EAAkB,KAAA,CAAA,oBAAA,CAAA,uBAAA"}
@@ -0,0 +1,22 @@
1
+
2
+ import { BottomSheetContentProps } from "./types.js";
3
+ import * as react from "react";
4
+
5
+ //#region src/components/BottomSheet/BottomSheetContent.d.ts
6
+ /**
7
+ * Scrollable content area for the bottom sheet.
8
+ *
9
+ * Renders an `Animated.ScrollView` that coordinates with the sheet's pan gesture:
10
+ *
11
+ * 1. `scrollEnabled` disables touch handling when locked; `decelerationRate`
12
+ * prevents residual momentum.
13
+ * 2. The scroll handler tracks `contentOffset.y` for the drag gesture.
14
+ * 3. A `Gesture.Native()` links to the sheet's pan gesture via
15
+ * `simultaneousWithExternalGesture` for gesture handoff.
16
+ *
17
+ * Automatically adds bottom safe-area padding to the content container.
18
+ */
19
+ declare const BottomSheetContent: react.NamedExoticComponent<BottomSheetContentProps>;
20
+ //#endregion
21
+ export { BottomSheetContent };
22
+ //# sourceMappingURL=BottomSheetContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BottomSheetContent.d.ts","names":[],"sources":["../../../src/components/BottomSheet/BottomSheetContent.tsx"],"mappings":";;;;;;;;AAWuD;;;;;;;;;;cAejD,kBAAA,EAAkB,KAAA,CAAA,oBAAA,CAAA,uBAAA"}
@@ -0,0 +1,63 @@
1
+ /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
+ import { useBottomSheetInternalContext } from "./BottomSheetInternalProvider.js";
3
+ import { memo, useMemo } from "react";
4
+ import { Platform, StyleSheet } from "react-native";
5
+ import { jsx } from "react/jsx-runtime";
6
+ import Animated, { useAnimatedProps, useAnimatedRef, useAnimatedScrollHandler } from "react-native-reanimated";
7
+ import { Gesture, GestureDetector } from "react-native-gesture-handler";
8
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
9
+
10
+ //#region src/components/BottomSheet/BottomSheetContent.tsx
11
+ /**
12
+ * Scrollable content area for the bottom sheet.
13
+ *
14
+ * Renders an `Animated.ScrollView` that coordinates with the sheet's pan gesture:
15
+ *
16
+ * 1. `scrollEnabled` disables touch handling when locked; `decelerationRate`
17
+ * prevents residual momentum.
18
+ * 2. The scroll handler tracks `contentOffset.y` for the drag gesture.
19
+ * 3. A `Gesture.Native()` links to the sheet's pan gesture via
20
+ * `simultaneousWithExternalGesture` for gesture handoff.
21
+ *
22
+ * Automatically adds bottom safe-area padding to the content container.
23
+ */
24
+ const BottomSheetContent = memo(function BottomSheetContent({ children }) {
25
+ const internalCtx = useBottomSheetInternalContext();
26
+ const scrollRef = useAnimatedRef();
27
+ const { bottom: safeBottom } = useSafeAreaInsets();
28
+ const contentContainerStyle = useMemo(() => ({ paddingBottom: safeBottom }), [safeBottom]);
29
+ const animatedScrollProps = useAnimatedProps(() => ({
30
+ scrollEnabled: !internalCtx?.scrollLocked.value,
31
+ decelerationRate: internalCtx?.scrollLocked.value ? 0 : .998
32
+ }));
33
+ const scrollHandler = useAnimatedScrollHandler({ onScroll: (event) => {
34
+ if (!internalCtx) return;
35
+ internalCtx.scrollOffsetY.value = event.contentOffset.y;
36
+ } });
37
+ if (!internalCtx) return /* @__PURE__ */ jsx(Animated.ScrollView, {
38
+ style: internalStyles.container,
39
+ contentContainerStyle,
40
+ children
41
+ });
42
+ const { panGestureRef } = internalCtx;
43
+ return /* @__PURE__ */ jsx(GestureDetector, {
44
+ gesture: Gesture.Native().simultaneousWithExternalGesture(panGestureRef),
45
+ children: /* @__PURE__ */ jsx(Animated.ScrollView, {
46
+ ref: scrollRef,
47
+ style: internalStyles.container,
48
+ contentContainerStyle,
49
+ onScroll: scrollHandler,
50
+ scrollEventThrottle: 16,
51
+ animatedProps: animatedScrollProps,
52
+ bounces: false,
53
+ overScrollMode: "never",
54
+ nestedScrollEnabled: Platform.OS === "android",
55
+ children
56
+ })
57
+ });
58
+ });
59
+ const internalStyles = StyleSheet.create({ container: { flex: 1 } });
60
+
61
+ //#endregion
62
+ export { BottomSheetContent };
63
+ //# sourceMappingURL=BottomSheetContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BottomSheetContent.js","names":[],"sources":["../../../src/components/BottomSheet/BottomSheetContent.tsx"],"sourcesContent":["import { memo, useMemo } from 'react';\nimport { Platform, StyleSheet } from 'react-native';\nimport { Gesture, GestureDetector } from 'react-native-gesture-handler';\nimport Animated, {\n useAnimatedProps,\n useAnimatedRef,\n useAnimatedScrollHandler,\n} from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\n\nimport { useBottomSheetInternalContext } from './BottomSheetInternalProvider';\nimport type { BottomSheetContentProps } from './types';\n\n/**\n * Scrollable content area for the bottom sheet.\n *\n * Renders an `Animated.ScrollView` that coordinates with the sheet's pan gesture:\n *\n * 1. `scrollEnabled` disables touch handling when locked; `decelerationRate`\n * prevents residual momentum.\n * 2. The scroll handler tracks `contentOffset.y` for the drag gesture.\n * 3. A `Gesture.Native()` links to the sheet's pan gesture via\n * `simultaneousWithExternalGesture` for gesture handoff.\n *\n * Automatically adds bottom safe-area padding to the content container.\n */\nconst BottomSheetContent = memo(function BottomSheetContent({ children }: BottomSheetContentProps) {\n const internalCtx = useBottomSheetInternalContext();\n const scrollRef = useAnimatedRef<Animated.ScrollView>();\n const { bottom: safeBottom } = useSafeAreaInsets();\n\n const contentContainerStyle = useMemo(() => ({ paddingBottom: safeBottom }), [safeBottom]);\n\n const animatedScrollProps = useAnimatedProps(() => ({\n scrollEnabled: !internalCtx?.scrollLocked.value,\n decelerationRate: internalCtx?.scrollLocked.value ? 0 : 0.998,\n }));\n\n // Track scroll offset so the drag gesture knows the scroll position.\n const scrollHandler = useAnimatedScrollHandler({\n onScroll: (event) => {\n if (!internalCtx) {\n return;\n }\n internalCtx.scrollOffsetY.value = event.contentOffset.y;\n },\n });\n\n if (!internalCtx) {\n return (\n <Animated.ScrollView\n style={internalStyles.container}\n contentContainerStyle={contentContainerStyle}\n >\n {children}\n </Animated.ScrollView>\n );\n }\n\n const { panGestureRef } = internalCtx;\n\n const nativeGesture = Gesture.Native().simultaneousWithExternalGesture(panGestureRef);\n\n return (\n <GestureDetector gesture={nativeGesture}>\n <Animated.ScrollView\n ref={scrollRef}\n style={internalStyles.container}\n contentContainerStyle={contentContainerStyle}\n onScroll={scrollHandler}\n scrollEventThrottle={16}\n animatedProps={animatedScrollProps}\n bounces={false}\n overScrollMode=\"never\"\n nestedScrollEnabled={Platform.OS === 'android'}\n >\n {children}\n </Animated.ScrollView>\n </GestureDetector>\n );\n});\n\nconst internalStyles = StyleSheet.create({\n container: {\n flex: 1,\n },\n});\n\nexport { BottomSheetContent };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,qBAAqB,KAAK,SAAS,mBAAmB,EAAE,YAAqC;CACjG,MAAM,cAAc,+BAA+B;CACnD,MAAM,YAAY,gBAAqC;CACvD,MAAM,EAAE,QAAQ,eAAe,mBAAmB;CAElD,MAAM,wBAAwB,eAAe,EAAE,eAAe,YAAY,GAAG,CAAC,WAAW,CAAC;CAE1F,MAAM,sBAAsB,wBAAwB;EAClD,eAAe,CAAC,aAAa,aAAa;EAC1C,kBAAkB,aAAa,aAAa,QAAQ,IAAI;EACzD,EAAE;CAGH,MAAM,gBAAgB,yBAAyB,EAC7C,WAAW,UAAU;AACnB,MAAI,CAAC,YACH;AAEF,cAAY,cAAc,QAAQ,MAAM,cAAc;IAEzD,CAAC;AAEF,KAAI,CAAC,YACH,QACE,oBAAC,SAAS;EACR,OAAO,eAAe;EACC;EAEtB;GACmB;CAI1B,MAAM,EAAE,kBAAkB;AAI1B,QACE,oBAAC;EAAgB,SAHG,QAAQ,QAAQ,CAAC,gCAAgC,cAAc;YAIjF,oBAAC,SAAS;GACR,KAAK;GACL,OAAO,eAAe;GACC;GACvB,UAAU;GACV,qBAAqB;GACrB,eAAe;GACf,SAAS;GACT,gBAAe;GACf,qBAAqB,SAAS,OAAO;GAEpC;IACmB;GACN;EAEpB;AAEF,MAAM,iBAAiB,WAAW,OAAO,EACvC,WAAW,EACT,MAAM,GACP,EACF,CAAC"}
@@ -0,0 +1,28 @@
1
+ /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
+ const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
4
+ const require_components_BottomSheet_BottomSheetProvider = require('./BottomSheetProvider.cjs');
5
+ let react = require("react");
6
+
7
+ //#region src/components/BottomSheet/BottomSheetDismiss.tsx
8
+ /**
9
+ * Clones the `render` element and injects an `onPress` handler that closes
10
+ * the nearest bottom sheet.
11
+ *
12
+ * Uses the `render` prop pattern to avoid nested pressable wrappers.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * <BottomSheetDismiss render={<Button>Close</Button>} />
17
+ * ```
18
+ */
19
+ const BottomSheetDismiss = (0, react.memo)(function BottomSheetDismiss({ render }) {
20
+ const controller = require_components_BottomSheet_BottomSheetProvider.useBottomSheetContext();
21
+ if (!controller) throw new Error("BottomSheetDismiss must be used inside a BottomSheetProvider.");
22
+ return (0, react.cloneElement)(render, { onPress: (0, react.useCallback)(() => {
23
+ controller.close();
24
+ }, [controller]) });
25
+ });
26
+
27
+ //#endregion
28
+ exports.BottomSheetDismiss = BottomSheetDismiss;