import React , { forwardRef , ReactNode , useEffect , useImperativeHandle , useRef , useState , } from 'react' ; import { StyleProp , View , ViewStyle } from 'react-native' ; import { RNKeyboard } from './module' ; interface IProps { style ? : StyleProp < ViewStyle > ; /**
     * If true, will keep the the keyboard area open even if the Keyboard is dismiss
     * Useful to switch to another view and then come back to the Keyboard view
     * NOTE: if false will not close the keyboard area to avoid layout jumping, use the close() method
     */ isOpen ? : boolean ; /**
     * Content to be placed under the Keyboard
     */ children : ReactNode ; /**
     * Until the keyboard shows once, we don't know it real height,
     * so we need a initial default height
     * (Default: 250)
     */ initialHeight ? : number ; /**
     * Minimum height for manually open view
     * (Default: 250)
     */ minHeight ? : number ; /**
     * Event fired when keyboard height changes
     */ onChange ? : ( isOpen : boolean , height : number ) => void ; } export type KeyboardAreaRef = { isOpen : ( ) => boolean ; open : ( ) => void ; close : ( ) => void ; } ; export const KeyboardArea = forwardRef < KeyboardAreaRef , IProps > ( ( { style , children , isOpen : externalOpen , initialHeight = 250 , minHeight = 250 , onChange , } , ref ) => { const isOpen = useRef ( false ) ; const forceOpen = useRef ( false ) ; const keyboardHeight = useRef ( initialHeight ) ; const [ currentHeight , setCurrentHeight ] = useState ( 0 ) ; const open = ( ) => { isOpen . current = true ; setCurrentHeight ( keyboardHeight . current ) ; if ( onChange ) { onChange ( true , keyboardHeight . current ) ; } } ; const close = ( ) => { isOpen . current = false ; setCurrentHeight ( 0 ) ; if ( onChange ) { onChange ( false , 0 ) ; } } ; useImperativeHandle ( ref , ( ) => ( { isOpen : ( ) => isOpen . current , open , close , } ) ) ; useEffect ( ( ) => { const keyboardHeightChanged = ( height ) => { if ( height > 0 && height !== keyboardHeight . current ) { keyboardHeight . current = height > minHeight ? height : minHeight ; } const needToOpen = forceOpen . current || height > 0 ; if ( needToOpen ) { open ( ) ; } else { close ( ) ; } } ; RNKeyboard . addKeyboardListener ( keyboardHeightChanged ) ; return ( ) => { RNKeyboard . removeKeyboardListener ( keyboardHeightChanged ) ; } ; } , [ ] ) ; useEffect ( ( ) => { forceOpen . current = externalOpen || false ; if ( forceOpen . current ) { open ( ) ; } } , [ externalOpen ] ) ; return < View style = { [ { height : currentHeight } , style ] } > { children } < /View>; } ) ;