react-native-keyboard-controller
Version:
Keyboard manager which works in identical way on both iOS and Android
190 lines (181 loc) • 7.65 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.KeyboardProvider = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _reactNativeIsEdgeToEdge = require("react-native-is-edge-to-edge");
var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
var _bindings = require("./bindings");
var _context = require("./context");
var _eventMappings = require("./event-mappings");
var _internal = require("./internal");
var _module = require("./module");
var _reanimated = require("./reanimated");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/* eslint react/jsx-sort-props: off */
const IS_EDGE_TO_EDGE = (0, _reactNativeIsEdgeToEdge.isEdgeToEdge)();
const KeyboardControllerViewAnimated = _reactNativeReanimated.default.createAnimatedComponent(_reactNative.Animated.createAnimatedComponent(_bindings.KeyboardControllerView));
const styles = _reactNative.StyleSheet.create({
container: {
flex: 1
},
hidden: {
display: "none",
position: "absolute"
}
});
// capture `Platform.OS` in separate variable to avoid deep workletization of entire RN package
// see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/393 and https://github.com/kirillzyusko/react-native-keyboard-controller/issues/294 for more details
const OS = _reactNative.Platform.OS;
/**
* A component that wrap your app. Under the hood it works with {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/keyboard-controller-view|KeyboardControllerView} to receive events during keyboard movements,
* maps these events to `Animated`/`Reanimated` values and store them in context.
*
* @param props - Provider props, such as `statusBarTranslucent`, `navigationBarTranslucent`, etc.
* @returns A component that should be mounted in root of your App layout.
* @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/keyboard-provider|Documentation} page for more details.
* @example
* ```tsx
* <KeyboardProvider>
* <NavigationContainer />
* </KeyboardProvider>
* ```
*/
const KeyboardProvider = props => {
const {
children,
statusBarTranslucent,
navigationBarTranslucent,
preserveEdgeToEdge,
enabled: initiallyEnabled = true,
preload = true
} = props;
// ref
const viewTagRef = (0, _react.useRef)(null);
// state
const [enabled, setEnabled] = (0, _react.useState)(initiallyEnabled);
// animated values
const progress = (0, _internal.useAnimatedValue)(0);
const height = (0, _internal.useAnimatedValue)(0);
// shared values
const progressSV = (0, _reactNativeReanimated.useSharedValue)(0);
const heightSV = (0, _reactNativeReanimated.useSharedValue)(0);
const layout = (0, _reactNativeReanimated.useSharedValue)(null);
const setKeyboardHandlers = (0, _internal.useEventHandlerRegistration)(_eventMappings.keyboardEventsMap, viewTagRef);
const setInputHandlers = (0, _internal.useEventHandlerRegistration)(_eventMappings.focusedInputEventsMap, viewTagRef);
// memo
const context = (0, _react.useMemo)(() => ({
enabled,
animated: {
progress: progress,
height: _reactNative.Animated.multiply(height, -1)
},
reanimated: {
progress: progressSV,
height: heightSV
},
layout,
setKeyboardHandlers,
setInputHandlers,
setEnabled
}), [enabled]);
const style = (0, _react.useMemo)(() => [styles.hidden, {
transform: [{
translateX: height
}, {
translateY: progress
}]
}], []);
const onKeyboardMove = (0, _react.useMemo)(() => _reactNative.Animated.event([{
nativeEvent: {
progress,
height
}
}],
// Setting useNativeDriver to true on web triggers a warning due to the absence of a native driver for web. Therefore, it is set to false.
{
useNativeDriver: _reactNative.Platform.OS !== "web"
}), []);
// handlers
const updateSharedValues = (event, platforms) => {
"worklet";
if (platforms.includes(OS)) {
// eslint-disable-next-line react-compiler/react-compiler
progressSV.value = event.progress;
heightSV.value = -event.height;
}
};
const keyboardHandler = (0, _reanimated.useAnimatedKeyboardHandler)({
onKeyboardMoveStart: event => {
"worklet";
updateSharedValues(event, ["ios"]);
},
onKeyboardMove: event => {
"worklet";
updateSharedValues(event, ["android"]);
},
onKeyboardMoveInteractive: event => {
"worklet";
updateSharedValues(event, ["android", "ios"]);
},
onKeyboardMoveEnd: event => {
"worklet";
updateSharedValues(event, ["android"]);
}
}, []);
const inputLayoutHandler = (0, _reanimated.useFocusedInputLayoutHandler)({
onFocusedInputLayoutChanged: e => {
"worklet";
if (e.target !== -1) {
layout.value = e;
} else {
layout.value = null;
}
}
}, []);
(0, _react.useEffect)(() => {
if (preload) {
_module.KeyboardController.preload();
}
}, [preload]);
if (__DEV__) {
(0, _reactNativeIsEdgeToEdge.controlEdgeToEdgeValues)({
statusBarTranslucent,
navigationBarTranslucent,
preserveEdgeToEdge
});
}
return /*#__PURE__*/_react.default.createElement(_context.KeyboardContext.Provider, {
value: context
}, /*#__PURE__*/_react.default.createElement(KeyboardControllerViewAnimated, {
ref: viewTagRef,
enabled: enabled,
navigationBarTranslucent: IS_EDGE_TO_EDGE || navigationBarTranslucent,
statusBarTranslucent: IS_EDGE_TO_EDGE || statusBarTranslucent,
preserveEdgeToEdge: IS_EDGE_TO_EDGE || preserveEdgeToEdge,
style: styles.container
// on*Reanimated prop must precede animated handlers to work correctly
,
onKeyboardMoveReanimated: keyboardHandler,
onKeyboardMoveStart: OS === "ios" ? onKeyboardMove : undefined,
onKeyboardMove: OS === "android" ? onKeyboardMove : undefined,
onKeyboardMoveInteractive: onKeyboardMove,
onKeyboardMoveEnd: OS === "android" ? onKeyboardMove : undefined,
onFocusedInputLayoutChangedReanimated: inputLayoutHandler
}, children), /*#__PURE__*/_react.default.createElement(_reactNative.Animated.View, {
// we are using this small hack, because if the component (where
// animated value has been used) is unmounted, then animation will
// stop receiving events (seems like it's react-native optimization).
// So we need to keep a reference to the animated value, to keep it's
// always mounted (keep a reference to an animated value).
//
// To test why it's needed, try to open screen which consumes Animated.Value
// then close it and open it again (for example 'Animated transition').
style: style
}));
};
exports.KeyboardProvider = KeyboardProvider;
//# sourceMappingURL=animated.js.map