react-native-keyboard-controller 1.10.2 → 1.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js +14 -7
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
- package/lib/module/components/KeyboardAwareScrollView/index.js +14 -7
- package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
- package/lib/typescript/components/KeyboardAwareScrollView/index.d.ts +3 -38
- package/package.json +1 -1
- package/src/components/KeyboardAwareScrollView/index.tsx +20 -7
|
@@ -13,7 +13,7 @@ var _utils = require("./utils");
|
|
|
13
13
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
14
14
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
15
15
|
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
16
|
-
|
|
16
|
+
/*
|
|
17
17
|
* Everything begins from `onStart` handler. This handler is called every time,
|
|
18
18
|
* when keyboard changes its size or when focused `TextInput` was changed. In
|
|
19
19
|
* this handler we are calculating/memoizing values which later will be used
|
|
@@ -55,6 +55,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
55
55
|
let {
|
|
56
56
|
children,
|
|
57
57
|
bottomOffset = 0,
|
|
58
|
+
disableScrollOnKeyboardHide = false,
|
|
58
59
|
...rest
|
|
59
60
|
} = _ref;
|
|
60
61
|
const scrollViewAnimatedRef = (0, _reactNativeReanimated.useAnimatedRef)();
|
|
@@ -62,6 +63,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
62
63
|
const position = (0, _reactNativeReanimated.useSharedValue)(0);
|
|
63
64
|
const currentKeyboardFrameHeight = (0, _reactNativeReanimated.useSharedValue)(0);
|
|
64
65
|
const keyboardHeight = (0, _reactNativeReanimated.useSharedValue)(0);
|
|
66
|
+
const keyboardWillAppear = (0, _reactNativeReanimated.useSharedValue)(false);
|
|
65
67
|
const tag = (0, _reactNativeReanimated.useSharedValue)(-1);
|
|
66
68
|
const initialKeyboardSize = (0, _reactNativeReanimated.useSharedValue)(0);
|
|
67
69
|
const scrollBeforeKeyboardMovement = (0, _reactNativeReanimated.useSharedValue)(0);
|
|
@@ -129,7 +131,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
129
131
|
"worklet";
|
|
130
132
|
|
|
131
133
|
const keyboardWillChangeSize = keyboardHeight.value !== e.height && e.height > 0;
|
|
132
|
-
|
|
134
|
+
keyboardWillAppear.value = e.height > 0 && keyboardHeight.value === 0;
|
|
133
135
|
const keyboardWillHide = e.height === 0;
|
|
134
136
|
const focusWasChanged = tag.value !== e.target && e.target !== -1 || keyboardWillChangeSize;
|
|
135
137
|
if (keyboardWillChangeSize) {
|
|
@@ -140,7 +142,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
140
142
|
initialKeyboardSize.value = 0;
|
|
141
143
|
scrollPosition.value = scrollBeforeKeyboardMovement.value;
|
|
142
144
|
}
|
|
143
|
-
if (keyboardWillAppear || keyboardWillChangeSize || focusWasChanged) {
|
|
145
|
+
if (keyboardWillAppear.value || keyboardWillChangeSize || focusWasChanged) {
|
|
144
146
|
// persist scroll value
|
|
145
147
|
scrollPosition.value = position.value;
|
|
146
148
|
// just persist height - later will be used in interpolation
|
|
@@ -157,7 +159,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
157
159
|
// this value to achieve smooth hide effect
|
|
158
160
|
scrollBeforeKeyboardMovement.value = position.value;
|
|
159
161
|
}
|
|
160
|
-
if (focusWasChanged && !keyboardWillAppear) {
|
|
162
|
+
if (focusWasChanged && !keyboardWillAppear.value) {
|
|
161
163
|
// update position on scroll value, so `onEnd` handler
|
|
162
164
|
// will pick up correct values
|
|
163
165
|
position.value += maybeScroll(e.height, true);
|
|
@@ -167,7 +169,11 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
167
169
|
"worklet";
|
|
168
170
|
|
|
169
171
|
currentKeyboardFrameHeight.value = e.height;
|
|
170
|
-
|
|
172
|
+
|
|
173
|
+
// if the user has set disableScrollOnKeyboardHide, only auto-scroll when the keyboard opens
|
|
174
|
+
if (!disableScrollOnKeyboardHide || keyboardWillAppear.value) {
|
|
175
|
+
maybeScroll(e.height);
|
|
176
|
+
}
|
|
171
177
|
},
|
|
172
178
|
onEnd: e => {
|
|
173
179
|
"worklet";
|
|
@@ -175,7 +181,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
175
181
|
keyboardHeight.value = e.height;
|
|
176
182
|
scrollPosition.value = position.value;
|
|
177
183
|
}
|
|
178
|
-
}, [height, maybeScroll]);
|
|
184
|
+
}, [height, maybeScroll, disableScrollOnKeyboardHide]);
|
|
179
185
|
(0, _reactNativeReanimated.useAnimatedReaction)(() => input.value, (current, previous) => {
|
|
180
186
|
if ((current === null || current === void 0 ? void 0 : current.target) === (previous === null || previous === void 0 ? void 0 : previous.target) && (current === null || current === void 0 ? void 0 : current.layout.height) !== (previous === null || previous === void 0 ? void 0 : previous.layout.height)) {
|
|
181
187
|
const prevLayout = layout.value;
|
|
@@ -190,7 +196,8 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
190
196
|
return /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.ScrollView, _extends({
|
|
191
197
|
ref: scrollViewAnimatedRef
|
|
192
198
|
}, rest, {
|
|
193
|
-
|
|
199
|
+
// @ts-expect-error `onScrollReanimated` is a fake prop needed for reanimated to intercept scroll events
|
|
200
|
+
onScrollReanimated: onScroll,
|
|
194
201
|
scrollEventThrottle: 16
|
|
195
202
|
}), children, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, {
|
|
196
203
|
style: view
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_reactNativeKeyboardController","_useSmoothKeyboardHandler","_utils","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","_extends","assign","bind","target","i","arguments","length","source","apply","KeyboardAwareScrollView","_ref","children","bottomOffset","rest","scrollViewAnimatedRef","useAnimatedRef","scrollPosition","useSharedValue","position","currentKeyboardFrameHeight","keyboardHeight","tag","initialKeyboardSize","scrollBeforeKeyboardMovement","input","useReanimatedFocusedInput","layout","height","useWindowDimensions","onScroll","useAnimatedScrollHandler","e","value","contentOffset","y","maybeScroll","useCallback","_layout$value","_layout$value2","animated","undefined","visibleRect","absoluteY","inputHeight","point","interpolatedScrollTo","interpolate","targetScrollY","Math","max","scrollTo","positionOnScreen","topOfScreen","onChangeText","_layout$value3","_input$value","prevScrollPosition","prevLayout","onChangeTextHandler","useMemo","debounce","useFocusedInputHandler","useSmoothKeyboardHandler","onStart","keyboardWillChangeSize","keyboardWillAppear","keyboardWillHide","focusWasChanged","onMove","onEnd","useAnimatedReaction","current","previous","view","useAnimatedStyle","paddingBottom","createElement","ScrollView","ref","scrollEventThrottle","View","style","_default","exports"],"sources":["index.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { useWindowDimensions } from \"react-native\";\nimport Reanimated, {\n interpolate,\n scrollTo,\n useAnimatedReaction,\n useAnimatedRef,\n useAnimatedScrollHandler,\n useAnimatedStyle,\n useSharedValue,\n} from \"react-native-reanimated\";\n\nimport {\n useFocusedInputHandler,\n useReanimatedFocusedInput,\n} from \"react-native-keyboard-controller\";\n\nimport { useSmoothKeyboardHandler } from \"./useSmoothKeyboardHandler\";\nimport { debounce } from \"./utils\";\n\nimport type { FC } from \"react\";\nimport type { ScrollViewProps } from \"react-native\";\nimport type { FocusedInputLayoutChangedEvent } from \"react-native-keyboard-controller\";\n\ntype KeyboardAwareScrollViewProps = {\n bottomOffset?: number;\n} & ScrollViewProps;\n\n/**\n * Everything begins from `onStart` handler. This handler is called every time,\n * when keyboard changes its size or when focused `TextInput` was changed. In\n * this handler we are calculating/memoizing values which later will be used\n * during layout movement. For that we calculate:\n * - layout of focused field (`layout`) - to understand whether there will be overlap\n * - initial keyboard size (`initialKeyboardSize`) - used in scroll interpolation\n * - future keyboard height (`keyboardHeight`) - used in scroll interpolation\n * - current scroll position (`scrollPosition`) - used to scroll from this point\n *\n * Once we've calculated all necessary variables - we can actually start to use them.\n * It happens in `onMove` handler - this function simply calls `maybeScroll` with\n * current keyboard frame height. This functions makes the smooth transition.\n *\n * When the transition has finished we go to `onEnd` handler. In this handler\n * we verify, that the current field is not overlapped within a keyboard frame.\n * For full `onStart`/`onMove`/`onEnd` flow it may look like a redundant thing,\n * however there could be some cases, when `onMove` is not called:\n * - on iOS when TextInput was changed - keyboard transition is instant\n * - on Android when TextInput was changed and keyboard size wasn't changed\n * So `onEnd` handler handle the case, when `onMove` wasn't triggered.\n *\n * ====================================================================================================================+\n * -----------------------------------------------------Flow chart-----------------------------------------------------+\n * ====================================================================================================================+\n *\n * +============================+ +============================+ +==================================+\n * + User Press on TextInput + => + Keyboard starts showing + => + As keyboard moves frame by frame + =>\n * + + + (run `onStart`) + + `onMove` is getting called +\n * +============================+ +============================+ +==================================+\n *\n *\n * +============================+ +============================+ +=====================================+\n * + Keyboard is shown and we + => + User moved focus to + => + Only `onStart`/`onEnd` maybe called +\n * + call `onEnd` handler + + another `TextInput` + + (without involving `onMove`) +\n * +============================+ +============================+ +=====================================+\n *\n */\nconst KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({\n children,\n bottomOffset = 0,\n ...rest\n}) => {\n const scrollViewAnimatedRef = useAnimatedRef<Reanimated.ScrollView>();\n const scrollPosition = useSharedValue(0);\n const position = useSharedValue(0);\n const currentKeyboardFrameHeight = useSharedValue(0);\n const keyboardHeight = useSharedValue(0);\n const tag = useSharedValue(-1);\n const initialKeyboardSize = useSharedValue(0);\n const scrollBeforeKeyboardMovement = useSharedValue(0);\n const { input } = useReanimatedFocusedInput();\n const layout = useSharedValue<FocusedInputLayoutChangedEvent | null>(null);\n\n const { height } = useWindowDimensions();\n\n const onScroll = useAnimatedScrollHandler(\n {\n onScroll: (e) => {\n position.value = e.contentOffset.y;\n },\n },\n [],\n );\n\n /**\n * Function that will scroll a ScrollView as keyboard gets moving\n */\n const maybeScroll = useCallback(\n (e: number, animated: boolean = false) => {\n \"worklet\";\n\n const visibleRect = height - keyboardHeight.value;\n const absoluteY = layout.value?.layout.absoluteY || 0;\n const inputHeight = layout.value?.layout.height || 0;\n const point = absoluteY + inputHeight;\n\n if (visibleRect - point <= bottomOffset) {\n const interpolatedScrollTo = interpolate(\n e,\n [initialKeyboardSize.value, keyboardHeight.value],\n [0, keyboardHeight.value - (height - point) + bottomOffset],\n );\n const targetScrollY =\n Math.max(interpolatedScrollTo, 0) + scrollPosition.value;\n scrollTo(scrollViewAnimatedRef, 0, targetScrollY, animated);\n\n return interpolatedScrollTo;\n }\n\n if (absoluteY < 0) {\n const positionOnScreen = visibleRect - inputHeight - bottomOffset;\n const topOfScreen = scrollPosition.value + absoluteY;\n\n scrollTo(\n scrollViewAnimatedRef,\n 0,\n topOfScreen - positionOnScreen,\n animated,\n );\n }\n\n return 0;\n },\n [bottomOffset],\n );\n\n const onChangeText = useCallback(() => {\n \"worklet\";\n\n // if typing a text caused layout shift, then we need to ignore this handler\n // because this event will be handled in `useAnimatedReaction` below\n if (layout.value?.layout.height !== input.value?.layout.height) {\n return;\n }\n\n const prevScrollPosition = scrollPosition.value;\n const prevLayout = layout.value;\n\n scrollPosition.value = position.value;\n layout.value = input.value;\n maybeScroll(keyboardHeight.value, true);\n scrollPosition.value = prevScrollPosition;\n layout.value = prevLayout;\n }, [maybeScroll]);\n const onChangeTextHandler = useMemo(\n () => debounce(onChangeText, 200),\n [onChangeText],\n );\n\n useFocusedInputHandler(\n {\n onChangeText: onChangeTextHandler,\n },\n [onChangeTextHandler],\n );\n\n useSmoothKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n const keyboardWillChangeSize =\n keyboardHeight.value !== e.height && e.height > 0;\n const keyboardWillAppear = e.height > 0 && keyboardHeight.value === 0;\n const keyboardWillHide = e.height === 0;\n const focusWasChanged =\n (tag.value !== e.target && e.target !== -1) || keyboardWillChangeSize;\n\n if (keyboardWillChangeSize) {\n initialKeyboardSize.value = keyboardHeight.value;\n }\n\n if (keyboardWillHide) {\n // on back transition need to interpolate as [0, keyboardHeight]\n initialKeyboardSize.value = 0;\n scrollPosition.value = scrollBeforeKeyboardMovement.value;\n }\n\n if (keyboardWillAppear || keyboardWillChangeSize || focusWasChanged) {\n // persist scroll value\n scrollPosition.value = position.value;\n // just persist height - later will be used in interpolation\n keyboardHeight.value = e.height;\n }\n\n // focus was changed\n if (focusWasChanged) {\n tag.value = e.target;\n\n // save position of focused text input when keyboard starts to move\n layout.value = input.value;\n // save current scroll position - when keyboard will hide we'll reuse\n // this value to achieve smooth hide effect\n scrollBeforeKeyboardMovement.value = position.value;\n }\n\n if (focusWasChanged && !keyboardWillAppear) {\n // update position on scroll value, so `onEnd` handler\n // will pick up correct values\n position.value += maybeScroll(e.height, true);\n }\n },\n onMove: (e) => {\n \"worklet\";\n\n currentKeyboardFrameHeight.value = e.height;\n\n maybeScroll(e.height);\n },\n onEnd: (e) => {\n \"worklet\";\n\n keyboardHeight.value = e.height;\n scrollPosition.value = position.value;\n },\n },\n [height, maybeScroll],\n );\n\n useAnimatedReaction(\n () => input.value,\n (current, previous) => {\n if (\n current?.target === previous?.target &&\n current?.layout.height !== previous?.layout.height\n ) {\n const prevLayout = layout.value;\n\n layout.value = input.value;\n scrollPosition.value += maybeScroll(keyboardHeight.value, true);\n layout.value = prevLayout;\n }\n },\n [],\n );\n\n const view = useAnimatedStyle(\n () => ({\n paddingBottom: currentKeyboardFrameHeight.value,\n }),\n [],\n );\n\n return (\n <Reanimated.ScrollView\n ref={scrollViewAnimatedRef}\n {...rest}\n onScroll={onScroll}\n scrollEventThrottle={16}\n >\n {children}\n <Reanimated.View style={view} />\n </Reanimated.ScrollView>\n );\n};\n\nexport default KeyboardAwareScrollView;\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AACA,IAAAE,sBAAA,GAAAH,uBAAA,CAAAC,OAAA;AAUA,IAAAG,8BAAA,GAAAH,OAAA;AAKA,IAAAI,yBAAA,GAAAJ,OAAA;AACA,IAAAK,MAAA,GAAAL,OAAA;AAAmC,SAAAM,yBAAAC,WAAA,eAAAC,OAAA,kCAAAC,iBAAA,OAAAD,OAAA,QAAAE,gBAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,WAAA,WAAAA,WAAA,GAAAG,gBAAA,GAAAD,iBAAA,KAAAF,WAAA;AAAA,SAAAR,wBAAAY,GAAA,EAAAJ,WAAA,SAAAA,WAAA,IAAAI,GAAA,IAAAA,GAAA,CAAAC,UAAA,WAAAD,GAAA,QAAAA,GAAA,oBAAAA,GAAA,wBAAAA,GAAA,4BAAAE,OAAA,EAAAF,GAAA,UAAAG,KAAA,GAAAR,wBAAA,CAAAC,WAAA,OAAAO,KAAA,IAAAA,KAAA,CAAAC,GAAA,CAAAJ,GAAA,YAAAG,KAAA,CAAAE,GAAA,CAAAL,GAAA,SAAAM,MAAA,WAAAC,qBAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,GAAA,IAAAX,GAAA,QAAAW,GAAA,kBAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAd,GAAA,EAAAW,GAAA,SAAAI,IAAA,GAAAR,qBAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAV,GAAA,EAAAW,GAAA,cAAAI,IAAA,KAAAA,IAAA,CAAAV,GAAA,IAAAU,IAAA,CAAAC,GAAA,KAAAR,MAAA,CAAAC,cAAA,CAAAH,MAAA,EAAAK,GAAA,EAAAI,IAAA,YAAAT,MAAA,CAAAK,GAAA,IAAAX,GAAA,CAAAW,GAAA,SAAAL,MAAA,CAAAJ,OAAA,GAAAF,GAAA,MAAAG,KAAA,IAAAA,KAAA,CAAAa,GAAA,CAAAhB,GAAA,EAAAM,MAAA,YAAAA,MAAA;AAAA,SAAAW,SAAA,IAAAA,QAAA,GAAAT,MAAA,CAAAU,MAAA,GAAAV,MAAA,CAAAU,MAAA,CAAAC,IAAA,eAAAC,MAAA,aAAAC,CAAA,MAAAA,CAAA,GAAAC,SAAA,CAAAC,MAAA,EAAAF,CAAA,UAAAG,MAAA,GAAAF,SAAA,CAAAD,CAAA,YAAAV,GAAA,IAAAa,MAAA,QAAAhB,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAU,MAAA,EAAAb,GAAA,KAAAS,MAAA,CAAAT,GAAA,IAAAa,MAAA,CAAAb,GAAA,gBAAAS,MAAA,YAAAH,QAAA,CAAAQ,KAAA,OAAAH,SAAA;AAUnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMI,uBAAyD,GAAGC,IAAA,IAI5D;EAAA,IAJ6D;IACjEC,QAAQ;IACRC,YAAY,GAAG,CAAC;IAChB,GAAGC;EACL,CAAC,GAAAH,IAAA;EACC,MAAMI,qBAAqB,GAAG,IAAAC,qCAAc,EAAwB,CAAC;EACrE,MAAMC,cAAc,GAAG,IAAAC,qCAAc,EAAC,CAAC,CAAC;EACxC,MAAMC,QAAQ,GAAG,IAAAD,qCAAc,EAAC,CAAC,CAAC;EAClC,MAAME,0BAA0B,GAAG,IAAAF,qCAAc,EAAC,CAAC,CAAC;EACpD,MAAMG,cAAc,GAAG,IAAAH,qCAAc,EAAC,CAAC,CAAC;EACxC,MAAMI,GAAG,GAAG,IAAAJ,qCAAc,EAAC,CAAC,CAAC,CAAC;EAC9B,MAAMK,mBAAmB,GAAG,IAAAL,qCAAc,EAAC,CAAC,CAAC;EAC7C,MAAMM,4BAA4B,GAAG,IAAAN,qCAAc,EAAC,CAAC,CAAC;EACtD,MAAM;IAAEO;EAAM,CAAC,GAAG,IAAAC,wDAAyB,EAAC,CAAC;EAC7C,MAAMC,MAAM,GAAG,IAAAT,qCAAc,EAAwC,IAAI,CAAC;EAE1E,MAAM;IAAEU;EAAO,CAAC,GAAG,IAAAC,gCAAmB,EAAC,CAAC;EAExC,MAAMC,QAAQ,GAAG,IAAAC,+CAAwB,EACvC;IACED,QAAQ,EAAGE,CAAC,IAAK;MACfb,QAAQ,CAACc,KAAK,GAAGD,CAAC,CAACE,aAAa,CAACC,CAAC;IACpC;EACF,CAAC,EACD,EACF,CAAC;;EAED;AACF;AACA;EACE,MAAMC,WAAW,GAAG,IAAAC,kBAAW,EAC7B,UAACL,CAAS,EAAgC;IACxC,SAAS;;IAAC,IAAAM,aAAA,EAAAC,cAAA;IAAA,IADAC,QAAiB,GAAAlC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAmC,SAAA,GAAAnC,SAAA,MAAG,KAAK;IAGnC,MAAMoC,WAAW,GAAGd,MAAM,GAAGP,cAAc,CAACY,KAAK;IACjD,MAAMU,SAAS,GAAG,EAAAL,aAAA,GAAAX,MAAM,CAACM,KAAK,cAAAK,aAAA,uBAAZA,aAAA,CAAcX,MAAM,CAACgB,SAAS,KAAI,CAAC;IACrD,MAAMC,WAAW,GAAG,EAAAL,cAAA,GAAAZ,MAAM,CAACM,KAAK,cAAAM,cAAA,uBAAZA,cAAA,CAAcZ,MAAM,CAACC,MAAM,KAAI,CAAC;IACpD,MAAMiB,KAAK,GAAGF,SAAS,GAAGC,WAAW;IAErC,IAAIF,WAAW,GAAGG,KAAK,IAAIhC,YAAY,EAAE;MACvC,MAAMiC,oBAAoB,GAAG,IAAAC,kCAAW,EACtCf,CAAC,EACD,CAACT,mBAAmB,CAACU,KAAK,EAAEZ,cAAc,CAACY,KAAK,CAAC,EACjD,CAAC,CAAC,EAAEZ,cAAc,CAACY,KAAK,IAAIL,MAAM,GAAGiB,KAAK,CAAC,GAAGhC,YAAY,CAC5D,CAAC;MACD,MAAMmC,aAAa,GACjBC,IAAI,CAACC,GAAG,CAACJ,oBAAoB,EAAE,CAAC,CAAC,GAAG7B,cAAc,CAACgB,KAAK;MAC1D,IAAAkB,+BAAQ,EAACpC,qBAAqB,EAAE,CAAC,EAAEiC,aAAa,EAAER,QAAQ,CAAC;MAE3D,OAAOM,oBAAoB;IAC7B;IAEA,IAAIH,SAAS,GAAG,CAAC,EAAE;MACjB,MAAMS,gBAAgB,GAAGV,WAAW,GAAGE,WAAW,GAAG/B,YAAY;MACjE,MAAMwC,WAAW,GAAGpC,cAAc,CAACgB,KAAK,GAAGU,SAAS;MAEpD,IAAAQ,+BAAQ,EACNpC,qBAAqB,EACrB,CAAC,EACDsC,WAAW,GAAGD,gBAAgB,EAC9BZ,QACF,CAAC;IACH;IAEA,OAAO,CAAC;EACV,CAAC,EACD,CAAC3B,YAAY,CACf,CAAC;EAED,MAAMyC,YAAY,GAAG,IAAAjB,kBAAW,EAAC,MAAM;IACrC,SAAS;;IAET;IACA;IAAA,IAAAkB,cAAA,EAAAC,YAAA;IACA,IAAI,EAAAD,cAAA,GAAA5B,MAAM,CAACM,KAAK,cAAAsB,cAAA,uBAAZA,cAAA,CAAc5B,MAAM,CAACC,MAAM,QAAA4B,YAAA,GAAK/B,KAAK,CAACQ,KAAK,cAAAuB,YAAA,uBAAXA,YAAA,CAAa7B,MAAM,CAACC,MAAM,GAAE;MAC9D;IACF;IAEA,MAAM6B,kBAAkB,GAAGxC,cAAc,CAACgB,KAAK;IAC/C,MAAMyB,UAAU,GAAG/B,MAAM,CAACM,KAAK;IAE/BhB,cAAc,CAACgB,KAAK,GAAGd,QAAQ,CAACc,KAAK;IACrCN,MAAM,CAACM,KAAK,GAAGR,KAAK,CAACQ,KAAK;IAC1BG,WAAW,CAACf,cAAc,CAACY,KAAK,EAAE,IAAI,CAAC;IACvChB,cAAc,CAACgB,KAAK,GAAGwB,kBAAkB;IACzC9B,MAAM,CAACM,KAAK,GAAGyB,UAAU;EAC3B,CAAC,EAAE,CAACtB,WAAW,CAAC,CAAC;EACjB,MAAMuB,mBAAmB,GAAG,IAAAC,cAAO,EACjC,MAAM,IAAAC,eAAQ,EAACP,YAAY,EAAE,GAAG,CAAC,EACjC,CAACA,YAAY,CACf,CAAC;EAED,IAAAQ,qDAAsB,EACpB;IACER,YAAY,EAAEK;EAChB,CAAC,EACD,CAACA,mBAAmB,CACtB,CAAC;EAED,IAAAI,kDAAwB,EACtB;IACEC,OAAO,EAAGhC,CAAC,IAAK;MACd,SAAS;;MAET,MAAMiC,sBAAsB,GAC1B5C,cAAc,CAACY,KAAK,KAAKD,CAAC,CAACJ,MAAM,IAAII,CAAC,CAACJ,MAAM,GAAG,CAAC;MACnD,MAAMsC,kBAAkB,GAAGlC,CAAC,CAACJ,MAAM,GAAG,CAAC,IAAIP,cAAc,CAACY,KAAK,KAAK,CAAC;MACrE,MAAMkC,gBAAgB,GAAGnC,CAAC,CAACJ,MAAM,KAAK,CAAC;MACvC,MAAMwC,eAAe,GAClB9C,GAAG,CAACW,KAAK,KAAKD,CAAC,CAAC5B,MAAM,IAAI4B,CAAC,CAAC5B,MAAM,KAAK,CAAC,CAAC,IAAK6D,sBAAsB;MAEvE,IAAIA,sBAAsB,EAAE;QAC1B1C,mBAAmB,CAACU,KAAK,GAAGZ,cAAc,CAACY,KAAK;MAClD;MAEA,IAAIkC,gBAAgB,EAAE;QACpB;QACA5C,mBAAmB,CAACU,KAAK,GAAG,CAAC;QAC7BhB,cAAc,CAACgB,KAAK,GAAGT,4BAA4B,CAACS,KAAK;MAC3D;MAEA,IAAIiC,kBAAkB,IAAID,sBAAsB,IAAIG,eAAe,EAAE;QACnE;QACAnD,cAAc,CAACgB,KAAK,GAAGd,QAAQ,CAACc,KAAK;QACrC;QACAZ,cAAc,CAACY,KAAK,GAAGD,CAAC,CAACJ,MAAM;MACjC;;MAEA;MACA,IAAIwC,eAAe,EAAE;QACnB9C,GAAG,CAACW,KAAK,GAAGD,CAAC,CAAC5B,MAAM;;QAEpB;QACAuB,MAAM,CAACM,KAAK,GAAGR,KAAK,CAACQ,KAAK;QAC1B;QACA;QACAT,4BAA4B,CAACS,KAAK,GAAGd,QAAQ,CAACc,KAAK;MACrD;MAEA,IAAImC,eAAe,IAAI,CAACF,kBAAkB,EAAE;QAC1C;QACA;QACA/C,QAAQ,CAACc,KAAK,IAAIG,WAAW,CAACJ,CAAC,CAACJ,MAAM,EAAE,IAAI,CAAC;MAC/C;IACF,CAAC;IACDyC,MAAM,EAAGrC,CAAC,IAAK;MACb,SAAS;;MAETZ,0BAA0B,CAACa,KAAK,GAAGD,CAAC,CAACJ,MAAM;MAE3CQ,WAAW,CAACJ,CAAC,CAACJ,MAAM,CAAC;IACvB,CAAC;IACD0C,KAAK,EAAGtC,CAAC,IAAK;MACZ,SAAS;;MAETX,cAAc,CAACY,KAAK,GAAGD,CAAC,CAACJ,MAAM;MAC/BX,cAAc,CAACgB,KAAK,GAAGd,QAAQ,CAACc,KAAK;IACvC;EACF,CAAC,EACD,CAACL,MAAM,EAAEQ,WAAW,CACtB,CAAC;EAED,IAAAmC,0CAAmB,EACjB,MAAM9C,KAAK,CAACQ,KAAK,EACjB,CAACuC,OAAO,EAAEC,QAAQ,KAAK;IACrB,IACE,CAAAD,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEpE,MAAM,OAAKqE,QAAQ,aAARA,QAAQ,uBAARA,QAAQ,CAAErE,MAAM,KACpC,CAAAoE,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAE7C,MAAM,CAACC,MAAM,OAAK6C,QAAQ,aAARA,QAAQ,uBAARA,QAAQ,CAAE9C,MAAM,CAACC,MAAM,GAClD;MACA,MAAM8B,UAAU,GAAG/B,MAAM,CAACM,KAAK;MAE/BN,MAAM,CAACM,KAAK,GAAGR,KAAK,CAACQ,KAAK;MAC1BhB,cAAc,CAACgB,KAAK,IAAIG,WAAW,CAACf,cAAc,CAACY,KAAK,EAAE,IAAI,CAAC;MAC/DN,MAAM,CAACM,KAAK,GAAGyB,UAAU;IAC3B;EACF,CAAC,EACD,EACF,CAAC;EAED,MAAMgB,IAAI,GAAG,IAAAC,uCAAgB,EAC3B,OAAO;IACLC,aAAa,EAAExD,0BAA0B,CAACa;EAC5C,CAAC,CAAC,EACF,EACF,CAAC;EAED,oBACE9D,MAAA,CAAAe,OAAA,CAAA2F,aAAA,CAACtG,sBAAA,CAAAW,OAAU,CAAC4F,UAAU,EAAA7E,QAAA;IACpB8E,GAAG,EAAEhE;EAAsB,GACvBD,IAAI;IACRgB,QAAQ,EAAEA,QAAS;IACnBkD,mBAAmB,EAAE;EAAG,IAEvBpE,QAAQ,eACTzC,MAAA,CAAAe,OAAA,CAAA2F,aAAA,CAACtG,sBAAA,CAAAW,OAAU,CAAC+F,IAAI;IAACC,KAAK,EAAER;EAAK,CAAE,CACV,CAAC;AAE5B,CAAC;AAAC,IAAAS,QAAA,GAEazE,uBAAuB;AAAA0E,OAAA,CAAAlG,OAAA,GAAAiG,QAAA"}
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_reactNativeKeyboardController","_useSmoothKeyboardHandler","_utils","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","_extends","assign","bind","target","i","arguments","length","source","apply","KeyboardAwareScrollView","_ref","children","bottomOffset","disableScrollOnKeyboardHide","rest","scrollViewAnimatedRef","useAnimatedRef","scrollPosition","useSharedValue","position","currentKeyboardFrameHeight","keyboardHeight","keyboardWillAppear","tag","initialKeyboardSize","scrollBeforeKeyboardMovement","input","useReanimatedFocusedInput","layout","height","useWindowDimensions","onScroll","useAnimatedScrollHandler","e","value","contentOffset","y","maybeScroll","useCallback","_layout$value","_layout$value2","animated","undefined","visibleRect","absoluteY","inputHeight","point","interpolatedScrollTo","interpolate","targetScrollY","Math","max","scrollTo","positionOnScreen","topOfScreen","onChangeText","_layout$value3","_input$value","prevScrollPosition","prevLayout","onChangeTextHandler","useMemo","debounce","useFocusedInputHandler","useSmoothKeyboardHandler","onStart","keyboardWillChangeSize","keyboardWillHide","focusWasChanged","onMove","onEnd","useAnimatedReaction","current","previous","view","useAnimatedStyle","paddingBottom","createElement","ScrollView","ref","onScrollReanimated","scrollEventThrottle","View","style","_default","exports"],"sources":["index.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { useWindowDimensions } from \"react-native\";\nimport Reanimated, {\n interpolate,\n scrollTo,\n useAnimatedReaction,\n useAnimatedRef,\n useAnimatedScrollHandler,\n useAnimatedStyle,\n useSharedValue,\n} from \"react-native-reanimated\";\n\nimport {\n useFocusedInputHandler,\n useReanimatedFocusedInput,\n} from \"react-native-keyboard-controller\";\n\nimport { useSmoothKeyboardHandler } from \"./useSmoothKeyboardHandler\";\nimport { debounce } from \"./utils\";\n\nimport type { FC } from \"react\";\nimport type { ScrollViewProps } from \"react-native\";\nimport type { FocusedInputLayoutChangedEvent } from \"react-native-keyboard-controller\";\n\ntype KeyboardAwareScrollViewProps = {\n /** The distance between keyboard and focused `TextInput` when keyboard is shown. Default is `0`. */\n bottomOffset?: number;\n /** Prevents automatic scrolling of the `ScrollView` when the keyboard gets hidden, maintaining the current screen position. Default is `false`. */\n disableScrollOnKeyboardHide?: boolean;\n} & ScrollViewProps;\n\n/*\n * Everything begins from `onStart` handler. This handler is called every time,\n * when keyboard changes its size or when focused `TextInput` was changed. In\n * this handler we are calculating/memoizing values which later will be used\n * during layout movement. For that we calculate:\n * - layout of focused field (`layout`) - to understand whether there will be overlap\n * - initial keyboard size (`initialKeyboardSize`) - used in scroll interpolation\n * - future keyboard height (`keyboardHeight`) - used in scroll interpolation\n * - current scroll position (`scrollPosition`) - used to scroll from this point\n *\n * Once we've calculated all necessary variables - we can actually start to use them.\n * It happens in `onMove` handler - this function simply calls `maybeScroll` with\n * current keyboard frame height. This functions makes the smooth transition.\n *\n * When the transition has finished we go to `onEnd` handler. In this handler\n * we verify, that the current field is not overlapped within a keyboard frame.\n * For full `onStart`/`onMove`/`onEnd` flow it may look like a redundant thing,\n * however there could be some cases, when `onMove` is not called:\n * - on iOS when TextInput was changed - keyboard transition is instant\n * - on Android when TextInput was changed and keyboard size wasn't changed\n * So `onEnd` handler handle the case, when `onMove` wasn't triggered.\n *\n * ====================================================================================================================+\n * -----------------------------------------------------Flow chart-----------------------------------------------------+\n * ====================================================================================================================+\n *\n * +============================+ +============================+ +==================================+\n * + User Press on TextInput + => + Keyboard starts showing + => + As keyboard moves frame by frame + =>\n * + + + (run `onStart`) + + `onMove` is getting called +\n * +============================+ +============================+ +==================================+\n *\n *\n * +============================+ +============================+ +=====================================+\n * + Keyboard is shown and we + => + User moved focus to + => + Only `onStart`/`onEnd` maybe called +\n * + call `onEnd` handler + + another `TextInput` + + (without involving `onMove`) +\n * +============================+ +============================+ +=====================================+\n *\n */\nconst KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({\n children,\n bottomOffset = 0,\n disableScrollOnKeyboardHide = false,\n ...rest\n}) => {\n const scrollViewAnimatedRef = useAnimatedRef<Reanimated.ScrollView>();\n const scrollPosition = useSharedValue(0);\n const position = useSharedValue(0);\n const currentKeyboardFrameHeight = useSharedValue(0);\n const keyboardHeight = useSharedValue(0);\n const keyboardWillAppear = useSharedValue(false);\n const tag = useSharedValue(-1);\n const initialKeyboardSize = useSharedValue(0);\n const scrollBeforeKeyboardMovement = useSharedValue(0);\n const { input } = useReanimatedFocusedInput();\n const layout = useSharedValue<FocusedInputLayoutChangedEvent | null>(null);\n\n const { height } = useWindowDimensions();\n\n const onScroll = useAnimatedScrollHandler(\n {\n onScroll: (e) => {\n position.value = e.contentOffset.y;\n },\n },\n [],\n );\n\n /**\n * Function that will scroll a ScrollView as keyboard gets moving\n */\n const maybeScroll = useCallback(\n (e: number, animated: boolean = false) => {\n \"worklet\";\n\n const visibleRect = height - keyboardHeight.value;\n const absoluteY = layout.value?.layout.absoluteY || 0;\n const inputHeight = layout.value?.layout.height || 0;\n const point = absoluteY + inputHeight;\n\n if (visibleRect - point <= bottomOffset) {\n const interpolatedScrollTo = interpolate(\n e,\n [initialKeyboardSize.value, keyboardHeight.value],\n [0, keyboardHeight.value - (height - point) + bottomOffset],\n );\n const targetScrollY =\n Math.max(interpolatedScrollTo, 0) + scrollPosition.value;\n scrollTo(scrollViewAnimatedRef, 0, targetScrollY, animated);\n\n return interpolatedScrollTo;\n }\n\n if (absoluteY < 0) {\n const positionOnScreen = visibleRect - inputHeight - bottomOffset;\n const topOfScreen = scrollPosition.value + absoluteY;\n\n scrollTo(\n scrollViewAnimatedRef,\n 0,\n topOfScreen - positionOnScreen,\n animated,\n );\n }\n\n return 0;\n },\n [bottomOffset],\n );\n\n const onChangeText = useCallback(() => {\n \"worklet\";\n\n // if typing a text caused layout shift, then we need to ignore this handler\n // because this event will be handled in `useAnimatedReaction` below\n if (layout.value?.layout.height !== input.value?.layout.height) {\n return;\n }\n\n const prevScrollPosition = scrollPosition.value;\n const prevLayout = layout.value;\n\n scrollPosition.value = position.value;\n layout.value = input.value;\n maybeScroll(keyboardHeight.value, true);\n scrollPosition.value = prevScrollPosition;\n layout.value = prevLayout;\n }, [maybeScroll]);\n const onChangeTextHandler = useMemo(\n () => debounce(onChangeText, 200),\n [onChangeText],\n );\n\n useFocusedInputHandler(\n {\n onChangeText: onChangeTextHandler,\n },\n [onChangeTextHandler],\n );\n\n useSmoothKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n const keyboardWillChangeSize =\n keyboardHeight.value !== e.height && e.height > 0;\n keyboardWillAppear.value = e.height > 0 && keyboardHeight.value === 0;\n const keyboardWillHide = e.height === 0;\n const focusWasChanged =\n (tag.value !== e.target && e.target !== -1) || keyboardWillChangeSize;\n\n if (keyboardWillChangeSize) {\n initialKeyboardSize.value = keyboardHeight.value;\n }\n\n if (keyboardWillHide) {\n // on back transition need to interpolate as [0, keyboardHeight]\n initialKeyboardSize.value = 0;\n scrollPosition.value = scrollBeforeKeyboardMovement.value;\n }\n\n if (\n keyboardWillAppear.value ||\n keyboardWillChangeSize ||\n focusWasChanged\n ) {\n // persist scroll value\n scrollPosition.value = position.value;\n // just persist height - later will be used in interpolation\n keyboardHeight.value = e.height;\n }\n\n // focus was changed\n if (focusWasChanged) {\n tag.value = e.target;\n\n // save position of focused text input when keyboard starts to move\n layout.value = input.value;\n // save current scroll position - when keyboard will hide we'll reuse\n // this value to achieve smooth hide effect\n scrollBeforeKeyboardMovement.value = position.value;\n }\n\n if (focusWasChanged && !keyboardWillAppear.value) {\n // update position on scroll value, so `onEnd` handler\n // will pick up correct values\n position.value += maybeScroll(e.height, true);\n }\n },\n onMove: (e) => {\n \"worklet\";\n\n currentKeyboardFrameHeight.value = e.height;\n\n // if the user has set disableScrollOnKeyboardHide, only auto-scroll when the keyboard opens\n if (!disableScrollOnKeyboardHide || keyboardWillAppear.value) {\n maybeScroll(e.height);\n }\n },\n onEnd: (e) => {\n \"worklet\";\n\n keyboardHeight.value = e.height;\n scrollPosition.value = position.value;\n },\n },\n [height, maybeScroll, disableScrollOnKeyboardHide],\n );\n\n useAnimatedReaction(\n () => input.value,\n (current, previous) => {\n if (\n current?.target === previous?.target &&\n current?.layout.height !== previous?.layout.height\n ) {\n const prevLayout = layout.value;\n\n layout.value = input.value;\n scrollPosition.value += maybeScroll(keyboardHeight.value, true);\n layout.value = prevLayout;\n }\n },\n [],\n );\n\n const view = useAnimatedStyle(\n () => ({\n paddingBottom: currentKeyboardFrameHeight.value,\n }),\n [],\n );\n\n return (\n <Reanimated.ScrollView\n ref={scrollViewAnimatedRef}\n {...rest}\n // @ts-expect-error `onScrollReanimated` is a fake prop needed for reanimated to intercept scroll events\n onScrollReanimated={onScroll}\n scrollEventThrottle={16}\n >\n {children}\n <Reanimated.View style={view} />\n </Reanimated.ScrollView>\n );\n};\n\nexport default KeyboardAwareScrollView;\n"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import Reanimated, { interpolate, scrollTo, useAnimatedReaction, useAnimatedRef,
|
|
|
5
5
|
import { useFocusedInputHandler, useReanimatedFocusedInput } from "react-native-keyboard-controller";
|
|
6
6
|
import { useSmoothKeyboardHandler } from "./useSmoothKeyboardHandler";
|
|
7
7
|
import { debounce } from "./utils";
|
|
8
|
-
|
|
8
|
+
/*
|
|
9
9
|
* Everything begins from `onStart` handler. This handler is called every time,
|
|
10
10
|
* when keyboard changes its size or when focused `TextInput` was changed. In
|
|
11
11
|
* this handler we are calculating/memoizing values which later will be used
|
|
@@ -47,6 +47,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
47
47
|
let {
|
|
48
48
|
children,
|
|
49
49
|
bottomOffset = 0,
|
|
50
|
+
disableScrollOnKeyboardHide = false,
|
|
50
51
|
...rest
|
|
51
52
|
} = _ref;
|
|
52
53
|
const scrollViewAnimatedRef = useAnimatedRef();
|
|
@@ -54,6 +55,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
54
55
|
const position = useSharedValue(0);
|
|
55
56
|
const currentKeyboardFrameHeight = useSharedValue(0);
|
|
56
57
|
const keyboardHeight = useSharedValue(0);
|
|
58
|
+
const keyboardWillAppear = useSharedValue(false);
|
|
57
59
|
const tag = useSharedValue(-1);
|
|
58
60
|
const initialKeyboardSize = useSharedValue(0);
|
|
59
61
|
const scrollBeforeKeyboardMovement = useSharedValue(0);
|
|
@@ -121,7 +123,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
121
123
|
"worklet";
|
|
122
124
|
|
|
123
125
|
const keyboardWillChangeSize = keyboardHeight.value !== e.height && e.height > 0;
|
|
124
|
-
|
|
126
|
+
keyboardWillAppear.value = e.height > 0 && keyboardHeight.value === 0;
|
|
125
127
|
const keyboardWillHide = e.height === 0;
|
|
126
128
|
const focusWasChanged = tag.value !== e.target && e.target !== -1 || keyboardWillChangeSize;
|
|
127
129
|
if (keyboardWillChangeSize) {
|
|
@@ -132,7 +134,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
132
134
|
initialKeyboardSize.value = 0;
|
|
133
135
|
scrollPosition.value = scrollBeforeKeyboardMovement.value;
|
|
134
136
|
}
|
|
135
|
-
if (keyboardWillAppear || keyboardWillChangeSize || focusWasChanged) {
|
|
137
|
+
if (keyboardWillAppear.value || keyboardWillChangeSize || focusWasChanged) {
|
|
136
138
|
// persist scroll value
|
|
137
139
|
scrollPosition.value = position.value;
|
|
138
140
|
// just persist height - later will be used in interpolation
|
|
@@ -149,7 +151,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
149
151
|
// this value to achieve smooth hide effect
|
|
150
152
|
scrollBeforeKeyboardMovement.value = position.value;
|
|
151
153
|
}
|
|
152
|
-
if (focusWasChanged && !keyboardWillAppear) {
|
|
154
|
+
if (focusWasChanged && !keyboardWillAppear.value) {
|
|
153
155
|
// update position on scroll value, so `onEnd` handler
|
|
154
156
|
// will pick up correct values
|
|
155
157
|
position.value += maybeScroll(e.height, true);
|
|
@@ -159,7 +161,11 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
159
161
|
"worklet";
|
|
160
162
|
|
|
161
163
|
currentKeyboardFrameHeight.value = e.height;
|
|
162
|
-
|
|
164
|
+
|
|
165
|
+
// if the user has set disableScrollOnKeyboardHide, only auto-scroll when the keyboard opens
|
|
166
|
+
if (!disableScrollOnKeyboardHide || keyboardWillAppear.value) {
|
|
167
|
+
maybeScroll(e.height);
|
|
168
|
+
}
|
|
163
169
|
},
|
|
164
170
|
onEnd: e => {
|
|
165
171
|
"worklet";
|
|
@@ -167,7 +173,7 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
167
173
|
keyboardHeight.value = e.height;
|
|
168
174
|
scrollPosition.value = position.value;
|
|
169
175
|
}
|
|
170
|
-
}, [height, maybeScroll]);
|
|
176
|
+
}, [height, maybeScroll, disableScrollOnKeyboardHide]);
|
|
171
177
|
useAnimatedReaction(() => input.value, (current, previous) => {
|
|
172
178
|
if ((current === null || current === void 0 ? void 0 : current.target) === (previous === null || previous === void 0 ? void 0 : previous.target) && (current === null || current === void 0 ? void 0 : current.layout.height) !== (previous === null || previous === void 0 ? void 0 : previous.layout.height)) {
|
|
173
179
|
const prevLayout = layout.value;
|
|
@@ -182,7 +188,8 @@ const KeyboardAwareScrollView = _ref => {
|
|
|
182
188
|
return /*#__PURE__*/React.createElement(Reanimated.ScrollView, _extends({
|
|
183
189
|
ref: scrollViewAnimatedRef
|
|
184
190
|
}, rest, {
|
|
185
|
-
|
|
191
|
+
// @ts-expect-error `onScrollReanimated` is a fake prop needed for reanimated to intercept scroll events
|
|
192
|
+
onScrollReanimated: onScroll,
|
|
186
193
|
scrollEventThrottle: 16
|
|
187
194
|
}), children, /*#__PURE__*/React.createElement(Reanimated.View, {
|
|
188
195
|
style: view
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","useMemo","useWindowDimensions","Reanimated","interpolate","scrollTo","useAnimatedReaction","useAnimatedRef","useAnimatedScrollHandler","useAnimatedStyle","useSharedValue","useFocusedInputHandler","useReanimatedFocusedInput","useSmoothKeyboardHandler","debounce","KeyboardAwareScrollView","_ref","children","bottomOffset","rest","scrollViewAnimatedRef","scrollPosition","position","currentKeyboardFrameHeight","keyboardHeight","tag","initialKeyboardSize","scrollBeforeKeyboardMovement","input","layout","height","onScroll","e","value","contentOffset","y","maybeScroll","_layout$value","_layout$value2","animated","arguments","length","undefined","visibleRect","absoluteY","inputHeight","point","interpolatedScrollTo","targetScrollY","Math","max","positionOnScreen","topOfScreen","onChangeText","_layout$value3","_input$value","prevScrollPosition","prevLayout","onChangeTextHandler","onStart","keyboardWillChangeSize","keyboardWillAppear","keyboardWillHide","focusWasChanged","target","onMove","onEnd","current","previous","view","paddingBottom","createElement","ScrollView","_extends","ref","scrollEventThrottle","View","style"],"sources":["index.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { useWindowDimensions } from \"react-native\";\nimport Reanimated, {\n interpolate,\n scrollTo,\n useAnimatedReaction,\n useAnimatedRef,\n useAnimatedScrollHandler,\n useAnimatedStyle,\n useSharedValue,\n} from \"react-native-reanimated\";\n\nimport {\n useFocusedInputHandler,\n useReanimatedFocusedInput,\n} from \"react-native-keyboard-controller\";\n\nimport { useSmoothKeyboardHandler } from \"./useSmoothKeyboardHandler\";\nimport { debounce } from \"./utils\";\n\nimport type { FC } from \"react\";\nimport type { ScrollViewProps } from \"react-native\";\nimport type { FocusedInputLayoutChangedEvent } from \"react-native-keyboard-controller\";\n\ntype KeyboardAwareScrollViewProps = {\n bottomOffset?: number;\n} & ScrollViewProps;\n\n/**\n * Everything begins from `onStart` handler. This handler is called every time,\n * when keyboard changes its size or when focused `TextInput` was changed. In\n * this handler we are calculating/memoizing values which later will be used\n * during layout movement. For that we calculate:\n * - layout of focused field (`layout`) - to understand whether there will be overlap\n * - initial keyboard size (`initialKeyboardSize`) - used in scroll interpolation\n * - future keyboard height (`keyboardHeight`) - used in scroll interpolation\n * - current scroll position (`scrollPosition`) - used to scroll from this point\n *\n * Once we've calculated all necessary variables - we can actually start to use them.\n * It happens in `onMove` handler - this function simply calls `maybeScroll` with\n * current keyboard frame height. This functions makes the smooth transition.\n *\n * When the transition has finished we go to `onEnd` handler. In this handler\n * we verify, that the current field is not overlapped within a keyboard frame.\n * For full `onStart`/`onMove`/`onEnd` flow it may look like a redundant thing,\n * however there could be some cases, when `onMove` is not called:\n * - on iOS when TextInput was changed - keyboard transition is instant\n * - on Android when TextInput was changed and keyboard size wasn't changed\n * So `onEnd` handler handle the case, when `onMove` wasn't triggered.\n *\n * ====================================================================================================================+\n * -----------------------------------------------------Flow chart-----------------------------------------------------+\n * ====================================================================================================================+\n *\n * +============================+ +============================+ +==================================+\n * + User Press on TextInput + => + Keyboard starts showing + => + As keyboard moves frame by frame + =>\n * + + + (run `onStart`) + + `onMove` is getting called +\n * +============================+ +============================+ +==================================+\n *\n *\n * +============================+ +============================+ +=====================================+\n * + Keyboard is shown and we + => + User moved focus to + => + Only `onStart`/`onEnd` maybe called +\n * + call `onEnd` handler + + another `TextInput` + + (without involving `onMove`) +\n * +============================+ +============================+ +=====================================+\n *\n */\nconst KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({\n children,\n bottomOffset = 0,\n ...rest\n}) => {\n const scrollViewAnimatedRef = useAnimatedRef<Reanimated.ScrollView>();\n const scrollPosition = useSharedValue(0);\n const position = useSharedValue(0);\n const currentKeyboardFrameHeight = useSharedValue(0);\n const keyboardHeight = useSharedValue(0);\n const tag = useSharedValue(-1);\n const initialKeyboardSize = useSharedValue(0);\n const scrollBeforeKeyboardMovement = useSharedValue(0);\n const { input } = useReanimatedFocusedInput();\n const layout = useSharedValue<FocusedInputLayoutChangedEvent | null>(null);\n\n const { height } = useWindowDimensions();\n\n const onScroll = useAnimatedScrollHandler(\n {\n onScroll: (e) => {\n position.value = e.contentOffset.y;\n },\n },\n [],\n );\n\n /**\n * Function that will scroll a ScrollView as keyboard gets moving\n */\n const maybeScroll = useCallback(\n (e: number, animated: boolean = false) => {\n \"worklet\";\n\n const visibleRect = height - keyboardHeight.value;\n const absoluteY = layout.value?.layout.absoluteY || 0;\n const inputHeight = layout.value?.layout.height || 0;\n const point = absoluteY + inputHeight;\n\n if (visibleRect - point <= bottomOffset) {\n const interpolatedScrollTo = interpolate(\n e,\n [initialKeyboardSize.value, keyboardHeight.value],\n [0, keyboardHeight.value - (height - point) + bottomOffset],\n );\n const targetScrollY =\n Math.max(interpolatedScrollTo, 0) + scrollPosition.value;\n scrollTo(scrollViewAnimatedRef, 0, targetScrollY, animated);\n\n return interpolatedScrollTo;\n }\n\n if (absoluteY < 0) {\n const positionOnScreen = visibleRect - inputHeight - bottomOffset;\n const topOfScreen = scrollPosition.value + absoluteY;\n\n scrollTo(\n scrollViewAnimatedRef,\n 0,\n topOfScreen - positionOnScreen,\n animated,\n );\n }\n\n return 0;\n },\n [bottomOffset],\n );\n\n const onChangeText = useCallback(() => {\n \"worklet\";\n\n // if typing a text caused layout shift, then we need to ignore this handler\n // because this event will be handled in `useAnimatedReaction` below\n if (layout.value?.layout.height !== input.value?.layout.height) {\n return;\n }\n\n const prevScrollPosition = scrollPosition.value;\n const prevLayout = layout.value;\n\n scrollPosition.value = position.value;\n layout.value = input.value;\n maybeScroll(keyboardHeight.value, true);\n scrollPosition.value = prevScrollPosition;\n layout.value = prevLayout;\n }, [maybeScroll]);\n const onChangeTextHandler = useMemo(\n () => debounce(onChangeText, 200),\n [onChangeText],\n );\n\n useFocusedInputHandler(\n {\n onChangeText: onChangeTextHandler,\n },\n [onChangeTextHandler],\n );\n\n useSmoothKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n const keyboardWillChangeSize =\n keyboardHeight.value !== e.height && e.height > 0;\n const keyboardWillAppear = e.height > 0 && keyboardHeight.value === 0;\n const keyboardWillHide = e.height === 0;\n const focusWasChanged =\n (tag.value !== e.target && e.target !== -1) || keyboardWillChangeSize;\n\n if (keyboardWillChangeSize) {\n initialKeyboardSize.value = keyboardHeight.value;\n }\n\n if (keyboardWillHide) {\n // on back transition need to interpolate as [0, keyboardHeight]\n initialKeyboardSize.value = 0;\n scrollPosition.value = scrollBeforeKeyboardMovement.value;\n }\n\n if (keyboardWillAppear || keyboardWillChangeSize || focusWasChanged) {\n // persist scroll value\n scrollPosition.value = position.value;\n // just persist height - later will be used in interpolation\n keyboardHeight.value = e.height;\n }\n\n // focus was changed\n if (focusWasChanged) {\n tag.value = e.target;\n\n // save position of focused text input when keyboard starts to move\n layout.value = input.value;\n // save current scroll position - when keyboard will hide we'll reuse\n // this value to achieve smooth hide effect\n scrollBeforeKeyboardMovement.value = position.value;\n }\n\n if (focusWasChanged && !keyboardWillAppear) {\n // update position on scroll value, so `onEnd` handler\n // will pick up correct values\n position.value += maybeScroll(e.height, true);\n }\n },\n onMove: (e) => {\n \"worklet\";\n\n currentKeyboardFrameHeight.value = e.height;\n\n maybeScroll(e.height);\n },\n onEnd: (e) => {\n \"worklet\";\n\n keyboardHeight.value = e.height;\n scrollPosition.value = position.value;\n },\n },\n [height, maybeScroll],\n );\n\n useAnimatedReaction(\n () => input.value,\n (current, previous) => {\n if (\n current?.target === previous?.target &&\n current?.layout.height !== previous?.layout.height\n ) {\n const prevLayout = layout.value;\n\n layout.value = input.value;\n scrollPosition.value += maybeScroll(keyboardHeight.value, true);\n layout.value = prevLayout;\n }\n },\n [],\n );\n\n const view = useAnimatedStyle(\n () => ({\n paddingBottom: currentKeyboardFrameHeight.value,\n }),\n [],\n );\n\n return (\n <Reanimated.ScrollView\n ref={scrollViewAnimatedRef}\n {...rest}\n onScroll={onScroll}\n scrollEventThrottle={16}\n >\n {children}\n <Reanimated.View style={view} />\n </Reanimated.ScrollView>\n );\n};\n\nexport default KeyboardAwareScrollView;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["React","useCallback","useMemo","useWindowDimensions","Reanimated","interpolate","scrollTo","useAnimatedReaction","useAnimatedRef","useAnimatedScrollHandler","useAnimatedStyle","useSharedValue","useFocusedInputHandler","useReanimatedFocusedInput","useSmoothKeyboardHandler","debounce","KeyboardAwareScrollView","_ref","children","bottomOffset","disableScrollOnKeyboardHide","rest","scrollViewAnimatedRef","scrollPosition","position","currentKeyboardFrameHeight","keyboardHeight","keyboardWillAppear","tag","initialKeyboardSize","scrollBeforeKeyboardMovement","input","layout","height","onScroll","e","value","contentOffset","y","maybeScroll","_layout$value","_layout$value2","animated","arguments","length","undefined","visibleRect","absoluteY","inputHeight","point","interpolatedScrollTo","targetScrollY","Math","max","positionOnScreen","topOfScreen","onChangeText","_layout$value3","_input$value","prevScrollPosition","prevLayout","onChangeTextHandler","onStart","keyboardWillChangeSize","keyboardWillHide","focusWasChanged","target","onMove","onEnd","current","previous","view","paddingBottom","createElement","ScrollView","_extends","ref","onScrollReanimated","scrollEventThrottle","View","style"],"sources":["index.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { useWindowDimensions } from \"react-native\";\nimport Reanimated, {\n interpolate,\n scrollTo,\n useAnimatedReaction,\n useAnimatedRef,\n useAnimatedScrollHandler,\n useAnimatedStyle,\n useSharedValue,\n} from \"react-native-reanimated\";\n\nimport {\n useFocusedInputHandler,\n useReanimatedFocusedInput,\n} from \"react-native-keyboard-controller\";\n\nimport { useSmoothKeyboardHandler } from \"./useSmoothKeyboardHandler\";\nimport { debounce } from \"./utils\";\n\nimport type { FC } from \"react\";\nimport type { ScrollViewProps } from \"react-native\";\nimport type { FocusedInputLayoutChangedEvent } from \"react-native-keyboard-controller\";\n\ntype KeyboardAwareScrollViewProps = {\n /** The distance between keyboard and focused `TextInput` when keyboard is shown. Default is `0`. */\n bottomOffset?: number;\n /** Prevents automatic scrolling of the `ScrollView` when the keyboard gets hidden, maintaining the current screen position. Default is `false`. */\n disableScrollOnKeyboardHide?: boolean;\n} & ScrollViewProps;\n\n/*\n * Everything begins from `onStart` handler. This handler is called every time,\n * when keyboard changes its size or when focused `TextInput` was changed. In\n * this handler we are calculating/memoizing values which later will be used\n * during layout movement. For that we calculate:\n * - layout of focused field (`layout`) - to understand whether there will be overlap\n * - initial keyboard size (`initialKeyboardSize`) - used in scroll interpolation\n * - future keyboard height (`keyboardHeight`) - used in scroll interpolation\n * - current scroll position (`scrollPosition`) - used to scroll from this point\n *\n * Once we've calculated all necessary variables - we can actually start to use them.\n * It happens in `onMove` handler - this function simply calls `maybeScroll` with\n * current keyboard frame height. This functions makes the smooth transition.\n *\n * When the transition has finished we go to `onEnd` handler. In this handler\n * we verify, that the current field is not overlapped within a keyboard frame.\n * For full `onStart`/`onMove`/`onEnd` flow it may look like a redundant thing,\n * however there could be some cases, when `onMove` is not called:\n * - on iOS when TextInput was changed - keyboard transition is instant\n * - on Android when TextInput was changed and keyboard size wasn't changed\n * So `onEnd` handler handle the case, when `onMove` wasn't triggered.\n *\n * ====================================================================================================================+\n * -----------------------------------------------------Flow chart-----------------------------------------------------+\n * ====================================================================================================================+\n *\n * +============================+ +============================+ +==================================+\n * + User Press on TextInput + => + Keyboard starts showing + => + As keyboard moves frame by frame + =>\n * + + + (run `onStart`) + + `onMove` is getting called +\n * +============================+ +============================+ +==================================+\n *\n *\n * +============================+ +============================+ +=====================================+\n * + Keyboard is shown and we + => + User moved focus to + => + Only `onStart`/`onEnd` maybe called +\n * + call `onEnd` handler + + another `TextInput` + + (without involving `onMove`) +\n * +============================+ +============================+ +=====================================+\n *\n */\nconst KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({\n children,\n bottomOffset = 0,\n disableScrollOnKeyboardHide = false,\n ...rest\n}) => {\n const scrollViewAnimatedRef = useAnimatedRef<Reanimated.ScrollView>();\n const scrollPosition = useSharedValue(0);\n const position = useSharedValue(0);\n const currentKeyboardFrameHeight = useSharedValue(0);\n const keyboardHeight = useSharedValue(0);\n const keyboardWillAppear = useSharedValue(false);\n const tag = useSharedValue(-1);\n const initialKeyboardSize = useSharedValue(0);\n const scrollBeforeKeyboardMovement = useSharedValue(0);\n const { input } = useReanimatedFocusedInput();\n const layout = useSharedValue<FocusedInputLayoutChangedEvent | null>(null);\n\n const { height } = useWindowDimensions();\n\n const onScroll = useAnimatedScrollHandler(\n {\n onScroll: (e) => {\n position.value = e.contentOffset.y;\n },\n },\n [],\n );\n\n /**\n * Function that will scroll a ScrollView as keyboard gets moving\n */\n const maybeScroll = useCallback(\n (e: number, animated: boolean = false) => {\n \"worklet\";\n\n const visibleRect = height - keyboardHeight.value;\n const absoluteY = layout.value?.layout.absoluteY || 0;\n const inputHeight = layout.value?.layout.height || 0;\n const point = absoluteY + inputHeight;\n\n if (visibleRect - point <= bottomOffset) {\n const interpolatedScrollTo = interpolate(\n e,\n [initialKeyboardSize.value, keyboardHeight.value],\n [0, keyboardHeight.value - (height - point) + bottomOffset],\n );\n const targetScrollY =\n Math.max(interpolatedScrollTo, 0) + scrollPosition.value;\n scrollTo(scrollViewAnimatedRef, 0, targetScrollY, animated);\n\n return interpolatedScrollTo;\n }\n\n if (absoluteY < 0) {\n const positionOnScreen = visibleRect - inputHeight - bottomOffset;\n const topOfScreen = scrollPosition.value + absoluteY;\n\n scrollTo(\n scrollViewAnimatedRef,\n 0,\n topOfScreen - positionOnScreen,\n animated,\n );\n }\n\n return 0;\n },\n [bottomOffset],\n );\n\n const onChangeText = useCallback(() => {\n \"worklet\";\n\n // if typing a text caused layout shift, then we need to ignore this handler\n // because this event will be handled in `useAnimatedReaction` below\n if (layout.value?.layout.height !== input.value?.layout.height) {\n return;\n }\n\n const prevScrollPosition = scrollPosition.value;\n const prevLayout = layout.value;\n\n scrollPosition.value = position.value;\n layout.value = input.value;\n maybeScroll(keyboardHeight.value, true);\n scrollPosition.value = prevScrollPosition;\n layout.value = prevLayout;\n }, [maybeScroll]);\n const onChangeTextHandler = useMemo(\n () => debounce(onChangeText, 200),\n [onChangeText],\n );\n\n useFocusedInputHandler(\n {\n onChangeText: onChangeTextHandler,\n },\n [onChangeTextHandler],\n );\n\n useSmoothKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n const keyboardWillChangeSize =\n keyboardHeight.value !== e.height && e.height > 0;\n keyboardWillAppear.value = e.height > 0 && keyboardHeight.value === 0;\n const keyboardWillHide = e.height === 0;\n const focusWasChanged =\n (tag.value !== e.target && e.target !== -1) || keyboardWillChangeSize;\n\n if (keyboardWillChangeSize) {\n initialKeyboardSize.value = keyboardHeight.value;\n }\n\n if (keyboardWillHide) {\n // on back transition need to interpolate as [0, keyboardHeight]\n initialKeyboardSize.value = 0;\n scrollPosition.value = scrollBeforeKeyboardMovement.value;\n }\n\n if (\n keyboardWillAppear.value ||\n keyboardWillChangeSize ||\n focusWasChanged\n ) {\n // persist scroll value\n scrollPosition.value = position.value;\n // just persist height - later will be used in interpolation\n keyboardHeight.value = e.height;\n }\n\n // focus was changed\n if (focusWasChanged) {\n tag.value = e.target;\n\n // save position of focused text input when keyboard starts to move\n layout.value = input.value;\n // save current scroll position - when keyboard will hide we'll reuse\n // this value to achieve smooth hide effect\n scrollBeforeKeyboardMovement.value = position.value;\n }\n\n if (focusWasChanged && !keyboardWillAppear.value) {\n // update position on scroll value, so `onEnd` handler\n // will pick up correct values\n position.value += maybeScroll(e.height, true);\n }\n },\n onMove: (e) => {\n \"worklet\";\n\n currentKeyboardFrameHeight.value = e.height;\n\n // if the user has set disableScrollOnKeyboardHide, only auto-scroll when the keyboard opens\n if (!disableScrollOnKeyboardHide || keyboardWillAppear.value) {\n maybeScroll(e.height);\n }\n },\n onEnd: (e) => {\n \"worklet\";\n\n keyboardHeight.value = e.height;\n scrollPosition.value = position.value;\n },\n },\n [height, maybeScroll, disableScrollOnKeyboardHide],\n );\n\n useAnimatedReaction(\n () => input.value,\n (current, previous) => {\n if (\n current?.target === previous?.target &&\n current?.layout.height !== previous?.layout.height\n ) {\n const prevLayout = layout.value;\n\n layout.value = input.value;\n scrollPosition.value += maybeScroll(keyboardHeight.value, true);\n layout.value = prevLayout;\n }\n },\n [],\n );\n\n const view = useAnimatedStyle(\n () => ({\n paddingBottom: currentKeyboardFrameHeight.value,\n }),\n [],\n );\n\n return (\n <Reanimated.ScrollView\n ref={scrollViewAnimatedRef}\n {...rest}\n // @ts-expect-error `onScrollReanimated` is a fake prop needed for reanimated to intercept scroll events\n onScrollReanimated={onScroll}\n scrollEventThrottle={16}\n >\n {children}\n <Reanimated.View style={view} />\n </Reanimated.ScrollView>\n );\n};\n\nexport default KeyboardAwareScrollView;\n"],"mappings":";AAAA,OAAOA,KAAK,IAAIC,WAAW,EAAEC,OAAO,QAAQ,OAAO;AACnD,SAASC,mBAAmB,QAAQ,cAAc;AAClD,OAAOC,UAAU,IACfC,WAAW,EACXC,QAAQ,EACRC,mBAAmB,EACnBC,cAAc,EACdC,wBAAwB,EACxBC,gBAAgB,EAChBC,cAAc,QACT,yBAAyB;AAEhC,SACEC,sBAAsB,EACtBC,yBAAyB,QACpB,kCAAkC;AAEzC,SAASC,wBAAwB,QAAQ,4BAA4B;AACrE,SAASC,QAAQ,QAAQ,SAAS;AAalC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,uBAAyD,GAAGC,IAAA,IAK5D;EAAA,IAL6D;IACjEC,QAAQ;IACRC,YAAY,GAAG,CAAC;IAChBC,2BAA2B,GAAG,KAAK;IACnC,GAAGC;EACL,CAAC,GAAAJ,IAAA;EACC,MAAMK,qBAAqB,GAAGd,cAAc,CAAwB,CAAC;EACrE,MAAMe,cAAc,GAAGZ,cAAc,CAAC,CAAC,CAAC;EACxC,MAAMa,QAAQ,GAAGb,cAAc,CAAC,CAAC,CAAC;EAClC,MAAMc,0BAA0B,GAAGd,cAAc,CAAC,CAAC,CAAC;EACpD,MAAMe,cAAc,GAAGf,cAAc,CAAC,CAAC,CAAC;EACxC,MAAMgB,kBAAkB,GAAGhB,cAAc,CAAC,KAAK,CAAC;EAChD,MAAMiB,GAAG,GAAGjB,cAAc,CAAC,CAAC,CAAC,CAAC;EAC9B,MAAMkB,mBAAmB,GAAGlB,cAAc,CAAC,CAAC,CAAC;EAC7C,MAAMmB,4BAA4B,GAAGnB,cAAc,CAAC,CAAC,CAAC;EACtD,MAAM;IAAEoB;EAAM,CAAC,GAAGlB,yBAAyB,CAAC,CAAC;EAC7C,MAAMmB,MAAM,GAAGrB,cAAc,CAAwC,IAAI,CAAC;EAE1E,MAAM;IAAEsB;EAAO,CAAC,GAAG9B,mBAAmB,CAAC,CAAC;EAExC,MAAM+B,QAAQ,GAAGzB,wBAAwB,CACvC;IACEyB,QAAQ,EAAGC,CAAC,IAAK;MACfX,QAAQ,CAACY,KAAK,GAAGD,CAAC,CAACE,aAAa,CAACC,CAAC;IACpC;EACF,CAAC,EACD,EACF,CAAC;;EAED;AACF;AACA;EACE,MAAMC,WAAW,GAAGtC,WAAW,CAC7B,UAACkC,CAAS,EAAgC;IACxC,SAAS;;IAAC,IAAAK,aAAA,EAAAC,cAAA;IAAA,IADAC,QAAiB,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,KAAK;IAGnC,MAAMG,WAAW,GAAGb,MAAM,GAAGP,cAAc,CAACU,KAAK;IACjD,MAAMW,SAAS,GAAG,EAAAP,aAAA,GAAAR,MAAM,CAACI,KAAK,cAAAI,aAAA,uBAAZA,aAAA,CAAcR,MAAM,CAACe,SAAS,KAAI,CAAC;IACrD,MAAMC,WAAW,GAAG,EAAAP,cAAA,GAAAT,MAAM,CAACI,KAAK,cAAAK,cAAA,uBAAZA,cAAA,CAAcT,MAAM,CAACC,MAAM,KAAI,CAAC;IACpD,MAAMgB,KAAK,GAAGF,SAAS,GAAGC,WAAW;IAErC,IAAIF,WAAW,GAAGG,KAAK,IAAI9B,YAAY,EAAE;MACvC,MAAM+B,oBAAoB,GAAG7C,WAAW,CACtC8B,CAAC,EACD,CAACN,mBAAmB,CAACO,KAAK,EAAEV,cAAc,CAACU,KAAK,CAAC,EACjD,CAAC,CAAC,EAAEV,cAAc,CAACU,KAAK,IAAIH,MAAM,GAAGgB,KAAK,CAAC,GAAG9B,YAAY,CAC5D,CAAC;MACD,MAAMgC,aAAa,GACjBC,IAAI,CAACC,GAAG,CAACH,oBAAoB,EAAE,CAAC,CAAC,GAAG3B,cAAc,CAACa,KAAK;MAC1D9B,QAAQ,CAACgB,qBAAqB,EAAE,CAAC,EAAE6B,aAAa,EAAET,QAAQ,CAAC;MAE3D,OAAOQ,oBAAoB;IAC7B;IAEA,IAAIH,SAAS,GAAG,CAAC,EAAE;MACjB,MAAMO,gBAAgB,GAAGR,WAAW,GAAGE,WAAW,GAAG7B,YAAY;MACjE,MAAMoC,WAAW,GAAGhC,cAAc,CAACa,KAAK,GAAGW,SAAS;MAEpDzC,QAAQ,CACNgB,qBAAqB,EACrB,CAAC,EACDiC,WAAW,GAAGD,gBAAgB,EAC9BZ,QACF,CAAC;IACH;IAEA,OAAO,CAAC;EACV,CAAC,EACD,CAACvB,YAAY,CACf,CAAC;EAED,MAAMqC,YAAY,GAAGvD,WAAW,CAAC,MAAM;IACrC,SAAS;;IAET;IACA;IAAA,IAAAwD,cAAA,EAAAC,YAAA;IACA,IAAI,EAAAD,cAAA,GAAAzB,MAAM,CAACI,KAAK,cAAAqB,cAAA,uBAAZA,cAAA,CAAczB,MAAM,CAACC,MAAM,QAAAyB,YAAA,GAAK3B,KAAK,CAACK,KAAK,cAAAsB,YAAA,uBAAXA,YAAA,CAAa1B,MAAM,CAACC,MAAM,GAAE;MAC9D;IACF;IAEA,MAAM0B,kBAAkB,GAAGpC,cAAc,CAACa,KAAK;IAC/C,MAAMwB,UAAU,GAAG5B,MAAM,CAACI,KAAK;IAE/Bb,cAAc,CAACa,KAAK,GAAGZ,QAAQ,CAACY,KAAK;IACrCJ,MAAM,CAACI,KAAK,GAAGL,KAAK,CAACK,KAAK;IAC1BG,WAAW,CAACb,cAAc,CAACU,KAAK,EAAE,IAAI,CAAC;IACvCb,cAAc,CAACa,KAAK,GAAGuB,kBAAkB;IACzC3B,MAAM,CAACI,KAAK,GAAGwB,UAAU;EAC3B,CAAC,EAAE,CAACrB,WAAW,CAAC,CAAC;EACjB,MAAMsB,mBAAmB,GAAG3D,OAAO,CACjC,MAAMa,QAAQ,CAACyC,YAAY,EAAE,GAAG,CAAC,EACjC,CAACA,YAAY,CACf,CAAC;EAED5C,sBAAsB,CACpB;IACE4C,YAAY,EAAEK;EAChB,CAAC,EACD,CAACA,mBAAmB,CACtB,CAAC;EAED/C,wBAAwB,CACtB;IACEgD,OAAO,EAAG3B,CAAC,IAAK;MACd,SAAS;;MAET,MAAM4B,sBAAsB,GAC1BrC,cAAc,CAACU,KAAK,KAAKD,CAAC,CAACF,MAAM,IAAIE,CAAC,CAACF,MAAM,GAAG,CAAC;MACnDN,kBAAkB,CAACS,KAAK,GAAGD,CAAC,CAACF,MAAM,GAAG,CAAC,IAAIP,cAAc,CAACU,KAAK,KAAK,CAAC;MACrE,MAAM4B,gBAAgB,GAAG7B,CAAC,CAACF,MAAM,KAAK,CAAC;MACvC,MAAMgC,eAAe,GAClBrC,GAAG,CAACQ,KAAK,KAAKD,CAAC,CAAC+B,MAAM,IAAI/B,CAAC,CAAC+B,MAAM,KAAK,CAAC,CAAC,IAAKH,sBAAsB;MAEvE,IAAIA,sBAAsB,EAAE;QAC1BlC,mBAAmB,CAACO,KAAK,GAAGV,cAAc,CAACU,KAAK;MAClD;MAEA,IAAI4B,gBAAgB,EAAE;QACpB;QACAnC,mBAAmB,CAACO,KAAK,GAAG,CAAC;QAC7Bb,cAAc,CAACa,KAAK,GAAGN,4BAA4B,CAACM,KAAK;MAC3D;MAEA,IACET,kBAAkB,CAACS,KAAK,IACxB2B,sBAAsB,IACtBE,eAAe,EACf;QACA;QACA1C,cAAc,CAACa,KAAK,GAAGZ,QAAQ,CAACY,KAAK;QACrC;QACAV,cAAc,CAACU,KAAK,GAAGD,CAAC,CAACF,MAAM;MACjC;;MAEA;MACA,IAAIgC,eAAe,EAAE;QACnBrC,GAAG,CAACQ,KAAK,GAAGD,CAAC,CAAC+B,MAAM;;QAEpB;QACAlC,MAAM,CAACI,KAAK,GAAGL,KAAK,CAACK,KAAK;QAC1B;QACA;QACAN,4BAA4B,CAACM,KAAK,GAAGZ,QAAQ,CAACY,KAAK;MACrD;MAEA,IAAI6B,eAAe,IAAI,CAACtC,kBAAkB,CAACS,KAAK,EAAE;QAChD;QACA;QACAZ,QAAQ,CAACY,KAAK,IAAIG,WAAW,CAACJ,CAAC,CAACF,MAAM,EAAE,IAAI,CAAC;MAC/C;IACF,CAAC;IACDkC,MAAM,EAAGhC,CAAC,IAAK;MACb,SAAS;;MAETV,0BAA0B,CAACW,KAAK,GAAGD,CAAC,CAACF,MAAM;;MAE3C;MACA,IAAI,CAACb,2BAA2B,IAAIO,kBAAkB,CAACS,KAAK,EAAE;QAC5DG,WAAW,CAACJ,CAAC,CAACF,MAAM,CAAC;MACvB;IACF,CAAC;IACDmC,KAAK,EAAGjC,CAAC,IAAK;MACZ,SAAS;;MAETT,cAAc,CAACU,KAAK,GAAGD,CAAC,CAACF,MAAM;MAC/BV,cAAc,CAACa,KAAK,GAAGZ,QAAQ,CAACY,KAAK;IACvC;EACF,CAAC,EACD,CAACH,MAAM,EAAEM,WAAW,EAAEnB,2BAA2B,CACnD,CAAC;EAEDb,mBAAmB,CACjB,MAAMwB,KAAK,CAACK,KAAK,EACjB,CAACiC,OAAO,EAAEC,QAAQ,KAAK;IACrB,IACE,CAAAD,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEH,MAAM,OAAKI,QAAQ,aAARA,QAAQ,uBAARA,QAAQ,CAAEJ,MAAM,KACpC,CAAAG,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAErC,MAAM,CAACC,MAAM,OAAKqC,QAAQ,aAARA,QAAQ,uBAARA,QAAQ,CAAEtC,MAAM,CAACC,MAAM,GAClD;MACA,MAAM2B,UAAU,GAAG5B,MAAM,CAACI,KAAK;MAE/BJ,MAAM,CAACI,KAAK,GAAGL,KAAK,CAACK,KAAK;MAC1Bb,cAAc,CAACa,KAAK,IAAIG,WAAW,CAACb,cAAc,CAACU,KAAK,EAAE,IAAI,CAAC;MAC/DJ,MAAM,CAACI,KAAK,GAAGwB,UAAU;IAC3B;EACF,CAAC,EACD,EACF,CAAC;EAED,MAAMW,IAAI,GAAG7D,gBAAgB,CAC3B,OAAO;IACL8D,aAAa,EAAE/C,0BAA0B,CAACW;EAC5C,CAAC,CAAC,EACF,EACF,CAAC;EAED,oBACEpC,KAAA,CAAAyE,aAAA,CAACrE,UAAU,CAACsE,UAAU,EAAAC,QAAA;IACpBC,GAAG,EAAEtD;EAAsB,GACvBD,IAAI;IACR;IACAwD,kBAAkB,EAAE3C,QAAS;IAC7B4C,mBAAmB,EAAE;EAAG,IAEvB5D,QAAQ,eACTlB,KAAA,CAAAyE,aAAA,CAACrE,UAAU,CAAC2E,IAAI;IAACC,KAAK,EAAET;EAAK,CAAE,CACV,CAAC;AAE5B,CAAC;AAED,eAAevD,uBAAuB"}
|
|
@@ -1,45 +1,10 @@
|
|
|
1
1
|
import type { FC } from "react";
|
|
2
2
|
import type { ScrollViewProps } from "react-native";
|
|
3
3
|
type KeyboardAwareScrollViewProps = {
|
|
4
|
+
/** The distance between keyboard and focused `TextInput` when keyboard is shown. Default is `0`. */
|
|
4
5
|
bottomOffset?: number;
|
|
6
|
+
/** Prevents automatic scrolling of the `ScrollView` when the keyboard gets hidden, maintaining the current screen position. Default is `false`. */
|
|
7
|
+
disableScrollOnKeyboardHide?: boolean;
|
|
5
8
|
} & ScrollViewProps;
|
|
6
|
-
/**
|
|
7
|
-
* Everything begins from `onStart` handler. This handler is called every time,
|
|
8
|
-
* when keyboard changes its size or when focused `TextInput` was changed. In
|
|
9
|
-
* this handler we are calculating/memoizing values which later will be used
|
|
10
|
-
* during layout movement. For that we calculate:
|
|
11
|
-
* - layout of focused field (`layout`) - to understand whether there will be overlap
|
|
12
|
-
* - initial keyboard size (`initialKeyboardSize`) - used in scroll interpolation
|
|
13
|
-
* - future keyboard height (`keyboardHeight`) - used in scroll interpolation
|
|
14
|
-
* - current scroll position (`scrollPosition`) - used to scroll from this point
|
|
15
|
-
*
|
|
16
|
-
* Once we've calculated all necessary variables - we can actually start to use them.
|
|
17
|
-
* It happens in `onMove` handler - this function simply calls `maybeScroll` with
|
|
18
|
-
* current keyboard frame height. This functions makes the smooth transition.
|
|
19
|
-
*
|
|
20
|
-
* When the transition has finished we go to `onEnd` handler. In this handler
|
|
21
|
-
* we verify, that the current field is not overlapped within a keyboard frame.
|
|
22
|
-
* For full `onStart`/`onMove`/`onEnd` flow it may look like a redundant thing,
|
|
23
|
-
* however there could be some cases, when `onMove` is not called:
|
|
24
|
-
* - on iOS when TextInput was changed - keyboard transition is instant
|
|
25
|
-
* - on Android when TextInput was changed and keyboard size wasn't changed
|
|
26
|
-
* So `onEnd` handler handle the case, when `onMove` wasn't triggered.
|
|
27
|
-
*
|
|
28
|
-
* ====================================================================================================================+
|
|
29
|
-
* -----------------------------------------------------Flow chart-----------------------------------------------------+
|
|
30
|
-
* ====================================================================================================================+
|
|
31
|
-
*
|
|
32
|
-
* +============================+ +============================+ +==================================+
|
|
33
|
-
* + User Press on TextInput + => + Keyboard starts showing + => + As keyboard moves frame by frame + =>
|
|
34
|
-
* + + + (run `onStart`) + + `onMove` is getting called +
|
|
35
|
-
* +============================+ +============================+ +==================================+
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* +============================+ +============================+ +=====================================+
|
|
39
|
-
* + Keyboard is shown and we + => + User moved focus to + => + Only `onStart`/`onEnd` maybe called +
|
|
40
|
-
* + call `onEnd` handler + + another `TextInput` + + (without involving `onMove`) +
|
|
41
|
-
* +============================+ +============================+ +=====================================+
|
|
42
|
-
*
|
|
43
|
-
*/
|
|
44
9
|
declare const KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps>;
|
|
45
10
|
export default KeyboardAwareScrollView;
|
package/package.json
CHANGED
|
@@ -23,10 +23,13 @@ import type { ScrollViewProps } from "react-native";
|
|
|
23
23
|
import type { FocusedInputLayoutChangedEvent } from "react-native-keyboard-controller";
|
|
24
24
|
|
|
25
25
|
type KeyboardAwareScrollViewProps = {
|
|
26
|
+
/** The distance between keyboard and focused `TextInput` when keyboard is shown. Default is `0`. */
|
|
26
27
|
bottomOffset?: number;
|
|
28
|
+
/** Prevents automatic scrolling of the `ScrollView` when the keyboard gets hidden, maintaining the current screen position. Default is `false`. */
|
|
29
|
+
disableScrollOnKeyboardHide?: boolean;
|
|
27
30
|
} & ScrollViewProps;
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
/*
|
|
30
33
|
* Everything begins from `onStart` handler. This handler is called every time,
|
|
31
34
|
* when keyboard changes its size or when focused `TextInput` was changed. In
|
|
32
35
|
* this handler we are calculating/memoizing values which later will be used
|
|
@@ -67,6 +70,7 @@ type KeyboardAwareScrollViewProps = {
|
|
|
67
70
|
const KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({
|
|
68
71
|
children,
|
|
69
72
|
bottomOffset = 0,
|
|
73
|
+
disableScrollOnKeyboardHide = false,
|
|
70
74
|
...rest
|
|
71
75
|
}) => {
|
|
72
76
|
const scrollViewAnimatedRef = useAnimatedRef<Reanimated.ScrollView>();
|
|
@@ -74,6 +78,7 @@ const KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({
|
|
|
74
78
|
const position = useSharedValue(0);
|
|
75
79
|
const currentKeyboardFrameHeight = useSharedValue(0);
|
|
76
80
|
const keyboardHeight = useSharedValue(0);
|
|
81
|
+
const keyboardWillAppear = useSharedValue(false);
|
|
77
82
|
const tag = useSharedValue(-1);
|
|
78
83
|
const initialKeyboardSize = useSharedValue(0);
|
|
79
84
|
const scrollBeforeKeyboardMovement = useSharedValue(0);
|
|
@@ -170,7 +175,7 @@ const KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({
|
|
|
170
175
|
|
|
171
176
|
const keyboardWillChangeSize =
|
|
172
177
|
keyboardHeight.value !== e.height && e.height > 0;
|
|
173
|
-
|
|
178
|
+
keyboardWillAppear.value = e.height > 0 && keyboardHeight.value === 0;
|
|
174
179
|
const keyboardWillHide = e.height === 0;
|
|
175
180
|
const focusWasChanged =
|
|
176
181
|
(tag.value !== e.target && e.target !== -1) || keyboardWillChangeSize;
|
|
@@ -185,7 +190,11 @@ const KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({
|
|
|
185
190
|
scrollPosition.value = scrollBeforeKeyboardMovement.value;
|
|
186
191
|
}
|
|
187
192
|
|
|
188
|
-
if (
|
|
193
|
+
if (
|
|
194
|
+
keyboardWillAppear.value ||
|
|
195
|
+
keyboardWillChangeSize ||
|
|
196
|
+
focusWasChanged
|
|
197
|
+
) {
|
|
189
198
|
// persist scroll value
|
|
190
199
|
scrollPosition.value = position.value;
|
|
191
200
|
// just persist height - later will be used in interpolation
|
|
@@ -203,7 +212,7 @@ const KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({
|
|
|
203
212
|
scrollBeforeKeyboardMovement.value = position.value;
|
|
204
213
|
}
|
|
205
214
|
|
|
206
|
-
if (focusWasChanged && !keyboardWillAppear) {
|
|
215
|
+
if (focusWasChanged && !keyboardWillAppear.value) {
|
|
207
216
|
// update position on scroll value, so `onEnd` handler
|
|
208
217
|
// will pick up correct values
|
|
209
218
|
position.value += maybeScroll(e.height, true);
|
|
@@ -214,7 +223,10 @@ const KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({
|
|
|
214
223
|
|
|
215
224
|
currentKeyboardFrameHeight.value = e.height;
|
|
216
225
|
|
|
217
|
-
|
|
226
|
+
// if the user has set disableScrollOnKeyboardHide, only auto-scroll when the keyboard opens
|
|
227
|
+
if (!disableScrollOnKeyboardHide || keyboardWillAppear.value) {
|
|
228
|
+
maybeScroll(e.height);
|
|
229
|
+
}
|
|
218
230
|
},
|
|
219
231
|
onEnd: (e) => {
|
|
220
232
|
"worklet";
|
|
@@ -223,7 +235,7 @@ const KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({
|
|
|
223
235
|
scrollPosition.value = position.value;
|
|
224
236
|
},
|
|
225
237
|
},
|
|
226
|
-
[height, maybeScroll],
|
|
238
|
+
[height, maybeScroll, disableScrollOnKeyboardHide],
|
|
227
239
|
);
|
|
228
240
|
|
|
229
241
|
useAnimatedReaction(
|
|
@@ -254,7 +266,8 @@ const KeyboardAwareScrollView: FC<KeyboardAwareScrollViewProps> = ({
|
|
|
254
266
|
<Reanimated.ScrollView
|
|
255
267
|
ref={scrollViewAnimatedRef}
|
|
256
268
|
{...rest}
|
|
257
|
-
|
|
269
|
+
// @ts-expect-error `onScrollReanimated` is a fake prop needed for reanimated to intercept scroll events
|
|
270
|
+
onScrollReanimated={onScroll}
|
|
258
271
|
scrollEventThrottle={16}
|
|
259
272
|
>
|
|
260
273
|
{children}
|