mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at vouch-impl 137 lines 3.4 kB view raw
1import * as React from 'react' 2import { 3 Dimensions, 4 NativeSyntheticEvent, 5 Platform, 6 StyleProp, 7 View, 8 ViewStyle, 9} from 'react-native' 10import {requireNativeModule, requireNativeViewManager} from 'expo-modules-core' 11 12import {BottomSheetState, BottomSheetViewProps} from './BottomSheet.types' 13import {BottomSheetPortalProvider} from './BottomSheetPortal' 14import {Context as PortalContext} from './BottomSheetPortal' 15 16const screenHeight = Dimensions.get('screen').height 17 18const NativeView: React.ComponentType< 19 BottomSheetViewProps & { 20 ref: React.RefObject<any> 21 style: StyleProp<ViewStyle> 22 } 23> = requireNativeViewManager('BottomSheet') 24 25const NativeModule = requireNativeModule('BottomSheet') 26 27const isIOS15 = Platform.OS === 'ios' && Number(Platform.Version) < 16 28 29export class BottomSheetNativeComponent extends React.Component< 30 BottomSheetViewProps, 31 { 32 open: boolean 33 viewHeight?: number 34 } 35> { 36 ref = React.createRef<any>() 37 38 static contextType = PortalContext 39 40 constructor(props: BottomSheetViewProps) { 41 super(props) 42 this.state = { 43 open: false, 44 } 45 } 46 47 present() { 48 this.setState({open: true}) 49 } 50 51 dismiss() { 52 this.ref.current?.dismiss() 53 } 54 55 private onStateChange = ( 56 event: NativeSyntheticEvent<{state: BottomSheetState}>, 57 ) => { 58 const {state} = event.nativeEvent 59 const isOpen = state !== 'closed' 60 this.setState({open: isOpen}) 61 this.props.onStateChange?.(event) 62 } 63 64 private updateLayout = () => { 65 this.ref.current?.updateLayout() 66 } 67 68 static dismissAll = async () => { 69 await NativeModule.dismissAll() 70 } 71 72 render() { 73 const Portal = this.context as React.ContextType<typeof PortalContext> 74 if (!Portal) { 75 throw new Error( 76 'BottomSheet: You need to wrap your component tree with a <BottomSheetPortalProvider> to use the bottom sheet.', 77 ) 78 } 79 80 if (!this.state.open) { 81 return null 82 } 83 84 const {children, backgroundColor, ...rest} = this.props 85 const cornerRadius = rest.cornerRadius ?? 0 86 87 let extraStyles 88 if (isIOS15 && this.state.viewHeight) { 89 const {viewHeight} = this.state 90 if (viewHeight < screenHeight / 2) { 91 extraStyles = { 92 height: viewHeight, 93 marginTop: screenHeight / 2 - viewHeight, 94 borderTopLeftRadius: cornerRadius, 95 borderTopRightRadius: cornerRadius, 96 } 97 } 98 } 99 100 return ( 101 <Portal> 102 <NativeView 103 {...rest} 104 onStateChange={this.onStateChange} 105 ref={this.ref} 106 style={{ 107 position: 'absolute', 108 height: screenHeight, 109 width: '100%', 110 }} 111 containerBackgroundColor={backgroundColor}> 112 <View 113 style={[ 114 { 115 flex: 1, 116 backgroundColor, 117 }, 118 Platform.OS === 'android' && { 119 borderTopLeftRadius: cornerRadius, 120 borderTopRightRadius: cornerRadius, 121 }, 122 extraStyles, 123 ]}> 124 <View 125 onLayout={e => { 126 const {height} = e.nativeEvent.layout 127 this.setState({viewHeight: height}) 128 this.updateLayout() 129 }}> 130 <BottomSheetPortalProvider>{children}</BottomSheetPortalProvider> 131 </View> 132 </View> 133 </NativeView> 134 </Portal> 135 ) 136 } 137}