import React, { useCallback, useRef } from 'react' import { Keyboard, ScrollView, ScrollViewProps, TextInput } from 'react-native' import { KeyboardView } from './keyboard_view' const FOCUSED_INPUT_BOTTOM_MARGIN = 32 type KeyboardScrollViewProps = Pick export function KeyboardScrollView({ children, contentContainerStyle }: KeyboardScrollViewProps) { const scrollViewRef = useRef(null) const scrollFocusedInputIntoView = useCallback(() => { const scrollView = scrollViewRef.current const input = TextInput.State.currentlyFocusedInput() if (!scrollView || !input) return const nativeScrollView = scrollView.getNativeScrollRef() const innerView = scrollView.getInnerViewRef() if (!nativeScrollView || !innerView) return nativeScrollView.measureInWindow((_scrollX, scrollTop, _scrollWidth, scrollHeight) => { const keyboardTop = Keyboard.metrics()?.screenY const scrollBottom = scrollTop + scrollHeight const visibleBottom = keyboardTop === undefined ? scrollBottom : Math.min(scrollBottom, keyboardTop) const visibleHeight = visibleBottom - scrollTop input.measureInWindow((_inputX, inputTop, _inputWidth, inputHeight) => { const inputBottom = inputTop + inputHeight + FOCUSED_INPUT_BOTTOM_MARGIN if (inputBottom <= visibleBottom) return input.measureLayout(innerView, (_left, contentTop, _contentWidth, contentHeight) => { scrollView.scrollTo({ y: contentTop + contentHeight + FOCUSED_INPUT_BOTTOM_MARGIN - visibleHeight, animated: true, }) }) }) }) }, []) return ( {children} ) }