@devvie/bottom-sheet
Version:
The 😎smart , 📦tiny , and 🎗flexible bottom sheet your app craves 🚀
600 lines (572 loc) • 26.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _index = require("../../constant/index.js");
var _useAnimatedValue = _interopRequireDefault(require("../../hooks/useAnimatedValue.js"));
var _index2 = _interopRequireDefault(require("../../hooks/useHandleAndroidBackButtonClose/index.js"));
var _index3 = _interopRequireDefault(require("../../hooks/useHandleKeyboardEvents/index.js"));
var _convertHeight = _interopRequireDefault(require("../../utils/convertHeight.js"));
var _resolveSnapPoints = _interopRequireDefault(require("../../utils/resolveSnapPoints.js"));
var _normalizeHeight = _interopRequireDefault(require("../../utils/normalizeHeight.js"));
var _separatePaddingStyles = _interopRequireDefault(require("../../utils/separatePaddingStyles.js"));
var _index4 = _interopRequireDefault(require("../backdrop/index.js"));
var _index5 = _interopRequireDefault(require("../container/index.js"));
var _index6 = _interopRequireDefault(require("../defaultHandleBar/index.js"));
var _typesD = require("./types.d.js");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
/**
* Main bottom sheet component
*/const BottomSheet = /*#__PURE__*/(0, _react.forwardRef)(({
backdropMaskColor = _index.DEFAULT_BACKDROP_MASK_COLOR,
children: Children,
animationType = _index.DEFAULT_ANIMATION,
closeOnBackdropPress = true,
height = _index.DEFAULT_HEIGHT,
snapPoints,
index = _index.DEFAULT_SNAP_INDEX,
onSnap,
hideDragHandle = false,
android_backdropMaskRippleColor,
dragHandleStyle,
disableBodyPanning = false,
disableDragHandlePanning = false,
customDragHandleComponent,
style: contentContainerStyle,
closeOnDragDown = true,
containerHeight: passedContainerHeight,
customBackdropComponent: CustomBackdropComponent,
customBackdropPosition = _typesD.CUSTOM_BACKDROP_POSITIONS.BEHIND,
modal = true,
openDuration = _index.DEFAULT_OPEN_ANIMATION_DURATION,
closeDuration = _index.DEFAULT_CLOSE_ANIMATION_DURATION,
customEasingFunction,
android_closeOnBackPress = true,
onClose,
onOpen,
onAnimate,
disableKeyboardHandling = false
}, ref) => {
/**
* ref instance callable methods
*/
(0, _react.useImperativeHandle)(ref, () => ({
open() {
openBottomSheet();
},
close() {
closeBottomSheet();
},
snapToIndex(snapIndex) {
snapToIndex(snapIndex);
},
expand() {
snapToIndex(_resolvedSnapPoints.length - 1);
},
collapse() {
snapToIndex(0);
}
}));
/**
* If passed container height is a valid number we use that as final container height
* else, it may be a percentage value so then we need to change it to a number (so it can be animated).
* The change is handled with `onLayout` further down
*/
const SCREEN_HEIGHT = (0, _reactNative.useWindowDimensions)().height; // actual container height is measured after layout
const [containerHeight, setContainerHeight] = (0, _react.useState)(SCREEN_HEIGHT);
const [sheetOpen, setSheetOpen] = (0, _react.useState)(false);
/** index of the snap point the sheet is currently resting on (ascending order) */
const [activeSnapIndex, setActiveSnapIndex] = (0, _react.useState)(index);
/** sheet height captured when a pan gesture starts, so drag math is relative to it */
const panStartHeight = (0, _react.useRef)(0);
// animated properties
const _animatedContainerHeight = (0, _useAnimatedValue.default)(0);
const _animatedBackdropMaskOpacity = (0, _useAnimatedValue.default)(0);
const _animatedHeight = (0, _useAnimatedValue.default)(0);
const contentWrapperRef = (0, _react.useRef)(null);
/** cached unique identifier of content container */
const cachedContentWrapperId = (0, _react.useRef)(undefined);
// here we separate all padding that may be applied via contentContainerStyle prop,
// these paddings will be applied to the `View` diretly wrapping `ChildNodes` in content container.
// All these is so that paddings applied to sheet doesn't affect the drag handle
// TODO: find better way to memoize `separatePaddingStyles` function return value to avoid
// redundant re-runs
const sepStyles = (0, _react.useMemo)(() => (0, _separatePaddingStyles.default)(contentContainerStyle), [contentContainerStyle]);
// Animation utility
const Animators = (0, _react.useMemo)(() => {
const _slideEasingFn = value => {
return value === 1 ? 1 : 1 - Math.pow(2, -10 * value);
};
const _springEasingFn = value => {
const decay = 9;
const multiplier = 4.5;
const divisor = 2.3;
const c4 = 2 * Math.PI / divisor;
return value === 0 ? 0 : value === 1 ? 1 : Math.pow(2, -decay * value) * Math.sin((value * multiplier - 0.75) * c4) + 1;
};
return {
animateContainerHeight(toValue, duration = 0) {
return _reactNative.Animated.timing(_animatedContainerHeight, {
toValue: toValue,
useNativeDriver: false,
duration: duration
});
},
animateBackdropMaskOpacity(toValue, duration) {
// we use passed open and close durations when animation type is fade
// but we use half of that for other animation types for good UX
const _duration = animationType === _typesD.ANIMATIONS.FADE ? duration : duration / 2.5;
return _reactNative.Animated.timing(_animatedBackdropMaskOpacity, {
toValue: toValue,
useNativeDriver: false,
duration: _duration
});
},
animateHeight(toValue, duration) {
return _reactNative.Animated.timing(_animatedHeight, {
toValue,
useNativeDriver: false,
duration: duration,
easing: customEasingFunction && typeof customEasingFunction === 'function' ? customEasingFunction : animationType === _typesD.ANIMATIONS.SLIDE ? _slideEasingFn : _springEasingFn
});
}
};
}, [animationType, customEasingFunction, _animatedContainerHeight, _animatedBackdropMaskOpacity, _animatedHeight]);
const interpolatedOpacity = (0, _react.useMemo)(() => animationType === _typesD.ANIMATIONS.FADE ? _animatedBackdropMaskOpacity.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [0, 0.3, 1],
extrapolate: 'clamp'
}) : contentContainerStyle?.opacity, [animationType, contentContainerStyle, _animatedBackdropMaskOpacity]);
/**
* Resolved resting heights (in pixels), ascending. When `snapPoints` is provided we
* resolve the whole array; otherwise we fall back to a single-element array holding the
* `height` prop, so the rest of the component treats both cases uniformly. An empty/all
* invalid `snapPoints` also falls back to `height`.
*/
const _resolvedSnapPoints = (0, _react.useMemo)(() => {
const hasSnapPoints = Array.isArray(snapPoints) && snapPoints.length > 0;
if (hasSnapPoints) {
const resolved = (0, _resolveSnapPoints.default)(snapPoints, containerHeight, hideDragHandle);
if (resolved.length) return resolved;
}
return [(0, _convertHeight.default)(height, containerHeight, hideDragHandle)];
}, [snapPoints, height, containerHeight, hideDragHandle]);
/** whether the sheet is operating in multi snap-point mode */
const _hasSnapPoints = _resolvedSnapPoints.length > 1;
/** active index, clamped to the currently valid range */
const _safeSnapIndex = Math.min(Math.max(activeSnapIndex, 0), _resolvedSnapPoints.length - 1);
/**
* Pixel height of the snap point the sheet currently rests on. Keeps the original
* `convertedHeight` name so every downstream consumer (keyboard handler, backdrop,
* pan math) is unaffected.
*/
const convertedHeight = _resolvedSnapPoints[_safeSnapIndex] ?? 0;
/**
* Re-syncs the animated sheet height to its active snap point when the geometry changes
* (orientation / `containerHeight` / `snapPoints` / `height`) while the sheet is open.
* Guarded by a geometry signature so it never re-animates on a user/programmatic snap
* (an `activeSnapIndex` change) — those are already animated by their own handlers.
*/
const _geometryKey = _resolvedSnapPoints.join();
const _prevGeometryKey = (0, _react.useRef)(_geometryKey);
// eslint-disable-next-line react-hooks/exhaustive-deps
(0, _react.useEffect)(() => {
if (_prevGeometryKey.current === _geometryKey) return;
_prevGeometryKey.current = _geometryKey;
if (!sheetOpen) return;
if (activeSnapIndex !== _safeSnapIndex) {
setActiveSnapIndex(_safeSnapIndex);
onSnap?.(_safeSnapIndex);
}
// FIXME: we use interface-undefined but existing property `_value` here and it's risky
// @ts-expect-error
const curHeight = _animatedHeight._value;
if (convertedHeight !== curHeight) {
if (animationType === _typesD.ANIMATIONS.FADE) _animatedHeight.setValue(convertedHeight);else Animators.animateHeight(convertedHeight, convertedHeight > curHeight ? openDuration : closeDuration).start();
}
});
/**
* If `disableKeyboardHandling` is false, handles keyboard pop up for both platforms,
* by auto adjusting sheet layout accordingly
*/
const keyboardHandler = (0, _index3.default)(!disableKeyboardHandling, convertedHeight, sheetOpen, Animators.animateHeight, contentWrapperRef, openDuration, closeDuration, containerHeight);
/**
* Returns conditioned gesture handlers for content container and handle bar elements
*/
const panHandlersFor = view => {
if (view === 'handlebar' && disableDragHandlePanning) return null;
if (view === 'contentwrapper' && disableBodyPanning) return null;
return _reactNative.PanResponder.create({
onMoveShouldSetPanResponderCapture: evt => {
if (view === 'handlebar') return true;
const cached = cachedContentWrapperId.current;
if (!cached) return false; // this signature alone should fix issue #34
return (
// @ts-expect-error _private field access
cached?.value === evt?.target?.[cached?.field] ||
// @ts-expect-error _private field access
cached?.value === evt?.currentTarget?.[cached?.field]
);
},
onPanResponderGrant: () => {
// capture the resting height when the drag starts, so movement is measured
// relative to it (handles dragging from any snap point or mid-animation)
// @ts-expect-error private `_value` field (see FIXME above)
panStartHeight.current = _animatedHeight._value;
},
onPanResponderMove: (_, gestureState) => {
const lowestSnap = _resolvedSnapPoints[0] ?? 0;
const maxSnap = _resolvedSnapPoints[_resolvedSnapPoints.length - 1] ?? 0;
// clamp between fully closed and the largest snap point
const next = Math.min(Math.max(panStartHeight.current - gestureState.dy, 0), maxSnap);
// backdrop stays opaque while at/above the smallest snap point and only
// fades as the sheet is dragged below it toward close
_animatedBackdropMaskOpacity.setValue(lowestSnap > 0 ? Math.min(Math.max(next / lowestSnap, 0), 1) : 0);
if (animationType !== _typesD.ANIMATIONS.FADE) _animatedHeight.setValue(next);
},
onPanResponderRelease(_, gestureState) {
const lowestSnap = _resolvedSnapPoints[0] ?? 0;
const maxSnap = _resolvedSnapPoints[_resolvedSnapPoints.length - 1] ?? 0;
const next = Math.min(Math.max(panStartHeight.current - gestureState.dy, 0), maxSnap);
// project where a flick would land so a fast drag carries further than a
// slow one (velocity only influences multi snap-point sheets)
const projected = _hasSnapPoints ? next - gestureState.vy * _index.SNAP_VELOCITY_FACTOR : next;
// dragged/flung below the smallest snap point past the close threshold
if (closeOnDragDown && projected < lowestSnap * _index.CLOSE_SNAP_RATIO) {
closeBottomSheet();
return;
}
_animatedBackdropMaskOpacity.setValue(1);
// fade has no height drag; just restore the backdrop and keep the snap point
if (animationType === _typesD.ANIMATIONS.FADE) return;
// settle on the snap point nearest the projected resting position
let targetIndex = 0;
let minDistance = Infinity;
for (let i = 0; i < _resolvedSnapPoints.length; i++) {
const distance = Math.abs((_resolvedSnapPoints[i] ?? 0) - projected);
if (distance < minDistance) {
minDistance = distance;
targetIndex = i;
}
}
Animators.animateHeight(_resolvedSnapPoints[targetIndex] ?? 0, openDuration / 2).start();
if (targetIndex !== _safeSnapIndex) {
setActiveSnapIndex(targetIndex);
onSnap?.(targetIndex);
}
}
}).panHandlers;
};
/**
* Polymorphic content container handle bar component
*/
/* eslint-disable react/no-unstable-nested-components, react-native/no-inline-styles */
const PolymorphicHandleBar = () => {
const CustomHandleBar = customDragHandleComponent;
return hideDragHandle ? null : CustomHandleBar && typeof CustomHandleBar === 'function' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
style: {
alignSelf: 'center'
},
...panHandlersFor('handlebar'),
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(CustomHandleBar, {
_animatedHeight: _animatedHeight
})
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_index6.default, {
style: dragHandleStyle,
...panHandlersFor('handlebar')
});
};
/* eslint-enable react/no-unstable-nested-components, react-native/no-inline-styles */
/**
* Extracts and caches either `_nativeTag` or `__nativeTag` or `__internalInstanceHandle` or `_internalFiberInstanceHandleDEV`
* reference of the `ContentWrapper` component based on which is available. Either will do for
* identifying the content wrapper in PanResponder
*/
const cacheElementReference = (0, _react.useCallback)(({
currentTarget,
nativeEvent
}) => {
const fabricInstanceHandleKey = '__internalInstanceHandle';
// @ts-expect-error `Fabric` renderer's instance handle reference/pointer
const fabricInstanceHandle = currentTarget?.[fabricInstanceHandleKey];
const oldNativeTagKey = '_nativeTag';
// @ts-expect-error `Paper` renderer's native tag number
const oldNativeTag = currentTarget?.[oldNativeTagKey];
const newNativeTagKey = '__nativeTag';
// @ts-expect-error `Fabric` renderer's native tag number
const newNativeTag = currentTarget?.[newNativeTagKey];
const paperInstanceHandleKey = '_internalFiberInstanceHandleDEV';
// @ts-expect-error `Paper` renderer's instance handle equivalent
const paperInstanceHandle = currentTarget?.[paperInstanceHandleKey];
if (!cachedContentWrapperId.current) {
if (fabricInstanceHandle) cachedContentWrapperId.current = {
field: fabricInstanceHandleKey,
value: fabricInstanceHandle
};else if (oldNativeTag) cachedContentWrapperId.current = {
field: oldNativeTagKey,
value: oldNativeTag
};else if (newNativeTag) cachedContentWrapperId.current = {
field: newNativeTagKey,
value: newNativeTag
};else if (paperInstanceHandle) cachedContentWrapperId.current = {
field: paperInstanceHandleKey,
value: paperInstanceHandle
};
// Check known stable keys for web if none of above exists
else if (_reactNative.Platform.OS === 'web') {
const responderKey = '__reactResponderId';
// @ts-expect-error `.target` is untyped
const responderId = nativeEvent?.target?.[responderKey];
if (responderId) {
cachedContentWrapperId.current = {
field: responderKey,
value: responderId
};
}
} else cachedContentWrapperId.current = undefined;
}
}, []);
/**
* Expands the bottom sheet. Opens to the snap point at `toIndex` (defaults to the
* `index` prop), resetting the active snap point so reopening always lands on it.
*/
const openBottomSheet = (toIndex = index) => {
const targetIndex = Math.min(Math.max(Math.trunc(toIndex), 0), _resolvedSnapPoints.length - 1);
const targetHeight = _resolvedSnapPoints[targetIndex] ?? 0;
setActiveSnapIndex(targetIndex);
// 1. open container
// 2. if using fade animation, set content container height manually, animate backdrop.
// else, animate backdrop and content container height in parallel
Animators.animateContainerHeight(!modal ? targetHeight : containerHeight).start();
if (animationType === _typesD.ANIMATIONS.FADE) {
_animatedHeight.setValue(targetHeight);
Animators.animateBackdropMaskOpacity(1, openDuration).start();
} else {
Animators.animateBackdropMaskOpacity(1, openDuration).start();
Animators.animateHeight(targetHeight, openDuration).start();
}
const wasOpen = sheetOpen;
setSheetOpen(true);
if (!wasOpen && onOpen) {
onOpen();
}
onSnap?.(targetIndex);
};
const closeBottomSheet = () => {
if (!sheetOpen) return;
if (animationType === _typesD.ANIMATIONS.FADE) {
// For fade, sheet opacity is tied to the backdrop, so we wait for the
// backdrop fade to complete before snapping the container shut.
Animators.animateBackdropMaskOpacity(0, closeDuration).start(anim => {
if (anim.finished) {
Animators.animateContainerHeight(0).start();
_animatedHeight.setValue(0);
}
});
} else if (animationType === _typesD.ANIMATIONS.SLIDE) {
// Run backdrop fade and height slide-out in parallel so flick-to-close
// doesn't pause mid-flight waiting for the (faster) backdrop fade.
// Snap the outer container to 0 only after the sheet has
// finished sliding out so the slide animation isn't clipped.
Animators.animateBackdropMaskOpacity(0, closeDuration).start();
Animators.animateHeight(0, closeDuration).start(anim => {
if (anim.finished) Animators.animateContainerHeight(0).start();
});
} else {
Animators.animateBackdropMaskOpacity(0, closeDuration).start();
// `animateHeight` and `animateContainerHeight` below need to run in parallel
// else there might be a noticeable flicker of sheet content
Animators.animateHeight(0, closeDuration).start();
Animators.animateContainerHeight(0).start();
}
setSheetOpen(false);
setActiveSnapIndex(-1);
keyboardHandler?.removeKeyboardListeners();
_reactNative.Keyboard.dismiss();
if (onClose) {
onClose();
}
onSnap?.(-1);
};
/**
* Animates the sheet to the snap point at `toIndex` (clamped). A negative index closes
* the sheet; if the sheet is closed, it opens at the target snap point. The animation is
* always driven off the live height so it never silently no-ops on a stale index.
*/
const snapToIndex = toIndex => {
if (toIndex < 0) {
closeBottomSheet();
return;
}
const clamped = Math.min(Math.max(Math.trunc(toIndex), 0), _resolvedSnapPoints.length - 1);
if (!sheetOpen) {
openBottomSheet(clamped);
return;
}
const targetHeight = _resolvedSnapPoints[clamped] ?? 0;
// @ts-expect-error private `_value` field (see FIXME above)
const curHeight = _animatedHeight._value;
if (animationType === _typesD.ANIMATIONS.FADE) {
if (curHeight !== targetHeight) {
Animators.animateBackdropMaskOpacity(0, openDuration / 2).start(anim => {
if (anim.finished) {
_animatedHeight.setValue(targetHeight);
Animators.animateBackdropMaskOpacity(1, openDuration / 2).start();
}
});
}
} else {
_animatedBackdropMaskOpacity.setValue(1);
if (curHeight !== targetHeight) {
const duration = targetHeight > curHeight ? openDuration : closeDuration;
Animators.animateHeight(targetHeight, duration).start();
}
}
if (clamped !== activeSnapIndex) {
setActiveSnapIndex(clamped);
onSnap?.(clamped);
}
};
const containerViewLayoutHandler = event => {
const newHeight = event.nativeEvent.layout.height;
setContainerHeight(newHeight);
// incase `containerHeight` prop value changes when bottom sheet is expanded
// we need to manually update the container height
if (sheetOpen) _animatedContainerHeight.setValue(newHeight);
};
/**
* Implementation logic for `onAnimate` prop
*/
(0, _react.useEffect)(() => {
if (onAnimate && typeof onAnimate === 'function') {
const animate = state => onAnimate(state.value);
let listenerId;
if (animationType === 'fade') listenerId = _animatedBackdropMaskOpacity.addListener(animate);else listenerId = _animatedHeight.addListener(animate);
return () => {
if (animationType === 'fade') _animatedBackdropMaskOpacity.removeListener(listenerId);else _animatedHeight.removeListener(listenerId);
};
}
return;
}, [onAnimate, animationType, _animatedBackdropMaskOpacity, _animatedHeight]);
/**
* Handles auto adjusting container view height and clamping
* and normalizing `containerHeight` prop upon change, if its a number.
* Also auto adjusts when orientation changes
*/
(0, _react.useLayoutEffect)(() => {
if (!modal) return; // no auto layout adjustment when backdrop is hidden
else {
if (typeof passedContainerHeight === 'number') {
setContainerHeight((0, _normalizeHeight.default)(passedContainerHeight));
if (sheetOpen) _animatedContainerHeight.setValue(passedContainerHeight);
} else if (typeof passedContainerHeight === 'undefined' && containerHeight !== SCREEN_HEIGHT) {
setContainerHeight(SCREEN_HEIGHT);
if (sheetOpen) _animatedContainerHeight.setValue(SCREEN_HEIGHT);
}
}
}, [passedContainerHeight, SCREEN_HEIGHT, sheetOpen, containerHeight, modal, _animatedContainerHeight]);
/**
* Handles hardware back button press for android
*/
(0, _index2.default)(android_closeOnBackPress, closeBottomSheet, sheetOpen);
// Children
const ChildNodes = typeof Children === 'function' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Children, {
_animatedHeight: _animatedHeight
}) : Children;
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [typeof passedContainerHeight === 'string' ?
/*#__PURE__*/
/**
* Below View handles converting `passedContainerHeight` from string to a number (to be animatable).
* It does this by taking the string height passed via `containerHeight` prop,
* and returning it's numeric equivalent after rendering, via its `onLayout` so we can
* use that as the final container height.
*/
(0, _jsxRuntime.jsx)(_reactNative.View, {
onLayout: containerViewLayoutHandler,
style: {
position: 'absolute',
height: passedContainerHeight,
width: 0,
opacity: 0
}
}) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_index5.default, {
style: {
height: _animatedContainerHeight
},
children: [modal ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_index4.default, {
BackdropComponent: CustomBackdropComponent,
_animatedHeight: _animatedHeight,
animatedBackdropOpacity: _animatedBackdropMaskOpacity,
backdropColor: backdropMaskColor,
backdropPosition: customBackdropPosition,
closeOnPress: closeOnBackdropPress,
containerHeight: containerHeight,
contentContainerHeight: convertedHeight,
pressHandler: closeBottomSheet,
rippleColor: android_backdropMaskRippleColor,
sheetOpen: sheetOpen
}) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
ref: contentWrapperRef,
onLayout: cacheElementReference
/* Merge external and internal styles carefully and orderly */,
style: [!modal ? materialStyles.contentContainerShadow : false, materialStyles.contentContainer,
// Apply default top-corner radii only when the user hasn't
// supplied a `borderRadius` shorthand since RN's render layer keeps
// individual corner properties over the shorthand, so leaving
// them in would silently override the user's value.
!(sepStyles?.otherStyles && 'borderRadius' in sepStyles.otherStyles) ? materialStyles.contentContainerTopRadius : false,
// we apply styles other than padding here
sepStyles?.otherStyles, {
height: _animatedHeight,
minHeight: _animatedHeight,
opacity: interpolatedOpacity
}],
...panHandlersFor('contentwrapper'),
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(PolymorphicHandleBar, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View
// we apply padding styles here to not affect drag handle above.
// `flex: 1` lets this fill the remaining space below the drag
// handle so children sized with `flex` or percentage heights
// render against the actual available area (issue #36).
, {
style: [materialStyles.contentBody, sepStyles?.paddingStyles],
children: ChildNodes
})]
}, 'BottomSheetContentContainer')]
})]
});
});
BottomSheet.displayName = 'BottomSheet';
BottomSheet.ANIMATIONS = _typesD.ANIMATIONS;
const materialStyles = _reactNative.StyleSheet.create({
contentContainer: {
backgroundColor: '#F7F2FA',
width: '100%',
overflow: 'hidden'
},
contentContainerTopRadius: {
borderTopLeftRadius: 28,
borderTopRightRadius: 28
},
contentBody: {
flex: 1
},
contentContainerShadow: _reactNative.Platform.OS === 'android' ? {
elevation: 7
} : {
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 3
},
shadowOpacity: 0.29,
shadowRadius: 4.65
}
});
var _default = exports.default = BottomSheet;
//# sourceMappingURL=index.js.map