react-native-dodge-keyboard 1.0.4 → 1.0.6

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 +1 -1
  2. package/index.js +58 -28
  3. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -11,7 +11,7 @@ export interface LiftUpDodge {
11
11
  /**
12
12
  * A reference to the view that should be lifted.
13
13
  *
14
- * null is returned if the view has been recently removed from the node hierarchy
14
+ * null may be returned if the view has been recently removed from the node hierarchy
15
15
  */
16
16
  viewRef: ScrollView | View | null;
17
17
  }
package/index.js CHANGED
@@ -25,29 +25,30 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
25
25
  */
26
26
  const viewRefsMap = useRef({});
27
27
  const doDodgeKeyboard = useRef();
28
- const previousLift = useRef();
28
+ const previousLift = useRef({ scrollId: undefined, lift: undefined });
29
29
  const wasVisible = useRef();
30
30
  const pendingIdleTask = useRef();
31
+ const resizerTimer = useRef();
31
32
  const lastKeyboardEvent = useRef();
32
33
 
33
34
  const clearPreviousDodge = (scrollId) => {
34
- if (previousLift.current && previousLift.current !== scrollId) {
35
- const viewRef = viewRefsMap.current[previousLift.current]?.scrollRef;
35
+ if (previousLift.current.scrollId && previousLift.current.scrollId !== scrollId) {
36
+ const viewRef = viewRefsMap.current[previousLift.current.scrollId]?.scrollRef;
36
37
  onHandleDodging?.({
37
38
  liftUp: 0,
38
39
  viewRef: viewRef || null,
39
40
  keyboardEvent: lastKeyboardEvent.current
40
41
  });
41
- previousLift.current = undefined;
42
+ previousLift.current = { scrollId: undefined, lift: undefined };
42
43
  }
43
44
  }
44
45
 
45
46
  /**
46
47
  * @param {import('react-native').KeyboardEvent | undefined} event
47
48
  * @param {boolean} visible
48
- * @param {boolean} fromIdle
49
+ * @param {{ fromIdle?: boolean, fromTimer?: boolean } | undefined} eventContext
49
50
  */
50
- doDodgeKeyboard.current = (event, visible, fromIdle) => {
51
+ doDodgeKeyboard.current = (event, visible, eventContext) => {
51
52
  if (Platform.OS === 'ios' && event && !event?.isEventFromThisApp) return;
52
53
 
53
54
  if (typeof visible !== 'boolean') {
@@ -68,6 +69,10 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
68
69
  cancelIdleCallback(pendingIdleTask.current);
69
70
  pendingIdleTask.current = undefined;
70
71
 
72
+ if (resizerTimer.current !== undefined)
73
+ clearTimeout(resizerTimer.current);
74
+ resizerTimer.current = undefined;
75
+
71
76
  if (
72
77
  visible &&
73
78
  keyboardInfo &&
@@ -84,10 +89,15 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
84
89
  ).flat();
85
90
 
86
91
  const initIdleTask = () => {
87
- if (!fromIdle)
92
+ if (!eventContext && pendingIdleTask.current === undefined)
88
93
  pendingIdleTask.current = requestIdleCallback(() => {
89
- doDodgeKeyboard.current(undefined, undefined, true);
90
- });
94
+ doDodgeKeyboard.current(undefined, undefined, { fromIdle: true });
95
+ }, { timeout: 300 });
96
+
97
+ if (!eventContext?.fromTimer && resizerTimer.current === undefined)
98
+ resizerTimer.current = setTimeout(() => {
99
+ doDodgeKeyboard.current(undefined, undefined, { fromTimer: true });
100
+ }, 700);
91
101
  }
92
102
 
93
103
  const checkFocused = checkIfElementIsFocused || (r => r?.isFocused?.());
@@ -97,16 +107,17 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
97
107
  if (scrollRef) {
98
108
  if (__is_standalone) {
99
109
  if (checkFocused(scrollRef, allInputList)) {
100
- UIManager.measure(findNodeHandle(scrollRef), (_x, _y, w, h, x, y) => {
101
- const { dodge_keyboard_offset } = _standalone_props || {};
110
+ UIManager.measure(findNodeHandle(scrollRef), (x, y, width, height, pageX, pageY) => {
111
+ const { dodge_keyboard_offset, dodge_keyboard_clipping } = _standalone_props || {};
102
112
  const thisOffset = isNumber(dodge_keyboard_offset) ? dodge_keyboard_offset : offset;
103
113
 
104
- const liftUp = Math.max(0, (y - keyboardInfo.screenY) + Math.min(h + thisOffset, keyboardInfo.screenY));
114
+ const liftUp = (pageY - keyboardInfo.screenY) + Math.min(height + thisOffset, keyboardInfo.screenY);
105
115
  clearPreviousDodge(scrollId);
106
- if (liftUp) {
107
- previousLift.current = scrollId;
116
+ if (liftUp > 0 || (dodge_keyboard_clipping && liftUp && previousLift.current.lift !== liftUp)) {
117
+ previousLift.current = { scrollId, lift: liftUp };
108
118
  onHandleDodging?.({
109
119
  liftUp,
120
+ layout: { x, y, width, height, pageX, pageY },
110
121
  viewRef: scrollRef,
111
122
  keyboardEvent: lastKeyboardEvent.current
112
123
  });
@@ -120,23 +131,27 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
120
131
  if (checkFocused(inputObj, allInputList)) {
121
132
  Promise.all([
122
133
  new Promise(resolve => {
123
- UIManager.measure(findNodeHandle(scrollRef), (x, y, w, h, px, py) => {
124
- resolve({ h, py });
134
+ UIManager.measure(findNodeHandle(scrollRef), (x, y, width, height, pageX, pageY) => {
135
+ resolve({
136
+ h: height,
137
+ py: pageY,
138
+ scrollLayout: { x, y, width, height, pageX, pageY }
139
+ });
125
140
  });
126
141
  }),
127
142
  new Promise(resolve => {
128
- inputObj.measure((x, y, w, h, px, py) => { // y is dynamic
129
- resolve({ py });
143
+ inputObj.measure((x, y, width, height, pageX, pageY) => { // y is dynamic
144
+ resolve({ py: pageY, layout: { x, y, width, height, pageX, pageY } });
130
145
  });
131
146
  }),
132
147
  new Promise((resolve, reject) => {
133
- inputObj.measureLayout(scrollRef, (l, t, w, h) => { // t is fixed
134
- resolve({ t, h })
148
+ inputObj.measureLayout(scrollRef, (l, t, width, height) => { // t is fixed
149
+ resolve({ t, h: height, relativeLayout: { left: l, top: t, width, height } });
135
150
  }, reject);
136
151
  })
137
- ]).then(([{ h: sh, py: sy }, { py: y }, { t, h }]) => {
152
+ ]).then(([{ h: sh, py: sy, scrollLayout }, { py: y, layout }, { t, h, relativeLayout }]) => {
138
153
 
139
- const { dodge_keyboard_offset } = props || {};
154
+ const { dodge_keyboard_offset, dodge_keyboard_clipping } = props || {};
140
155
  const thisOffset = isNumber(dodge_keyboard_offset) ? dodge_keyboard_offset : offset;
141
156
 
142
157
  const scrollInputY = y - sy;
@@ -149,10 +164,13 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
149
164
  // for lifting up the scroll-view
150
165
  const liftUp = Math.max(0, requiredScrollY - t);
151
166
  clearPreviousDodge(scrollId);
152
- if (liftUp) {
153
- previousLift.current = scrollId;
167
+ if (liftUp > 0 || (dodge_keyboard_clipping && liftUp && previousLift.current.lift !== liftUp)) {
168
+ previousLift.current = { scrollId, lift: liftUp };
154
169
  onHandleDodging?.({
155
170
  liftUp,
171
+ layout,
172
+ scrollLayout,
173
+ relativeLayout,
156
174
  viewRef: scrollRef,
157
175
  keyboardEvent: lastKeyboardEvent.current
158
176
  });
@@ -218,11 +236,19 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
218
236
  if (disabled) return;
219
237
  const frameListener = Keyboard.addListener('keyboardDidChangeFrame', e => doDodgeKeyboard.current(e));
220
238
  const showListener = Keyboard.addListener(
221
- Platform.OS === 'android' ? 'keyboardDidShow' : 'keyboardWillShow',
239
+ 'keyboardWillShow',
222
240
  e => doDodgeKeyboard.current(e, true)
223
241
  );
224
242
  const hiddenListener = Keyboard.addListener(
225
- Platform.OS === 'android' ? 'keyboardDidHide' : 'keyboardWillHide',
243
+ 'keyboardWillHide',
244
+ e => doDodgeKeyboard.current(e, false)
245
+ );
246
+ const didShowListener = Keyboard.addListener(
247
+ 'keyboardDidShow',
248
+ e => doDodgeKeyboard.current(e, true)
249
+ );
250
+ const didHideListener = Keyboard.addListener(
251
+ 'keyboardDidHide',
226
252
  e => doDodgeKeyboard.current(e, false)
227
253
  );
228
254
 
@@ -230,6 +256,8 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
230
256
  frameListener.remove();
231
257
  showListener.remove();
232
258
  hiddenListener.remove();
259
+ didShowListener.remove();
260
+ didHideListener.remove();
233
261
  }
234
262
  }, [!disabled]);
235
263
 
@@ -252,7 +280,8 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
252
280
  viewRefsMap.current[scrollId].__is_standalone = true;
253
281
  viewRefsMap.current[scrollId]._standalone_props = {
254
282
  dodge_keyboard_offset: node.props?.dodge_keyboard_offset,
255
- dodge_keyboard_lift: node.props?.dodge_keyboard_lift
283
+ dodge_keyboard_lift: node.props?.dodge_keyboard_lift,
284
+ dodge_keyboard_clipping: node.props?.dodge_keyboard_clipping
256
285
  };
257
286
  }
258
287
  }
@@ -282,7 +311,8 @@ export default function ({ children, offset = 10, disabled, onHandleDodging, dis
282
311
  viewRefsMap.current[scrollId].inputRef[inputId] = {};
283
312
  viewRefsMap.current[scrollId].inputRef[inputId].props = {
284
313
  dodge_keyboard_offset: inputNode.props?.dodge_keyboard_offset,
285
- dodge_keyboard_lift: inputNode.props?.dodge_keyboard_lift
314
+ dodge_keyboard_lift: inputNode.props?.dodge_keyboard_lift,
315
+ dodge_keyboard_clipping: inputNode.props?.dodge_keyboard_clipping
286
316
  };
287
317
  }
288
318
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-dodge-keyboard",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
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",