react-native-trays
Version:
Production-grade, Family inspired, React Native Tray System library
120 lines (118 loc) • 3.96 kB
JavaScript
"use strict";
/**
* TrayRenderer.tsx
*
* Renders a single tray component with animation and keyboard adjustment support.
* Handles tray position, animation, and keyboard-aware behavior for tray UI.
*/
import React, { useEffect } from 'react';
import { View, Platform, Keyboard, StyleSheet } from 'react-native';
import Animated, { useAnimatedStyle, useSharedValue, withTiming, Easing, LinearTransition, SlideInDown, SlideOutDown, FadeInDown, FadeOutDown } from 'react-native-reanimated';
/**
* Props for TrayRenderer component.
* @property trayKey - Unique key for the tray instance.
* @property trayProps - Props to pass to the tray component.
* @property config - Tray stack configuration.
* @property TrayComponent - The tray component to render.
* @property insets - Safe area insets for proper positioning.
*/
import { jsx as _jsx } from "react/jsx-runtime";
/**
* TrayRenderer
*
* Renders the given tray component with animation and keyboard-aware adjustments.
* Handles tray position, entry/exit animations, and safe area insets.
*/
export const TrayRenderer = ({
trayKey,
trayProps,
config,
TrayComponent,
insets
}) => {
const trayBottom = useSharedValue(insets.bottom);
useEffect(() => {
if (!config.adjustForKeyboard) return;
const handleKeyboardShow = e => {
trayBottom.value = withTiming(e.endCoordinates.height + 20, {
duration: Platform.OS === 'ios' ? 60 : 250,
easing: Easing.out(Easing.ease)
});
};
const handleKeyboardHide = () => {
trayBottom.value = withTiming(insets.bottom, {
duration: Platform.OS === 'ios' ? 90 : 200,
easing: Easing.out(Easing.ease)
});
};
const showSub = Platform.OS === 'ios' ? Keyboard.addListener('keyboardWillShow', handleKeyboardShow) : Keyboard.addListener('keyboardDidShow', handleKeyboardShow);
const hideSub = Platform.OS === 'ios' ? Keyboard.addListener('keyboardWillHide', handleKeyboardHide) : Keyboard.addListener('keyboardDidHide', handleKeyboardHide);
return () => {
showSub.remove();
hideSub.remove();
};
}, [config.adjustForKeyboard, insets.bottom, trayBottom]);
const trayAnimatedStyle = useAnimatedStyle(() => config.stickToTop ? {
top: insets.top + (typeof config.trayStyles?.top === 'number' ? config.trayStyles?.top : 0)
} : {
bottom: trayBottom.value + (typeof config.trayStyles?.bottom === 'number' ? config.trayStyles?.bottom : 0)
}, [config.trayStyles]);
const {
enteringAnimation = SlideInDown,
exitingAnimation = SlideOutDown,
horizontalSpacing = 20
} = config;
return /*#__PURE__*/_jsx(Animated.View, {
style: [styles.tray, {
backgroundColor: config.customTheming ? undefined : '#fff',
shadowColor: config.customTheming ? undefined : '#000',
left: insets.left + horizontalSpacing,
right: insets.right + horizontalSpacing
}, config.trayStyles, trayAnimatedStyle],
layout: LinearTransition.easing(Easing.out(Easing.ease)).duration(150),
entering: enteringAnimation,
exiting: exitingAnimation,
children: /*#__PURE__*/_jsx(View, {
style: styles.content,
children: /*#__PURE__*/_jsx(Animated.View, {
entering: FadeInDown.duration(180),
exiting: FadeOutDown.duration(120),
children: /*#__PURE__*/_jsx(TrayComponent, {
...(trayProps ?? {})
})
}, trayKey)
})
});
};
const styles = StyleSheet.create({
tray: {
position: 'absolute',
borderRadius: 30,
shadowOffset: {
width: 0,
height: 5
},
shadowOpacity: 0.25,
shadowRadius: 40,
elevation: 10,
overflow: 'hidden',
zIndex: 999
},
content: {
position: 'relative',
flex: 1
},
closeBtnWrapper: {
position: 'absolute',
zIndex: 1,
top: 20,
right: 20,
overflow: 'hidden'
},
closeBtn: {
width: 30,
height: 30,
zIndex: 2
}
});
//# sourceMappingURL=TrayRenderer.js.map