UNPKG

@gorhom/bottom-sheet

Version:

A performant interactive bottom sheet with fully configurable options 🚀

86 lines (81 loc) • 3.19 kB
"use strict"; import { useEffect } from 'react'; import { Keyboard, Platform } from 'react-native'; import { runOnUI, useAnimatedReaction, useSharedValue, useWorkletCallback } from 'react-native-reanimated'; import { KEYBOARD_STATE } from '../constants'; const KEYBOARD_EVENT_MAPPER = { KEYBOARD_SHOW: Platform.select({ ios: 'keyboardWillShow', android: 'keyboardDidShow', default: '' }), KEYBOARD_HIDE: Platform.select({ ios: 'keyboardWillHide', android: 'keyboardDidHide', default: '' }) }; export const useKeyboard = () => { //#region variables const shouldHandleKeyboardEvents = useSharedValue(false); const keyboardState = useSharedValue(KEYBOARD_STATE.UNDETERMINED); const keyboardHeight = useSharedValue(0); const keyboardAnimationEasing = useSharedValue('keyboard'); const keyboardAnimationDuration = useSharedValue(500); // biome-ignore lint: to be addressed! const temporaryCachedKeyboardEvent = useSharedValue([]); //#endregion //#region worklets const handleKeyboardEvent = useWorkletCallback((state, height, duration, easing) => { if (state === KEYBOARD_STATE.SHOWN && !shouldHandleKeyboardEvents.value) { /** * if the keyboard event was fired before the `onFocus` on TextInput, * then we cache the input, and wait till the `shouldHandleKeyboardEvents` * to be updated then fire this function again. */ temporaryCachedKeyboardEvent.value = [state, height, duration, easing]; return; } keyboardHeight.value = state === KEYBOARD_STATE.SHOWN ? height : keyboardHeight.value; keyboardAnimationDuration.value = duration; keyboardAnimationEasing.value = easing; keyboardState.value = state; temporaryCachedKeyboardEvent.value = []; }, []); //#endregion //#region effects useEffect(() => { const handleOnKeyboardShow = event => { runOnUI(handleKeyboardEvent)(KEYBOARD_STATE.SHOWN, event.endCoordinates.height, event.duration, event.easing); }; const handleOnKeyboardHide = event => { runOnUI(handleKeyboardEvent)(KEYBOARD_STATE.HIDDEN, event.endCoordinates.height, event.duration, event.easing); }; const showSubscription = Keyboard.addListener(KEYBOARD_EVENT_MAPPER.KEYBOARD_SHOW, handleOnKeyboardShow); const hideSubscription = Keyboard.addListener(KEYBOARD_EVENT_MAPPER.KEYBOARD_HIDE, handleOnKeyboardHide); return () => { showSubscription.remove(); hideSubscription.remove(); }; }, [handleKeyboardEvent]); /** * This reaction is needed to handle the issue with multiline text input. * * @link https://github.com/gorhom/react-native-bottom-sheet/issues/411 */ useAnimatedReaction(() => shouldHandleKeyboardEvents.value, result => { const params = temporaryCachedKeyboardEvent.value; if (result && params.length > 0) { handleKeyboardEvent(params[0], params[1], params[2], params[3]); } }, []); //#endregion return { state: keyboardState, height: keyboardHeight, animationEasing: keyboardAnimationEasing, animationDuration: keyboardAnimationDuration, shouldHandleKeyboardEvents }; }; //# sourceMappingURL=useKeyboard.js.map