react-native-dodge-keyboard 1.0.2 → 1.0.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.
Files changed (3) hide show
  1. package/index.d.ts +10 -1
  2. package/index.js +282 -200
  3. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -102,6 +102,15 @@ interface ReactHijackerProps {
102
102
  }
103
103
 
104
104
  export function ReactHijacker(props: ReactHijackerProps): React.ReactElement | null;
105
+ export function __HijackNode(props: { children: () => React.ReactElement | null }): React.ReactElement | null;
106
+
107
+ export function createHijackedElement(element?: React.ReactElement | null): { __element: React.ReactElement | null };
105
108
 
106
109
  export function isDodgeScrollable(element: React.ReactNode, disableTagCheck?: boolean): boolean;
107
- export function isDodgeInput(element: React.ReactNode, disableTagCheck?: boolean): boolean;
110
+ export function isDodgeInput(element: React.ReactNode, disableTagCheck?: boolean): boolean;
111
+
112
+ interface KeyboardPlaceholderProps {
113
+ doHeight: (keyboardheight: number) => number;
114
+ }
115
+
116
+ export function KeyboardPlaceholderView(props: KeyboardPlaceholderProps): React.ReactElement | null;
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Children, cloneElement, createElement, forwardRef, isValidElement, memo, useEffect, useMemo, useRef, useState } from "react";
2
- import { Dimensions, findNodeHandle, Keyboard, StyleSheet, UIManager } from "react-native";
2
+ import { Animated, Dimensions, findNodeHandle, Keyboard, Platform, StyleSheet, UIManager, useAnimatedValue } from "react-native";
3
3
 
4
4
  export default function ({ children, offset = 10, disabled, onHandleDodging, disableTagCheck, checkIfElementIsFocused }) {
5
5
  if (checkIfElementIsFocused !== undefined) {
@@ -24,9 +24,9 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
24
24
  * @type {import("react").RefObject<{[key: string]: { __is_standalone: boolean, _standalone_props: { dodge_keyboard_offset?: number, dodge_keyboard_lift?: boolean }, scrollRef: import("react-native").ScrollView, inputRef: {[key: string]: { ref: import("react-native").TextInput, props: { dodge_keyboard_offset?: number, dodge_keyboard_lift?: boolean } }} }}>}
25
25
  */
26
26
  const viewRefsMap = useRef({});
27
- const isKeyboardVisible = useRef();
28
27
  const doDodgeKeyboard = useRef();
29
28
  const previousLift = useRef();
29
+ const wasVisible = useRef();
30
30
 
31
31
  const clearPreviousDodge = (scrollId) => {
32
32
  if (previousLift.current && previousLift.current !== scrollId) {
@@ -36,14 +36,26 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
36
36
  }
37
37
  }
38
38
 
39
- doDodgeKeyboard.current = () => {
39
+ /**
40
+ * @param {import('react-native').KeyboardEvent | undefined} event
41
+ * @param {boolean} visible
42
+ */
43
+ doDodgeKeyboard.current = (event, visible) => {
44
+ if (typeof visible !== 'boolean') {
45
+ if (typeof wasVisible.current === 'boolean') {
46
+ visible = wasVisible.current;
47
+ } else return;
48
+ }
49
+
50
+ wasVisible.current = visible;
51
+
40
52
  try {
41
- const keyboardInfo = Keyboard.metrics();
53
+ const keyboardInfo = event?.endCoordinates || Keyboard.metrics();
42
54
  const { width: windowWidth, height: windowHeight } = Dimensions.get('window');
43
55
 
44
56
  // console.log('doDodgeKeyboard');
45
57
  if (
46
- isKeyboardVisible.current &&
58
+ visible &&
47
59
  keyboardInfo &&
48
60
  !disabled &&
49
61
  (keyboardInfo.width === windowWidth ||
@@ -101,7 +113,7 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
101
113
  if (scrollLift) {
102
114
  setCurrentPaddedScroller([scrollId, scrollLift, newScrollY]);
103
115
  } else {
104
- scrollRef.scrollTo({ y: newScrollY, animated: true });
116
+ tryPerformScroll(scrollRef, newScrollY, true);
105
117
  setCurrentPaddedScroller();
106
118
  }
107
119
  }
@@ -124,20 +136,24 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
124
136
  }
125
137
  }
126
138
 
139
+ const tryPerformScroll = (ref, y, animated = true) => {
140
+ if (!ref) return;
141
+
142
+ if (ref.scrollTo) {
143
+ ref.scrollTo?.({ y, animated });
144
+ } else if (ref.scrollToOffset) {
145
+ ref.scrollToOffset?.({ offset: y, animated });
146
+ } else {
147
+ ref.getScrollResponder?.()?.scrollTo?.({ y, animated });
148
+ }
149
+ }
150
+
127
151
  const [paddedId, paddedSize, paddedScroll] = currentPaddedScroller || [];
128
152
 
129
153
  useEffect(() => {
130
154
  if (currentPaddedScroller) {
131
155
  const ref = viewRefsMap.current[paddedId]?.scrollRef;
132
- if (ref) {
133
- if (ref.scrollTo) {
134
- ref.scrollTo?.({ y: paddedScroll, animated: true });
135
- } else if (ref.scrollToOffset) {
136
- ref.scrollToOffset?.({ offset: paddedScroll, animated: true });
137
- } else {
138
- ref.getScrollResponder?.()?.scrollTo?.({ y: paddedScroll, animated: true });
139
- }
140
- }
156
+ tryPerformScroll(ref, paddedScroll, false);
141
157
  }
142
158
  }, [currentPaddedScroller]);
143
159
 
@@ -147,19 +163,15 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
147
163
 
148
164
  useEffect(() => {
149
165
  if (disabled) return;
150
- const frameListener = Keyboard.addListener('keyboardDidChangeFrame', e => {
151
- doDodgeKeyboard.current();
152
- });
153
-
154
- const showListener = Keyboard.addListener('keyboardDidShow', e => {
155
- isKeyboardVisible.current = true;
156
- doDodgeKeyboard.current();
157
- });
158
-
159
- const hiddenListener = Keyboard.addListener('keyboardDidHide', e => {
160
- isKeyboardVisible.current = false;
161
- doDodgeKeyboard.current();
162
- });
166
+ const frameListener = Keyboard.addListener('keyboardDidChangeFrame', e => doDodgeKeyboard.current(e));
167
+ const showListener = Keyboard.addListener(
168
+ Platform.OS === 'android' ? 'keyboardDidShow' : 'keyboardWillShow',
169
+ e => doDodgeKeyboard.current(e, true)
170
+ );
171
+ const hiddenListener = Keyboard.addListener(
172
+ Platform.OS === 'android' ? 'keyboardDidHide' : 'keyboardWillHide',
173
+ e => doDodgeKeyboard.current(e, false)
174
+ );
163
175
 
164
176
  return () => {
165
177
  frameListener.remove();
@@ -168,145 +180,158 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
168
180
  }
169
181
  }, [!disabled]);
170
182
 
171
- return (
172
- <ReactHijacker
173
- doHijack={(node, path) => {
174
- if (node?.props?.['dodge_keyboard_scan_off']) return { element: node };
175
-
176
- const isStandalone = isDodgeInput(node);
177
-
178
- if (isStandalone || isDodgeScrollable(node, disableTagCheck)) {
179
- const scrollId = path.join('=>');
180
- const initNode = () => {
181
- if (!viewRefsMap.current[scrollId])
182
- viewRefsMap.current[scrollId] = { inputRef: {} };
183
-
184
- if (isStandalone) {
185
- viewRefsMap.current[scrollId].__is_standalone = true;
186
- viewRefsMap.current[scrollId]._standalone_props = {
187
- dodge_keyboard_offset: node.props?.dodge_keyboard_offset,
188
- dodge_keyboard_lift: node.props?.dodge_keyboard_lift
189
- };
190
- }
191
- }
192
- const shouldPad = scrollId === paddedId;
193
- const contentStyle = shouldPad && StyleSheet.flatten(node.props?.contentContainerStyle);
194
- const rootRenderItem = node.prop?.renderItem;
195
- const rootKeyExtractor = node.prop?.keyExtractor;
196
- const hasInternalList = !isStandalone && (typeof rootRenderItem === 'function' && !node.props?.children);
197
-
198
- const doRefCleanup = () => {
199
- if (
200
- viewRefsMap.current[scrollId]?.scrollRef ||
201
- Object.keys(viewRefsMap.current[scrollId]?.inputRef || {}).length
202
- ) return;
203
- delete viewRefsMap.current[scrollId];
204
- }
183
+ const nodeIdIte = useRef(0);
205
184
 
206
- const injectChild = (children, childPath) =>
207
- ReactHijacker({
208
- children,
209
- path: childPath,
210
- doHijack: (inputNode, path) => {
211
- if (isDodgeInput(inputNode, disableTagCheck)) {
212
- const inputId = path.join('=>');
213
- const initInputNode = () => {
214
- initNode();
215
- if (!viewRefsMap.current[scrollId].inputRef[inputId])
216
- viewRefsMap.current[scrollId].inputRef[inputId] = {};
217
- viewRefsMap.current[scrollId].inputRef[inputId].props = {
218
- dodge_keyboard_offset: inputNode.props?.dodge_keyboard_offset,
219
- dodge_keyboard_lift: inputNode.props?.dodge_keyboard_lift
220
- };
221
- }
185
+ const onHijackNode = node => {
186
+ if (node?.props?.dodge_keyboard_scan_off || node?.props?.__dodging_keyboard) return;
222
187
 
223
- initInputNode();
224
-
225
- return {
226
- props: {
227
- ...inputNode.props,
228
- onFocus: (...args) => {
229
- doDodgeKeyboard.current();
230
- return inputNode.props?.onFocus?.(...args);
231
- },
232
- onLayout: (...args) => {
233
- doDodgeKeyboard.current();
234
- return inputNode.props?.onLayout?.(...args);
235
- },
236
- ref: r => {
237
- if (r) {
238
- initInputNode();
239
-
240
- viewRefsMap.current[scrollId].inputRef[inputId].ref = r;
241
- } else if (viewRefsMap.current[scrollId]?.inputRef?.[inputId]) {
242
- delete viewRefsMap.current[scrollId].inputRef[inputId];
243
- doRefCleanup();
244
- }
188
+ const isStandalone = isDodgeInput(node);
189
+ if (!isStandalone && !isDodgeScrollable(node, disableTagCheck)) return;
245
190
 
246
- const thatRef = inputNode.props?.ref;
247
- if (typeof thatRef === 'function') {
248
- thatRef(r);
249
- } else if (thatRef) thatRef.current = r;
250
- }
251
- }
252
- };
253
- }
191
+ const renderer = () => {
192
+ const scrollId = useMemo(() => `${++nodeIdIte.current}`, []);
193
+
194
+ const initNode = () => {
195
+ if (!viewRefsMap.current[scrollId])
196
+ viewRefsMap.current[scrollId] = { inputRef: {} };
197
+
198
+ if (isStandalone) {
199
+ viewRefsMap.current[scrollId].__is_standalone = true;
200
+ viewRefsMap.current[scrollId]._standalone_props = {
201
+ dodge_keyboard_offset: node.props?.dodge_keyboard_offset,
202
+ dodge_keyboard_lift: node.props?.dodge_keyboard_lift
203
+ };
204
+ }
205
+ }
206
+ const shouldPad = !isStandalone && scrollId === paddedId;
207
+ const contentStyle = shouldPad && StyleSheet.flatten(node.props?.contentContainerStyle);
208
+ const rootRenderItem = node.props?.renderItem;
209
+ const hasInternalList = !isStandalone && (typeof rootRenderItem === 'function' && !node.props?.children);
210
+
211
+ const doRefCleanup = () => {
212
+ if (
213
+ viewRefsMap.current[scrollId]?.scrollRef ||
214
+ Object.keys(viewRefsMap.current[scrollId]?.inputRef || {}).length
215
+ ) return;
216
+ delete viewRefsMap.current[scrollId];
217
+ }
218
+
219
+ const injectChild = (children, childPath) =>
220
+ ReactHijacker({
221
+ children,
222
+ path: childPath,
223
+ doHijack: inputNode => {
224
+ if (node?.props?.__dodging_keyboard) return;
225
+
226
+ if (!isDodgeInput(inputNode, disableTagCheck)) return;
227
+
228
+ const inputRenderer = () => {
229
+ const inputId = useMemo(() => `${++nodeIdIte.current}`, []);
230
+ const initInputNode = () => {
231
+ initNode();
232
+ if (!viewRefsMap.current[scrollId].inputRef[inputId])
233
+ viewRefsMap.current[scrollId].inputRef[inputId] = {};
234
+ viewRefsMap.current[scrollId].inputRef[inputId].props = {
235
+ dodge_keyboard_offset: inputNode.props?.dodge_keyboard_offset,
236
+ dodge_keyboard_lift: inputNode.props?.dodge_keyboard_lift
237
+ };
254
238
  }
255
- });
256
-
257
- return {
258
- props: {
259
- ...node.props,
260
- ...shouldPad ? {
261
- contentContainerStyle: {
262
- ...contentStyle,
263
- paddingBottom: paddedSize + (isNumber(contentStyle?.paddingBottom) ? contentStyle.paddingBottom : 0)
264
- }
265
- } : {},
266
- ref: r => {
267
- if (r) {
268
- initNode();
269
- viewRefsMap.current[scrollId].scrollRef = r;
270
- } else if (viewRefsMap.current[scrollId]) {
271
- viewRefsMap.current[scrollId].scrollRef = undefined;
272
- doRefCleanup();
273
- }
274
239
 
275
- const thatRef = node.props?.ref;
276
- if (typeof thatRef === 'function') {
277
- thatRef(r);
278
- } else if (thatRef) thatRef.current = r;
279
- },
280
- ...isStandalone ? {
240
+ initInputNode();
241
+
242
+ const newProps = {
243
+ ...inputNode.props,
244
+ __dodging_keyboard: true,
281
245
  onFocus: (...args) => {
282
246
  doDodgeKeyboard.current();
283
- return node.props?.onFocus?.(...args);
284
- }
285
- } : {},
286
- onLayout: (...args) => {
287
- doDodgeKeyboard.current();
288
- return node.props?.onLayout?.(...args);
289
- },
290
- ...isStandalone ? {} :
291
- hasInternalList ? {
292
- renderItem: (...args) => {
293
- const { item, index } = args[0] || {};
294
-
295
- return injectChild(
296
- rootRenderItem(...args),
297
- [
298
- ...path,
299
- index,
300
- ...typeof rootKeyExtractor === 'function' ?
301
- [rootKeyExtractor?.(item, index)] : []
302
- ]
303
- );
247
+ return inputNode.props?.onFocus?.(...args);
248
+ },
249
+ onLayout: (...args) => {
250
+ doDodgeKeyboard.current();
251
+ return inputNode.props?.onLayout?.(...args);
252
+ },
253
+ ref: r => {
254
+ if (r) {
255
+ initInputNode();
256
+
257
+ viewRefsMap.current[scrollId].inputRef[inputId].ref = r;
258
+ } else if (viewRefsMap.current[scrollId]?.inputRef?.[inputId]) {
259
+ delete viewRefsMap.current[scrollId].inputRef[inputId];
260
+ doRefCleanup();
304
261
  }
305
- } : { children: injectChild(node.props?.children, path) }
262
+
263
+ const thatRef = inputNode.props?.ref;
264
+ if (typeof thatRef === 'function') {
265
+ thatRef(r);
266
+ } else if (thatRef) thatRef.current = r;
267
+ }
268
+ };
269
+
270
+ return cloneElement(inputNode, newProps);
306
271
  }
307
- };
308
- }
309
- }}>
272
+
273
+ return createHijackedElement(
274
+ <__HijackNode>
275
+ {inputRenderer}
276
+ </__HijackNode>
277
+ );
278
+ }
279
+ });
280
+
281
+ const newProps = {
282
+ ...node.props,
283
+ __dodging_keyboard: true,
284
+ ...shouldPad ? {
285
+ contentContainerStyle: {
286
+ ...contentStyle,
287
+ paddingBottom: paddedSize + (isNumber(contentStyle?.paddingBottom) ? contentStyle.paddingBottom : 0)
288
+ }
289
+ } : {},
290
+ ref: r => {
291
+ if (r) {
292
+ initNode();
293
+ viewRefsMap.current[scrollId].scrollRef = r;
294
+ } else if (viewRefsMap.current[scrollId]) {
295
+ viewRefsMap.current[scrollId].scrollRef = undefined;
296
+ doRefCleanup();
297
+ }
298
+
299
+ const thatRef = node.props?.ref;
300
+ if (typeof thatRef === 'function') {
301
+ thatRef(r);
302
+ } else if (thatRef) thatRef.current = r;
303
+ },
304
+ ...isStandalone ? {
305
+ onFocus: (...args) => {
306
+ doDodgeKeyboard.current();
307
+ return node.props?.onFocus?.(...args);
308
+ }
309
+ } : {},
310
+ onLayout: (...args) => {
311
+ doDodgeKeyboard.current();
312
+ return node.props?.onLayout?.(...args);
313
+ },
314
+ ...isStandalone ? {} :
315
+ hasInternalList ? {
316
+ renderItem: (...args) => {
317
+ return injectChild(rootRenderItem(...args));
318
+ }
319
+ } : { children: injectChild(node.props?.children) }
320
+ };
321
+
322
+ return cloneElement(node, newProps);
323
+ }
324
+
325
+ return createHijackedElement(
326
+ <__HijackNode>
327
+ {renderer}
328
+ </__HijackNode>
329
+ );
330
+ };
331
+
332
+ return (
333
+ <ReactHijacker
334
+ doHijack={onHijackNode}>
310
335
  {children}
311
336
  </ReactHijacker>
312
337
  );
@@ -329,62 +354,43 @@ const REACT_SYMBOLS = {
329
354
  memo: Symbol.for('react.memo')
330
355
  };
331
356
 
332
- export function ReactHijacker({ children, doHijack, path }) {
333
- const renderRefs = useMemo(() => new Map(), []);
334
-
357
+ export function ReactHijacker({ children, doHijack, enableLocator }) {
335
358
  const instantDoHijack = useRef();
336
359
  instantDoHijack.current = doHijack;
337
360
 
338
- const injectIntoTree = (node, path = [], arrayIndex) => {
361
+ const injectIntoTree = (node, path) => {
339
362
  if (!node) return node;
340
363
  if (Array.isArray(node)) {
341
- path = [...path, ...arrayIndex === undefined ? [0] : [arrayIndex]];
342
- return Children.map(node, (v, i) => injectIntoTree(v, path, i));
364
+ return Children.map(node, (v, i) => injectIntoTree(v, path && [...path, i]));
343
365
  }
344
366
  if (!isValidElement(node)) return node;
345
367
 
346
- path = [...path, ...arrayIndex === undefined ? [0] : [arrayIndex], getNodeId(node)];
368
+ if (path) path = [...path, getNodeId(node)];
347
369
 
348
370
  let thisObj;
349
- if (thisObj = instantDoHijack.current?.(node, path)) {
350
- const { element, props } = thisObj;
351
-
352
- if (Object.hasOwn(thisObj, 'element')) return element;
353
- if (props) return cloneElement(node, props);
354
- return node;
371
+ if (Object.hasOwn((thisObj = instantDoHijack.current?.(node, path)) || {}, '__element')) {
372
+ return thisObj.__element;
355
373
  }
356
374
 
357
375
  if (!isHostElement(node)) {
358
376
  const wrapNodeType = (nodeType, pathway, pathKey) => {
359
- pathway = [...pathway, getNodeId(undefined, nodeType, pathKey)];
360
- const path_id = pathway.join(',');
361
- let renderRefStore = renderRefs.get(nodeType);
362
-
363
- if (renderRefStore?.[path_id]) return renderRefStore[path_id];
377
+ if (pathway) pathway = [...pathway, getNodeId(undefined, nodeType, pathKey)];
364
378
 
365
379
  // if (doLogging) console.log('wrapNodeType path:', pathway, ' node:', nodeType);
366
380
  const render = (renderedNode) => {
367
381
  // if (doLogging) console.log('deep path:', pathway, ' node:', renderedNode);
368
- return injectIntoTree(renderedNode, pathway);
382
+ return injectIntoTree(renderedNode, pathway && [...pathway, 0]);
369
383
  }
370
384
 
371
- let newType;
372
-
373
385
  if (typeof nodeType === 'function') { // check self closed tag
374
- newType = hijackRender(nodeType, render);
386
+ return hijackRender(nodeType, render);
375
387
  } else if (nodeType?.$$typeof === REACT_SYMBOLS.forwardRef) {
376
- newType = forwardRef(hijackRender(nodeType.render, render));
388
+ return forwardRef(hijackRender(nodeType.render, render));
377
389
  } else if (nodeType?.$$typeof === REACT_SYMBOLS.memo) {
378
- newType = memo(wrapNodeType(nodeType.type, pathway), nodeType.compare);
390
+ const newType = memo(wrapNodeType(nodeType.type, pathway), nodeType.compare);
379
391
  newType.displayName = nodeType.displayName || nodeType.name;
380
- }
381
-
382
- if (newType) {
383
- if (!renderRefStore) renderRefs.set(nodeType, renderRefStore = {});
384
- renderRefStore[path_id] = newType;
385
392
  return newType;
386
393
  }
387
-
388
394
  return nodeType;
389
395
  }
390
396
 
@@ -394,15 +400,24 @@ export function ReactHijacker({ children, doHijack, path }) {
394
400
  node.type?.$$typeof === REACT_SYMBOLS.memo // check memo
395
401
  ) {
396
402
  // if (doLogging) console.log('doLog path:', path, ' node:', node);
397
- const injectedType = wrapNodeType(node.type, path.slice(0, -1), node.key);
398
- return createElement(
399
- injectedType,
400
- {
401
- ...node.props,
402
- key: node.key,
403
- // ...isForwardRef ? { ref: node.ref } : {}
404
- },
405
- node.props?.children
403
+ return (
404
+ <__HijackNodePath>
405
+ {() => {
406
+ const hijackType = useMemo(() =>
407
+ wrapNodeType(node.type, path && path.slice(0, -1), node.key),
408
+ [node.type]
409
+ );
410
+
411
+ return createElement(
412
+ hijackType,
413
+ {
414
+ ...node.props,
415
+ key: node.key
416
+ },
417
+ node.props?.children
418
+ );
419
+ }}
420
+ </__HijackNodePath>
406
421
  );
407
422
  }
408
423
  }
@@ -410,15 +425,24 @@ export function ReactHijacker({ children, doHijack, path }) {
410
425
  const children = node.props?.children;
411
426
  if (children)
412
427
  return cloneElement(node, {
413
- children: injectIntoTree(children, path)
428
+ children: injectIntoTree(children, path && [...path, 0])
414
429
  });
415
430
 
416
431
  return node;
417
432
  };
418
433
 
419
- return injectIntoTree(children, path);
434
+ return injectIntoTree(children, enableLocator ? [] : undefined);
420
435
  };
421
436
 
437
+ export const createHijackedElement = (element) => ({ __element: element });
438
+ export function __HijackNode({ children }) {
439
+ return children?.();
440
+ }
441
+
442
+ function __HijackNodePath({ children }) {
443
+ return children?.();
444
+ }
445
+
422
446
  const hijackRender = (type, doHijack) =>
423
447
  new Proxy(type, {
424
448
  apply(target, thisArg, args) {
@@ -492,4 +516,62 @@ export const isDodgeInput = (element, disableTagCheck) => {
492
516
 
493
517
  return inputTypes.includes(element.type?.displayName)
494
518
  || inputTypes.includes(element.type?.name);
495
- };
519
+ };
520
+
521
+ export const KeyboardPlaceholderView = ({ doHeight }) => {
522
+ const height = useAnimatedValue(0);
523
+
524
+ const instantDoHeight = useRef();
525
+ instantDoHeight.current = doHeight;
526
+
527
+ useEffect(() => {
528
+ let wasVisible;
529
+ /**
530
+ * @param {import('react-native').KeyboardEvent} event
531
+ * @param {boolean} visible
532
+ */
533
+ const updateKeyboardHeight = (event, visible) => {
534
+ if (typeof visible !== 'boolean') {
535
+ if (typeof wasVisible === 'boolean') {
536
+ visible = wasVisible;
537
+ } else return;
538
+ }
539
+
540
+ wasVisible = visible;
541
+
542
+ const { endCoordinates, isEventFromThisApp, duration } = event;
543
+ if (Platform.OS === 'ios' && !isEventFromThisApp) return;
544
+
545
+ const kh = visible ? endCoordinates.height : 0;
546
+ const newHeight = Math.max(0, instantDoHeight.current ? instantDoHeight.current(kh) : kh);
547
+ const newDuration = (Math.abs(height._value - newHeight) * duration) / endCoordinates.height;
548
+
549
+ Animated.timing(height, {
550
+ duration: newDuration,
551
+ toValue: newHeight,
552
+ useNativeDriver: false
553
+ }).start();
554
+ }
555
+
556
+ const initialMetric = Keyboard.metrics();
557
+ if (initialMetric) updateKeyboardHeight(initialMetric, true);
558
+
559
+ const frameListener = Keyboard.addListener('keyboardDidChangeFrame', e => updateKeyboardHeight(e));
560
+ const showListener = Keyboard.addListener(
561
+ Platform.OS === 'android' ? 'keyboardDidShow' : 'keyboardWillShow',
562
+ e => updateKeyboardHeight(e, true)
563
+ );
564
+ const hiddenListener = Keyboard.addListener(
565
+ Platform.OS === 'android' ? 'keyboardDidHide' : 'keyboardWillHide',
566
+ e => updateKeyboardHeight(e, false)
567
+ );
568
+
569
+ return () => {
570
+ frameListener.remove();
571
+ showListener.remove();
572
+ hiddenListener.remove();
573
+ }
574
+ }, []);
575
+
576
+ return <Animated.View style={{ height }} />;
577
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-dodge-keyboard",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "react-native-dodge-keyboard is a tiny library designed to flawlessly move your UI out of the way of the keyboard",
5
5
  "keywords": [
6
6
  "react-native",