UNPKG

react-native-keyboard-controller

Version:

Keyboard manager which works in identical way on both iOS and Android

126 lines (120 loc) 5.21 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useSmoothKeyboardHandler = void 0; var _reactNative = require("react-native"); var _reactNativeReanimated = require("react-native-reanimated"); var _hooks = require("../../hooks"); const IS_ANDROID_ELEVEN_OR_HIGHER = _reactNative.Platform.OS === "android" && _reactNative.Platform.Version >= 30; // on these platforms keyboard transitions will be smooth const IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS = IS_ANDROID_ELEVEN_OR_HIGHER || _reactNative.Platform.OS === "ios"; // on Android Telegram is not using androidx.core values and uses custom interpolation // duration is taken from here: https://github.com/DrKLO/Telegram/blob/e9a35cea54c06277c69d41b8e25d94b5d7ede065/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java#L39 // and bezier is taken from: https://github.com/DrKLO/Telegram/blob/e9a35cea54c06277c69d41b8e25d94b5d7ede065/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java#L40 const TELEGRAM_ANDROID_TIMING_CONFIG = { duration: 250, easing: _reactNativeReanimated.Easing.bezier(0.19919472913616398, 0.010644531250000006, 0.27920937042459737, 0.91025390625) }; /** * Hook that uses default transitions for iOS and Android > 11, and uses * custom interpolation on Android < 11 to achieve more smooth animation. * * @param handler - Object containing keyboard event handlers. * @param [deps] - Dependencies array for the effect. * @example * ```ts * useSmoothKeyboardHandler( * { * onStart: (e) => { * "worklet"; * * // your handler for keyboard start * }, * }, * [], * ); * ``` */ const useSmoothKeyboardHandler = (handler, deps) => { const target = (0, _reactNativeReanimated.useSharedValue)(-1); const height = (0, _reactNativeReanimated.useSharedValue)(0); const persistedHeight = (0, _reactNativeReanimated.useSharedValue)(0); const animatedKeyboardHeight = (0, _reactNativeReanimated.useSharedValue)(0); (0, _reactNativeReanimated.useAnimatedReaction)(() => { if (IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS) { return; } if (persistedHeight.value === 0) { return; } const event = { // it'll be always `TELEGRAM_ANDROID_TIMING_CONFIG.duration`, since we're running animation via `withTiming` duration: TELEGRAM_ANDROID_TIMING_CONFIG.duration, target: target.value, height: animatedKeyboardHeight.value, progress: animatedKeyboardHeight.value / persistedHeight.value }; return event; }, evt => { var _handler$onMove; if (!evt) { return; } (_handler$onMove = handler.onMove) === null || _handler$onMove === void 0 || _handler$onMove.call(handler, evt); // dispatch `onEnd` if (evt.height === height.value) { var _handler$onEnd; (_handler$onEnd = handler.onEnd) === null || _handler$onEnd === void 0 || _handler$onEnd.call(handler, evt); // eslint-disable-next-line react-compiler/react-compiler persistedHeight.value = height.value; } }, // REA uses own version of `DependencyList` and it's not compatible with the same type from React deps); (0, _hooks.useKeyboardHandler)({ onStart: e => { "worklet"; // immediately dispatch onStart/onEnd events if onStart dispatched with the same height // and don't wait for animation 250ms var _handler$onStart2; if (!IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS && e.height === persistedHeight.value) { var _handler$onStart, _handler$onEnd2; (_handler$onStart = handler.onStart) === null || _handler$onStart === void 0 || _handler$onStart.call(handler, e); (_handler$onEnd2 = handler.onEnd) === null || _handler$onEnd2 === void 0 || _handler$onEnd2.call(handler, e); return; } target.value = e.target; height.value = e.height; if (e.height > 0) { persistedHeight.value = e.height; } // if we are running on Android < 9, then we are using custom interpolation // to achieve smoother animation and use `animatedKeyboardHeight` as animation // driver if (!IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS) { animatedKeyboardHeight.value = (0, _reactNativeReanimated.withTiming)(e.height, TELEGRAM_ANDROID_TIMING_CONFIG); } (_handler$onStart2 = handler.onStart) === null || _handler$onStart2 === void 0 || _handler$onStart2.call(handler, { ...e, duration: IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS ? e.duration : TELEGRAM_ANDROID_TIMING_CONFIG.duration }); }, onMove: e => { "worklet"; if (IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS) { var _handler$onMove2; (_handler$onMove2 = handler.onMove) === null || _handler$onMove2 === void 0 || _handler$onMove2.call(handler, e); } }, onEnd: e => { "worklet"; if (IS_ANDROID_ELEVEN_OR_HIGHER_OR_IOS) { var _handler$onEnd3; (_handler$onEnd3 = handler.onEnd) === null || _handler$onEnd3 === void 0 || _handler$onEnd3.call(handler, e); } } }, deps); }; exports.useSmoothKeyboardHandler = useSmoothKeyboardHandler; //# sourceMappingURL=useSmoothKeyboardHandler.js.map