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.
- package/index.d.ts +10 -1
- package/index.js +282 -200
- 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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
|
|
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
|
-
|
|
207
|
-
|
|
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
|
-
|
|
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
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
361
|
+
const injectIntoTree = (node, path) => {
|
|
339
362
|
if (!node) return node;
|
|
340
363
|
if (Array.isArray(node)) {
|
|
341
|
-
|
|
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,
|
|
368
|
+
if (path) path = [...path, getNodeId(node)];
|
|
347
369
|
|
|
348
370
|
let thisObj;
|
|
349
|
-
if (thisObj = instantDoHijack.current?.(node, path)) {
|
|
350
|
-
|
|
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
|
-
|
|
386
|
+
return hijackRender(nodeType, render);
|
|
375
387
|
} else if (nodeType?.$$typeof === REACT_SYMBOLS.forwardRef) {
|
|
376
|
-
|
|
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
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
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,
|
|
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