react-native-auto-positioned-popup 1.0.3 → 1.0.5
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/AutoPositionedPopup.d.ts.map +1 -1
- package/lib/AutoPositionedPopup.js +264 -30
- package/package.json +2 -2
- package/src/AutoPositionedPopup.tsx +378 -42
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoPositionedPopup.d.ts","sourceRoot":"","sources":["../src/AutoPositionedPopup.tsx"],"names":[],"mappings":"AAAA,OAAc,EAGZ,yBAAyB,EAEzB,mBAAmB,EAOpB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"AutoPositionedPopup.d.ts","sourceRoot":"","sources":["../src/AutoPositionedPopup.tsx"],"names":[],"mappings":"AAAA,OAAc,EAGZ,yBAAyB,EAEzB,mBAAmB,EAOpB,MAAM,OAAO,CAAC;AAYf,OAAO,EAAC,wBAAwB,EAAqB,MAAM,4BAA4B,CAAC;AAgMxF,QAAA,MAAM,mBAAmB,EAAE,mBAAmB,CAC5C,yBAAyB,CAAC,wBAAwB,CAAC,CAqoBpD,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -88,16 +88,73 @@ const PopupList = memo(({ data, selectedItem, onItemPress, renderItem, keyExtrac
|
|
|
88
88
|
<AdvancedFlatList data={internalData} keyExtractor={keyExtractor} renderItem={renderItem || defaultRenderItem} keyboardShouldPersistTaps="always" showsVerticalScrollIndicator={true} nestedScrollEnabled={true}/>
|
|
89
89
|
</View>);
|
|
90
90
|
});
|
|
91
|
+
// List layout constants
|
|
92
|
+
const listLayout = {
|
|
93
|
+
height: 200,
|
|
94
|
+
};
|
|
91
95
|
// Main AutoPositionedPopup component
|
|
92
96
|
const AutoPositionedPopup = memo(forwardRef((props, parentRef) => {
|
|
93
|
-
|
|
97
|
+
console.log('AutoPositionedPopup props=', props);
|
|
98
|
+
const { tag, style, AutoPositionedPopupBtnStyle, placeholder = 'Please Select', onSubmitEditing, TextInputProps = {}, inputStyle, labelStyle, popUpViewStyle = { left: '5%', width: '90%' }, fetchData, renderItem, onItemSelected, localSearch = false, pageSize = 20, selectedItem, useTextInput = false, btwChildren, CustomRow = ({ children }) => <View>{children}</View>, keyExtractor = (item) => item === null || item === void 0 ? void 0 : item.id, AutoPositionedPopupBtnDisabled = false, forceRemoveAllRootViewOnItemSelected = false, centerDisplay = false, selectedItemBackgroundColor = 'rgba(116, 116, 128, 0.08)', } = props;
|
|
99
|
+
// State management similar to project implementation
|
|
100
|
+
const [state, setState] = useState({
|
|
101
|
+
isFocus: false,
|
|
102
|
+
selectedItem: selectedItem,
|
|
103
|
+
});
|
|
94
104
|
// Use RootView context
|
|
95
|
-
const { addRootView, removeRootView, rootViews,
|
|
105
|
+
const { addRootView, removeRootView, rootViews, setSearchQuery: setContextSearchQuery, setRootViewNativeStyle } = useRootView();
|
|
96
106
|
const rootViewsRef = useRef(rootViews);
|
|
107
|
+
// Track TextInput focus and RootView states like project implementation
|
|
108
|
+
const hasTriggeredFocus = useRef(false);
|
|
109
|
+
const hasAddedRootView = useRef(false);
|
|
110
|
+
const hasShownRootView = useRef(false);
|
|
111
|
+
// Additional refs for keyboard and position tracking
|
|
112
|
+
const ref_isFocus = useRef();
|
|
113
|
+
const ref_isKeyboardFullyShown = useRef();
|
|
114
|
+
const ref_listPos = useRef();
|
|
115
|
+
const keyboardVisibleRef = useRef(false);
|
|
116
|
+
const refAutoPositionedPopup = useRef(null);
|
|
117
|
+
// Simple keyboard status tracking (alternative to useKeyboardStatus hook)
|
|
118
|
+
const [isKeyboardFullyShown, setIsKeyboardFullyShown] = useState(false);
|
|
119
|
+
// Keyboard listeners
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => {
|
|
122
|
+
setIsKeyboardFullyShown(true);
|
|
123
|
+
});
|
|
124
|
+
const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {
|
|
125
|
+
setIsKeyboardFullyShown(false);
|
|
126
|
+
});
|
|
127
|
+
return () => {
|
|
128
|
+
keyboardDidShowListener === null || keyboardDidShowListener === void 0 ? void 0 : keyboardDidShowListener.remove();
|
|
129
|
+
keyboardDidHideListener === null || keyboardDidHideListener === void 0 ? void 0 : keyboardDidHideListener.remove();
|
|
130
|
+
};
|
|
131
|
+
}, []);
|
|
97
132
|
useEffect(() => {
|
|
133
|
+
console.log('AutoPositionedPopup rootViews=', rootViews);
|
|
98
134
|
rootViewsRef.current = rootViews;
|
|
135
|
+
if (rootViews.length === 0) {
|
|
136
|
+
hasAddedRootView.current = false;
|
|
137
|
+
hasShownRootView.current = false;
|
|
138
|
+
hasTriggeredFocus.current = false;
|
|
139
|
+
setState((prevState) => {
|
|
140
|
+
return Object.assign(Object.assign({}, prevState), { isFocus: false });
|
|
141
|
+
});
|
|
142
|
+
}
|
|
99
143
|
}, [rootViews]);
|
|
100
|
-
//
|
|
144
|
+
// Sync selectedItem changes like project implementation
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
var _a, _b;
|
|
147
|
+
console.log('AutoPositionedPopup useEffect tag=', tag);
|
|
148
|
+
console.log('AutoPositionedPopup useEffect selectedItem=', selectedItem);
|
|
149
|
+
console.log('AutoPositionedPopup useEffect state.selectedItem=', state.selectedItem);
|
|
150
|
+
if (((_a = state.selectedItem) === null || _a === void 0 ? void 0 : _a.id) !== (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id) || ((_b = state.selectedItem) === null || _b === void 0 ? void 0 : _b.title) !== (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.title)) {
|
|
151
|
+
console.log('AutoPositionedPopup useEffect selectedItem!=state.selectedItem');
|
|
152
|
+
setState((prevState) => {
|
|
153
|
+
return Object.assign(Object.assign({}, prevState), { selectedItem: selectedItem });
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}, [selectedItem, state.selectedItem, tag]);
|
|
157
|
+
// Legacy state for compatibility
|
|
101
158
|
const [isVisible, setIsVisible] = useState(false);
|
|
102
159
|
const [data, setData] = useState([]);
|
|
103
160
|
const [loading, setLoading] = useState(false);
|
|
@@ -255,22 +312,38 @@ const AutoPositionedPopup = memo(forwardRef((props, parentRef) => {
|
|
|
255
312
|
});
|
|
256
313
|
}, 100);
|
|
257
314
|
}, [calculatePosition, loadData, popupPosition, useTextInput, placeholder, theme, inputStyle, TextInputProps, data, selectedItem, renderItem, keyExtractor, centerDisplay, addRootView, hidePopup, handleSearchChange, handleItemPress, LIST_HEIGHT, selectedItemBackgroundColor]);
|
|
258
|
-
// Handle button press
|
|
315
|
+
// Handle button press - following project implementation logic
|
|
259
316
|
const handleButtonPress = useCallback(() => {
|
|
260
317
|
if (AutoPositionedPopupBtnDisabled)
|
|
261
318
|
return;
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
319
|
+
console.log('AutoPositionedPopup onPress tag=', tag);
|
|
320
|
+
console.log('AutoPositionedPopup onPress state.isFocus=', state.isFocus);
|
|
321
|
+
console.log('AutoPositionedPopup onPress useTextInput=', useTextInput);
|
|
322
|
+
console.log('AutoPositionedPopup onPress hasAddedRootView.current=', hasAddedRootView.current);
|
|
323
|
+
console.log('AutoPositionedPopup onPress hasShownRootView.current=', hasShownRootView.current);
|
|
324
|
+
console.log('AutoPositionedPopup onPress hasTriggeredFocus.current=', hasTriggeredFocus.current);
|
|
325
|
+
console.log('AutoPositionedPopup onPress state.selectedItem=', state.selectedItem);
|
|
326
|
+
setState((prevState) => {
|
|
327
|
+
return Object.assign(Object.assign({}, prevState), { isFocus: true });
|
|
328
|
+
});
|
|
329
|
+
if (!hasAddedRootView.current && useTextInput) {
|
|
330
|
+
// TextInput version: hide first, show after keyboard fully appears
|
|
331
|
+
hasAddedRootView.current = true;
|
|
332
|
+
hasShownRootView.current = false;
|
|
333
|
+
addRootView({
|
|
334
|
+
id: tag,
|
|
335
|
+
style: {
|
|
336
|
+
top: 0,
|
|
337
|
+
left: 0,
|
|
338
|
+
width: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.width,
|
|
339
|
+
height: listLayout.height,
|
|
340
|
+
opacity: 0,
|
|
341
|
+
},
|
|
342
|
+
component: (<PopupList data={data} selectedItem={state.selectedItem} onItemPress={handleItemPress} renderItem={renderItem} keyExtractor={keyExtractor} theme={theme} rootViewsRef={rootViewsRef} fetchData={fetchData} localSearch={localSearch} pageSize={pageSize} onDataUpdate={handleDataUpdate} selectedItemBackgroundColor={selectedItemBackgroundColor}/>),
|
|
343
|
+
useModal: false,
|
|
344
|
+
});
|
|
272
345
|
}
|
|
273
|
-
}, [AutoPositionedPopupBtnDisabled, useTextInput,
|
|
346
|
+
}, [AutoPositionedPopupBtnDisabled, useTextInput, state.isFocus, state.selectedItem, tag, hasAddedRootView, hasShownRootView, hasTriggeredFocus, addRootView, popUpViewStyle, data, handleItemPress, renderItem, keyExtractor, theme, rootViewsRef, fetchData, localSearch, pageSize, handleDataUpdate, selectedItemBackgroundColor]);
|
|
274
347
|
// Imperative handle for parent component access
|
|
275
348
|
useImperativeHandle(parentRef, () => ({
|
|
276
349
|
clearSelectedItem: () => {
|
|
@@ -280,7 +353,23 @@ const AutoPositionedPopup = memo(forwardRef((props, parentRef) => {
|
|
|
280
353
|
showPopup,
|
|
281
354
|
hidePopup,
|
|
282
355
|
}), [tag, showPopup, hidePopup]);
|
|
283
|
-
//
|
|
356
|
+
// Component lifecycle management like project implementation
|
|
357
|
+
useEffect(() => {
|
|
358
|
+
console.log(`AutoPositionedPopup componentDidMount tag=`, tag);
|
|
359
|
+
//componentWillUnmount
|
|
360
|
+
return () => {
|
|
361
|
+
console.log(`AutoPositionedPopup componentWillUnmount tag=`, tag);
|
|
362
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected, rootViewsRef.current);
|
|
363
|
+
setContextSearchQuery('');
|
|
364
|
+
if (textInputRef.current) {
|
|
365
|
+
textInputRef.current.blur();
|
|
366
|
+
hasTriggeredFocus.current = false;
|
|
367
|
+
hasAddedRootView.current = false;
|
|
368
|
+
hasShownRootView.current = false;
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
}, [tag, removeRootView, forceRemoveAllRootViewOnItemSelected, setContextSearchQuery]);
|
|
372
|
+
// Cleanup debounce timer
|
|
284
373
|
useEffect(() => {
|
|
285
374
|
return () => {
|
|
286
375
|
if (debounceTimerRef.current) {
|
|
@@ -288,19 +377,164 @@ const AutoPositionedPopup = memo(forwardRef((props, parentRef) => {
|
|
|
288
377
|
}
|
|
289
378
|
};
|
|
290
379
|
}, []);
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
380
|
+
useEffect(() => {
|
|
381
|
+
var _a, _b;
|
|
382
|
+
console.log('AutoPositionedPopup useEffect tag=', tag);
|
|
383
|
+
console.log('AutoPositionedPopup useEffect state.isFocus=', state.isFocus);
|
|
384
|
+
console.log('AutoPositionedPopup useEffect isKeyboardFullyShown=', isKeyboardFullyShown);
|
|
385
|
+
console.log('AutoPositionedPopup useEffect ref_isFocus.current=', ref_isFocus.current);
|
|
386
|
+
console.log('AutoPositionedPopup useEffect ref_isKeyboardFullyShown.current=', ref_isKeyboardFullyShown.current);
|
|
387
|
+
console.log('AutoPositionedPopup useEffect useTextInput=', useTextInput);
|
|
388
|
+
console.log('AutoPositionedPopup useEffect TextInputProps=', TextInputProps);
|
|
389
|
+
console.log('AutoPositionedPopup useEffect hasAddedRootView.current=', hasAddedRootView.current);
|
|
390
|
+
console.log('AutoPositionedPopup useEffect hasShownRootView.current=', hasShownRootView.current);
|
|
391
|
+
if (useTextInput) {
|
|
392
|
+
if (isKeyboardFullyShown && hasAddedRootView.current && !hasShownRootView.current && state.isFocus) {
|
|
393
|
+
(_a = refAutoPositionedPopup.current) === null || _a === void 0 ? void 0 : _a.measureInWindow((x, y, width, height) => {
|
|
394
|
+
console.log('AutoPositionedPopup measureInWindow x=', x, ' y=', y, ' width=', width, ' height=', height);
|
|
395
|
+
// Get the full screen height (including the status bar and navigation bar)
|
|
396
|
+
const screenHeight = Dimensions.get('screen').height;
|
|
397
|
+
console.log('AutoPositionedPopup screenHeight=', screenHeight);
|
|
398
|
+
if (y + height < screenHeight / 2 - listLayout.height / 2) {
|
|
399
|
+
console.log('AutoPositionedPopup y + height < screenHeight / 2');
|
|
400
|
+
ref_listPos.current = { x: x, y: y + height, width: width };
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
console.log('AutoPositionedPopup y + height >= screenHeight / 2');
|
|
404
|
+
ref_listPos.current = { x: x, y: y - listLayout.height, width: width };
|
|
405
|
+
}
|
|
406
|
+
console.log('AutoPositionedPopup ref_listPos.current=', ref_listPos.current);
|
|
407
|
+
setRootViewNativeStyle(tag, {
|
|
408
|
+
top: ref_listPos.current.y,
|
|
409
|
+
left: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.left,
|
|
410
|
+
width: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.width,
|
|
411
|
+
height: listLayout.height,
|
|
412
|
+
opacity: 1,
|
|
413
|
+
});
|
|
414
|
+
hasShownRootView.current = true;
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
else if (!isKeyboardFullyShown && ref_isFocus.current) {
|
|
418
|
+
console.log('AutoPositionedPopup isKeyboardFullyShown useEffect removeRootView tag=', tag, ' forceRemoveAllRootViewOnItemSelected=', forceRemoveAllRootViewOnItemSelected);
|
|
419
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected);
|
|
420
|
+
setState((prevState) => {
|
|
421
|
+
return Object.assign(Object.assign({}, prevState), { isFocus: false });
|
|
422
|
+
});
|
|
423
|
+
setContextSearchQuery('');
|
|
424
|
+
hasAddedRootView.current = false;
|
|
425
|
+
hasShownRootView.current = false;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
if (state.isFocus) {
|
|
430
|
+
(_b = refAutoPositionedPopup.current) === null || _b === void 0 ? void 0 : _b.measureInWindow((x, y, width, height) => {
|
|
431
|
+
console.log('AutoPositionedPopup measureInWindow x=', x, ' y=', y, ' width=', width, ' height=', height);
|
|
432
|
+
// Get the full screen height (including the status bar and navigation bar)
|
|
433
|
+
const screenHeight = Dimensions.get('screen').height;
|
|
434
|
+
console.log('AutoPositionedPopup screenHeight=', screenHeight);
|
|
435
|
+
if (y + height < screenHeight / 2 - listLayout.height / 2) {
|
|
436
|
+
console.log('AutoPositionedPopup y + height < screenHeight / 2');
|
|
437
|
+
ref_listPos.current = { x: x, y: y + height, width: width };
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
console.log('AutoPositionedPopup y + height >= screenHeight / 2');
|
|
441
|
+
ref_listPos.current = { x: x, y: y - listLayout.height, width: width };
|
|
442
|
+
}
|
|
443
|
+
console.log('AutoPositionedPopup ref_listPos.current=', ref_listPos.current);
|
|
444
|
+
console.log('AutoPositionedPopup addRootView tag=', tag);
|
|
445
|
+
addRootView({
|
|
446
|
+
id: tag,
|
|
447
|
+
style: {
|
|
448
|
+
top: ref_listPos.current.y,
|
|
449
|
+
left: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.left,
|
|
450
|
+
width: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.width,
|
|
451
|
+
height: listLayout.height,
|
|
452
|
+
opacity: 1,
|
|
453
|
+
},
|
|
454
|
+
component: (<PopupList data={data} selectedItem={state.selectedItem} onItemPress={handleItemPress} renderItem={renderItem} keyExtractor={keyExtractor} theme={theme} rootViewsRef={rootViewsRef} fetchData={fetchData} localSearch={localSearch} pageSize={pageSize} onDataUpdate={handleDataUpdate} selectedItemBackgroundColor={selectedItemBackgroundColor}/>),
|
|
455
|
+
useModal: true,
|
|
456
|
+
onModalClose: () => {
|
|
457
|
+
console.log('AutoPositionedPopup onModalClose tag=', tag);
|
|
458
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected, rootViewsRef.current);
|
|
459
|
+
setState((prevState) => {
|
|
460
|
+
return Object.assign(Object.assign({}, prevState), { isFocus: false });
|
|
461
|
+
});
|
|
462
|
+
hasAddedRootView.current = false;
|
|
463
|
+
hasShownRootView.current = false;
|
|
464
|
+
hasTriggeredFocus.current = false;
|
|
465
|
+
setContextSearchQuery('');
|
|
466
|
+
},
|
|
467
|
+
centerDisplay,
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
if (isKeyboardFullyShown) {
|
|
473
|
+
ref_isFocus.current = state.isFocus;
|
|
474
|
+
if (isKeyboardFullyShown !== keyboardVisibleRef.current) {
|
|
475
|
+
keyboardVisibleRef.current = isKeyboardFullyShown;
|
|
476
|
+
// Ensure TextInput has correct focus when keyboard is fully shown
|
|
477
|
+
if (isKeyboardFullyShown && textInputRef.current) {
|
|
478
|
+
// Force ensure TextInput displays correct value
|
|
479
|
+
if (searchQueryRef.current) {
|
|
480
|
+
textInputRef.current.setNativeProps({ text: searchQueryRef.current });
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}, [
|
|
486
|
+
isKeyboardFullyShown,
|
|
487
|
+
state.isFocus,
|
|
488
|
+
useTextInput,
|
|
489
|
+
forceRemoveAllRootViewOnItemSelected,
|
|
490
|
+
tag,
|
|
491
|
+
state.selectedItem,
|
|
492
|
+
popUpViewStyle,
|
|
493
|
+
data,
|
|
494
|
+
handleItemPress,
|
|
495
|
+
renderItem,
|
|
496
|
+
keyExtractor,
|
|
497
|
+
theme,
|
|
498
|
+
rootViewsRef,
|
|
499
|
+
fetchData,
|
|
500
|
+
localSearch,
|
|
501
|
+
pageSize,
|
|
502
|
+
handleDataUpdate,
|
|
503
|
+
selectedItemBackgroundColor,
|
|
504
|
+
removeRootView,
|
|
505
|
+
setContextSearchQuery,
|
|
506
|
+
addRootView,
|
|
507
|
+
centerDisplay,
|
|
508
|
+
setRootViewNativeStyle,
|
|
509
|
+
]);
|
|
510
|
+
// Render the component following project implementation
|
|
511
|
+
return useMemo(() => {
|
|
512
|
+
var _a;
|
|
513
|
+
return (<CustomRow>
|
|
514
|
+
<View style={[styles.contain, style]} ref={refAutoPositionedPopup}>
|
|
515
|
+
{!state.isFocus || !useTextInput ? (<TouchableOpacity style={[styles.AutoPositionedPopupBtn, AutoPositionedPopupBtnStyle]} disabled={AutoPositionedPopupBtnDisabled} onPress={handleButtonPress}>
|
|
516
|
+
{!btwChildren ? (<Text style={[
|
|
517
|
+
styles.searchQueryTxt,
|
|
518
|
+
state.selectedItem && { color: theme.colors.text },
|
|
519
|
+
labelStyle,
|
|
520
|
+
]} numberOfLines={1} ellipsizeMode={'tail'}>
|
|
521
|
+
{((_a = state.selectedItem) === null || _a === void 0 ? void 0 : _a.title) || placeholder}
|
|
522
|
+
</Text>) : (btwChildren())}
|
|
523
|
+
</TouchableOpacity>) : (useTextInput &&
|
|
524
|
+
state.isFocus && (<RNTextInput ref={textInputRef} key="fixed-textinput-key" style={[
|
|
525
|
+
styles.inputStyle,
|
|
526
|
+
{
|
|
527
|
+
textAlignVertical: 'center',
|
|
528
|
+
paddingVertical: 0,
|
|
529
|
+
paddingHorizontal: 0,
|
|
530
|
+
},
|
|
531
|
+
inputStyle,
|
|
532
|
+
]} textAlign={TextInputProps['textAlign'] || 'left'} multiline={TextInputProps['multiline'] || false} numberOfLines={TextInputProps['numberOfLines'] || 1} placeholder={placeholder} placeholderTextColor={theme.colors.placeholderText} defaultValue={searchQueryRef.current} onChangeText={handleSearchChange} onSubmitEditing={(e) => {
|
|
533
|
+
onSubmitEditing === null || onSubmitEditing === void 0 ? void 0 : onSubmitEditing(e);
|
|
534
|
+
Keyboard.dismiss();
|
|
535
|
+
}} returnKeyType="done" {...TextInputProps}/>))}
|
|
536
|
+
</View>
|
|
537
|
+
</CustomRow>);
|
|
538
|
+
}, [state.isFocus, useTextInput, AutoPositionedPopupBtnStyle, AutoPositionedPopupBtnDisabled, handleButtonPress, btwChildren, state.selectedItem, theme.colors.text, labelStyle, placeholder, textInputRef, inputStyle, TextInputProps, searchQueryRef, handleSearchChange, onSubmitEditing, style, refAutoPositionedPopup]);
|
|
305
539
|
}));
|
|
306
540
|
export default AutoPositionedPopup;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-auto-positioned-popup",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "A highly customizable React Native auto-positioned popup component with search functionality and flexible styling options",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"engines": {
|
|
76
76
|
"node": ">=14.0.0"
|
|
77
77
|
},
|
|
78
|
-
"react-native": "
|
|
78
|
+
"react-native": "lib/index.js",
|
|
79
79
|
"dependencies": {
|
|
80
80
|
"react-native-advanced-flatlist": "^1.0.4"
|
|
81
81
|
}
|
|
@@ -18,11 +18,10 @@ import {
|
|
|
18
18
|
TextInput as RNTextInput,
|
|
19
19
|
TouchableOpacity,
|
|
20
20
|
View,
|
|
21
|
-
ViewStyle,
|
|
22
21
|
} from 'react-native';
|
|
23
22
|
import {AdvancedFlatList} from 'react-native-advanced-flatlist';
|
|
24
23
|
import {TextInputSubmitEditingEventData} from 'react-native/Libraries/Components/TextInput/TextInput';
|
|
25
|
-
import {
|
|
24
|
+
import {NativeSyntheticEvent} from 'react-native/Libraries/Types/CoreEventTypes';
|
|
26
25
|
import {AutoPositionedPopupProps, Data, SelectedItem} from './AutoPositionedPopupProps';
|
|
27
26
|
import styles from './AutoPositionedPopup.style';
|
|
28
27
|
import {useRootView} from './RootViewContext';
|
|
@@ -203,18 +202,29 @@ const PopupList: React.FC<PopupListProps> = memo(({
|
|
|
203
202
|
);
|
|
204
203
|
});
|
|
205
204
|
|
|
205
|
+
// State interface for AutoPositionedPopup
|
|
206
|
+
interface StateProps {
|
|
207
|
+
isFocus?: boolean;
|
|
208
|
+
selectedItem?: SelectedItem | any;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// List layout constants
|
|
212
|
+
const listLayout = {
|
|
213
|
+
height: 200,
|
|
214
|
+
};
|
|
215
|
+
|
|
206
216
|
// Main AutoPositionedPopup component
|
|
207
217
|
const AutoPositionedPopup: MemoExoticComponent<
|
|
208
218
|
ForwardRefExoticComponent<AutoPositionedPopupProps>
|
|
209
219
|
> = memo(
|
|
210
220
|
forwardRef<unknown, AutoPositionedPopupProps>(
|
|
211
221
|
(props: AutoPositionedPopupProps, parentRef: ForwardedRef<unknown>): React.JSX.Element => {
|
|
222
|
+
console.log('AutoPositionedPopup props=', props);
|
|
212
223
|
const {
|
|
213
224
|
tag,
|
|
214
225
|
style,
|
|
215
226
|
AutoPositionedPopupBtnStyle,
|
|
216
227
|
placeholder = 'Please Select',
|
|
217
|
-
textAlign = 'right',
|
|
218
228
|
onSubmitEditing,
|
|
219
229
|
TextInputProps = {},
|
|
220
230
|
inputStyle,
|
|
@@ -236,15 +246,81 @@ const AutoPositionedPopup: MemoExoticComponent<
|
|
|
236
246
|
selectedItemBackgroundColor = 'rgba(116, 116, 128, 0.08)',
|
|
237
247
|
} = props;
|
|
238
248
|
|
|
249
|
+
// State management similar to project implementation
|
|
250
|
+
const [state, setState] = useState<StateProps>({
|
|
251
|
+
isFocus: false,
|
|
252
|
+
selectedItem: selectedItem,
|
|
253
|
+
});
|
|
254
|
+
|
|
239
255
|
// Use RootView context
|
|
240
|
-
const {addRootView, removeRootView, rootViews,
|
|
256
|
+
const {addRootView, removeRootView, rootViews, setSearchQuery: setContextSearchQuery, setRootViewNativeStyle} = useRootView();
|
|
241
257
|
const rootViewsRef = useRef(rootViews);
|
|
242
258
|
|
|
259
|
+
// Track TextInput focus and RootView states like project implementation
|
|
260
|
+
const hasTriggeredFocus = useRef(false);
|
|
261
|
+
const hasAddedRootView = useRef(false);
|
|
262
|
+
const hasShownRootView = useRef(false);
|
|
263
|
+
|
|
264
|
+
// Additional refs for keyboard and position tracking
|
|
265
|
+
const ref_isFocus = useRef<boolean>();
|
|
266
|
+
const ref_isKeyboardFullyShown = useRef<boolean>();
|
|
267
|
+
const ref_listPos = useRef<any>();
|
|
268
|
+
const keyboardVisibleRef = useRef(false);
|
|
269
|
+
const refAutoPositionedPopup = useRef<View>(null);
|
|
270
|
+
|
|
271
|
+
// Simple keyboard status tracking (alternative to useKeyboardStatus hook)
|
|
272
|
+
const [isKeyboardFullyShown, setIsKeyboardFullyShown] = useState(false);
|
|
273
|
+
|
|
274
|
+
// Keyboard listeners
|
|
275
|
+
useEffect(() => {
|
|
276
|
+
const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => {
|
|
277
|
+
setIsKeyboardFullyShown(true);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {
|
|
281
|
+
setIsKeyboardFullyShown(false);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
return () => {
|
|
285
|
+
keyboardDidShowListener?.remove();
|
|
286
|
+
keyboardDidHideListener?.remove();
|
|
287
|
+
};
|
|
288
|
+
}, []);
|
|
289
|
+
|
|
243
290
|
useEffect(() => {
|
|
291
|
+
console.log('AutoPositionedPopup rootViews=', rootViews);
|
|
244
292
|
rootViewsRef.current = rootViews;
|
|
293
|
+
if (rootViews.length === 0) {
|
|
294
|
+
hasAddedRootView.current = false;
|
|
295
|
+
hasShownRootView.current = false;
|
|
296
|
+
hasTriggeredFocus.current = false;
|
|
297
|
+
setState((prevState) => {
|
|
298
|
+
return {
|
|
299
|
+
...prevState,
|
|
300
|
+
isFocus: false,
|
|
301
|
+
};
|
|
302
|
+
});
|
|
303
|
+
}
|
|
245
304
|
}, [rootViews]);
|
|
246
305
|
|
|
247
|
-
//
|
|
306
|
+
// Sync selectedItem changes like project implementation
|
|
307
|
+
useEffect(() => {
|
|
308
|
+
console.log('AutoPositionedPopup useEffect tag=', tag);
|
|
309
|
+
console.log('AutoPositionedPopup useEffect selectedItem=', selectedItem);
|
|
310
|
+
console.log('AutoPositionedPopup useEffect state.selectedItem=', state.selectedItem);
|
|
311
|
+
if (state.selectedItem?.id !== selectedItem?.id || state.selectedItem?.title !== selectedItem?.title) {
|
|
312
|
+
console.log('AutoPositionedPopup useEffect selectedItem!=state.selectedItem');
|
|
313
|
+
setState((prevState) => {
|
|
314
|
+
return {
|
|
315
|
+
...prevState,
|
|
316
|
+
selectedItem: selectedItem,
|
|
317
|
+
};
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
}, [selectedItem, state.selectedItem, tag]);
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
// Legacy state for compatibility
|
|
248
324
|
const [isVisible, setIsVisible] = useState(false);
|
|
249
325
|
const [data, setData] = useState<SelectedItem[]>([]);
|
|
250
326
|
const [loading, setLoading] = useState(false);
|
|
@@ -456,20 +532,67 @@ const AutoPositionedPopup: MemoExoticComponent<
|
|
|
456
532
|
}, 100);
|
|
457
533
|
}, [calculatePosition, loadData, popupPosition, useTextInput, placeholder, theme, inputStyle, TextInputProps, data, selectedItem, renderItem, keyExtractor, centerDisplay, addRootView, hidePopup, handleSearchChange, handleItemPress, LIST_HEIGHT, selectedItemBackgroundColor]);
|
|
458
534
|
|
|
459
|
-
// Handle button press
|
|
535
|
+
// Handle button press - following project implementation logic
|
|
460
536
|
const handleButtonPress = useCallback(() => {
|
|
461
537
|
if (AutoPositionedPopupBtnDisabled) return;
|
|
462
538
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
539
|
+
console.log('AutoPositionedPopup onPress tag=', tag);
|
|
540
|
+
console.log('AutoPositionedPopup onPress state.isFocus=', state.isFocus);
|
|
541
|
+
console.log('AutoPositionedPopup onPress useTextInput=', useTextInput);
|
|
542
|
+
console.log(
|
|
543
|
+
'AutoPositionedPopup onPress hasAddedRootView.current=',
|
|
544
|
+
hasAddedRootView.current
|
|
545
|
+
);
|
|
546
|
+
console.log(
|
|
547
|
+
'AutoPositionedPopup onPress hasShownRootView.current=',
|
|
548
|
+
hasShownRootView.current
|
|
549
|
+
);
|
|
550
|
+
console.log(
|
|
551
|
+
'AutoPositionedPopup onPress hasTriggeredFocus.current=',
|
|
552
|
+
hasTriggeredFocus.current
|
|
553
|
+
);
|
|
554
|
+
console.log('AutoPositionedPopup onPress state.selectedItem=', state.selectedItem);
|
|
555
|
+
|
|
556
|
+
setState((prevState) => {
|
|
557
|
+
return {
|
|
558
|
+
...prevState,
|
|
559
|
+
isFocus: true,
|
|
560
|
+
};
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
if (!hasAddedRootView.current && useTextInput) {
|
|
564
|
+
// TextInput version: hide first, show after keyboard fully appears
|
|
565
|
+
hasAddedRootView.current = true;
|
|
566
|
+
hasShownRootView.current = false;
|
|
567
|
+
addRootView({
|
|
568
|
+
id: tag,
|
|
569
|
+
style: {
|
|
570
|
+
top: 0,
|
|
571
|
+
left: 0,
|
|
572
|
+
width: popUpViewStyle?.width,
|
|
573
|
+
height: listLayout.height,
|
|
574
|
+
opacity: 0,
|
|
575
|
+
},
|
|
576
|
+
component: (
|
|
577
|
+
<PopupList
|
|
578
|
+
data={data}
|
|
579
|
+
selectedItem={state.selectedItem}
|
|
580
|
+
onItemPress={handleItemPress}
|
|
581
|
+
renderItem={renderItem}
|
|
582
|
+
keyExtractor={keyExtractor}
|
|
583
|
+
theme={theme}
|
|
584
|
+
rootViewsRef={rootViewsRef}
|
|
585
|
+
fetchData={fetchData}
|
|
586
|
+
localSearch={localSearch}
|
|
587
|
+
pageSize={pageSize}
|
|
588
|
+
onDataUpdate={handleDataUpdate}
|
|
589
|
+
selectedItemBackgroundColor={selectedItemBackgroundColor}
|
|
590
|
+
/>
|
|
591
|
+
),
|
|
592
|
+
useModal: false,
|
|
593
|
+
});
|
|
471
594
|
}
|
|
472
|
-
}, [AutoPositionedPopupBtnDisabled, useTextInput,
|
|
595
|
+
}, [AutoPositionedPopupBtnDisabled, useTextInput, state.isFocus, state.selectedItem, tag, hasAddedRootView, hasShownRootView, hasTriggeredFocus, addRootView, popUpViewStyle, data, handleItemPress, renderItem, keyExtractor, theme, rootViewsRef, fetchData, localSearch, pageSize, handleDataUpdate, selectedItemBackgroundColor]);
|
|
473
596
|
|
|
474
597
|
// Imperative handle for parent component access
|
|
475
598
|
useImperativeHandle(
|
|
@@ -485,7 +608,25 @@ const AutoPositionedPopup: MemoExoticComponent<
|
|
|
485
608
|
[tag, showPopup, hidePopup]
|
|
486
609
|
);
|
|
487
610
|
|
|
488
|
-
//
|
|
611
|
+
// Component lifecycle management like project implementation
|
|
612
|
+
useEffect(() => {
|
|
613
|
+
console.log(`AutoPositionedPopup componentDidMount tag=`, tag);
|
|
614
|
+
|
|
615
|
+
//componentWillUnmount
|
|
616
|
+
return () => {
|
|
617
|
+
console.log(`AutoPositionedPopup componentWillUnmount tag=`, tag);
|
|
618
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected, rootViewsRef.current);
|
|
619
|
+
setContextSearchQuery('');
|
|
620
|
+
if (textInputRef.current) {
|
|
621
|
+
textInputRef.current.blur();
|
|
622
|
+
hasTriggeredFocus.current = false;
|
|
623
|
+
hasAddedRootView.current = false;
|
|
624
|
+
hasShownRootView.current = false;
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
}, [tag, removeRootView, forceRemoveAllRootViewOnItemSelected, setContextSearchQuery]);
|
|
628
|
+
|
|
629
|
+
// Cleanup debounce timer
|
|
489
630
|
useEffect(() => {
|
|
490
631
|
return () => {
|
|
491
632
|
if (debounceTimerRef.current) {
|
|
@@ -494,34 +635,229 @@ const AutoPositionedPopup: MemoExoticComponent<
|
|
|
494
635
|
};
|
|
495
636
|
}, []);
|
|
496
637
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
638
|
+
useEffect(() => {
|
|
639
|
+
console.log('AutoPositionedPopup useEffect tag=', tag);
|
|
640
|
+
console.log('AutoPositionedPopup useEffect state.isFocus=', state.isFocus);
|
|
641
|
+
console.log('AutoPositionedPopup useEffect isKeyboardFullyShown=', isKeyboardFullyShown);
|
|
642
|
+
console.log('AutoPositionedPopup useEffect ref_isFocus.current=', ref_isFocus.current);
|
|
643
|
+
console.log(
|
|
644
|
+
'AutoPositionedPopup useEffect ref_isKeyboardFullyShown.current=',
|
|
645
|
+
ref_isKeyboardFullyShown.current
|
|
646
|
+
);
|
|
647
|
+
console.log('AutoPositionedPopup useEffect useTextInput=', useTextInput);
|
|
648
|
+
console.log('AutoPositionedPopup useEffect TextInputProps=', TextInputProps);
|
|
649
|
+
console.log('AutoPositionedPopup useEffect hasAddedRootView.current=', hasAddedRootView.current);
|
|
650
|
+
console.log('AutoPositionedPopup useEffect hasShownRootView.current=', hasShownRootView.current);
|
|
651
|
+
|
|
652
|
+
if (useTextInput) {
|
|
653
|
+
if (isKeyboardFullyShown && hasAddedRootView.current && !hasShownRootView.current && state.isFocus) {
|
|
654
|
+
refAutoPositionedPopup.current?.measureInWindow((x: number, y: number, width: number, height: number) => {
|
|
655
|
+
console.log('AutoPositionedPopup measureInWindow x=', x, ' y=', y, ' width=', width, ' height=', height);
|
|
656
|
+
// Get the full screen height (including the status bar and navigation bar)
|
|
657
|
+
const screenHeight = Dimensions.get('screen').height;
|
|
658
|
+
console.log('AutoPositionedPopup screenHeight=', screenHeight);
|
|
659
|
+
|
|
660
|
+
if (y + height < screenHeight / 2 - listLayout.height / 2) {
|
|
661
|
+
console.log('AutoPositionedPopup y + height < screenHeight / 2');
|
|
662
|
+
ref_listPos.current = { x: x, y: y + height, width: width };
|
|
663
|
+
} else {
|
|
664
|
+
console.log('AutoPositionedPopup y + height >= screenHeight / 2');
|
|
665
|
+
ref_listPos.current = { x: x, y: y - listLayout.height, width: width };
|
|
666
|
+
}
|
|
667
|
+
console.log('AutoPositionedPopup ref_listPos.current=', ref_listPos.current);
|
|
668
|
+
|
|
669
|
+
setRootViewNativeStyle(tag, {
|
|
670
|
+
top: ref_listPos.current.y,
|
|
671
|
+
left: popUpViewStyle?.left,
|
|
672
|
+
width: popUpViewStyle?.width,
|
|
673
|
+
height: listLayout.height,
|
|
674
|
+
opacity: 1,
|
|
675
|
+
});
|
|
676
|
+
hasShownRootView.current = true;
|
|
677
|
+
});
|
|
678
|
+
} else if (!isKeyboardFullyShown && ref_isFocus.current) {
|
|
679
|
+
console.log(
|
|
680
|
+
'AutoPositionedPopup isKeyboardFullyShown useEffect removeRootView tag=',
|
|
681
|
+
tag,
|
|
682
|
+
' forceRemoveAllRootViewOnItemSelected=',
|
|
683
|
+
forceRemoveAllRootViewOnItemSelected
|
|
684
|
+
);
|
|
685
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected);
|
|
686
|
+
setState((prevState) => {
|
|
687
|
+
return {
|
|
688
|
+
...prevState,
|
|
689
|
+
isFocus: false,
|
|
690
|
+
};
|
|
691
|
+
});
|
|
692
|
+
setContextSearchQuery('');
|
|
693
|
+
hasAddedRootView.current = false;
|
|
694
|
+
hasShownRootView.current = false;
|
|
695
|
+
}
|
|
696
|
+
} else {
|
|
697
|
+
if (state.isFocus) {
|
|
698
|
+
refAutoPositionedPopup.current?.measureInWindow((x: number, y: number, width: number, height: number) => {
|
|
699
|
+
console.log('AutoPositionedPopup measureInWindow x=', x, ' y=', y, ' width=', width, ' height=', height);
|
|
700
|
+
// Get the full screen height (including the status bar and navigation bar)
|
|
701
|
+
const screenHeight = Dimensions.get('screen').height;
|
|
702
|
+
console.log('AutoPositionedPopup screenHeight=', screenHeight);
|
|
703
|
+
|
|
704
|
+
if (y + height < screenHeight / 2 - listLayout.height / 2) {
|
|
705
|
+
console.log('AutoPositionedPopup y + height < screenHeight / 2');
|
|
706
|
+
ref_listPos.current = { x: x, y: y + height, width: width };
|
|
707
|
+
} else {
|
|
708
|
+
console.log('AutoPositionedPopup y + height >= screenHeight / 2');
|
|
709
|
+
ref_listPos.current = { x: x, y: y - listLayout.height, width: width };
|
|
710
|
+
}
|
|
711
|
+
console.log('AutoPositionedPopup ref_listPos.current=', ref_listPos.current);
|
|
712
|
+
|
|
713
|
+
console.log('AutoPositionedPopup addRootView tag=', tag);
|
|
714
|
+
addRootView({
|
|
715
|
+
id: tag,
|
|
716
|
+
style: {
|
|
717
|
+
top: ref_listPos.current.y,
|
|
718
|
+
left: popUpViewStyle?.left,
|
|
719
|
+
width: popUpViewStyle?.width,
|
|
720
|
+
height: listLayout.height,
|
|
721
|
+
opacity: 1,
|
|
722
|
+
},
|
|
723
|
+
component: (
|
|
724
|
+
<PopupList
|
|
725
|
+
data={data}
|
|
726
|
+
selectedItem={state.selectedItem}
|
|
727
|
+
onItemPress={handleItemPress}
|
|
728
|
+
renderItem={renderItem}
|
|
729
|
+
keyExtractor={keyExtractor}
|
|
730
|
+
theme={theme}
|
|
731
|
+
rootViewsRef={rootViewsRef}
|
|
732
|
+
fetchData={fetchData}
|
|
733
|
+
localSearch={localSearch}
|
|
734
|
+
pageSize={pageSize}
|
|
735
|
+
onDataUpdate={handleDataUpdate}
|
|
736
|
+
selectedItemBackgroundColor={selectedItemBackgroundColor}
|
|
737
|
+
/>
|
|
738
|
+
),
|
|
739
|
+
useModal: true,
|
|
740
|
+
onModalClose: () => {
|
|
741
|
+
console.log('AutoPositionedPopup onModalClose tag=', tag);
|
|
742
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected, rootViewsRef.current);
|
|
743
|
+
setState((prevState) => {
|
|
744
|
+
return {
|
|
745
|
+
...prevState,
|
|
746
|
+
isFocus: false,
|
|
747
|
+
};
|
|
748
|
+
});
|
|
749
|
+
hasAddedRootView.current = false;
|
|
750
|
+
hasShownRootView.current = false;
|
|
751
|
+
hasTriggeredFocus.current = false;
|
|
752
|
+
setContextSearchQuery('');
|
|
753
|
+
},
|
|
754
|
+
centerDisplay,
|
|
755
|
+
});
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
if (isKeyboardFullyShown) {
|
|
761
|
+
ref_isFocus.current = state.isFocus;
|
|
762
|
+
if (isKeyboardFullyShown !== keyboardVisibleRef.current) {
|
|
763
|
+
keyboardVisibleRef.current = isKeyboardFullyShown;
|
|
764
|
+
// Ensure TextInput has correct focus when keyboard is fully shown
|
|
765
|
+
if (isKeyboardFullyShown && textInputRef.current) {
|
|
766
|
+
// Force ensure TextInput displays correct value
|
|
767
|
+
if (searchQueryRef.current) {
|
|
768
|
+
textInputRef.current.setNativeProps({ text: searchQueryRef.current });
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}, [
|
|
774
|
+
isKeyboardFullyShown,
|
|
775
|
+
state.isFocus,
|
|
776
|
+
useTextInput,
|
|
777
|
+
forceRemoveAllRootViewOnItemSelected,
|
|
778
|
+
tag,
|
|
779
|
+
state.selectedItem,
|
|
780
|
+
popUpViewStyle,
|
|
781
|
+
data,
|
|
782
|
+
handleItemPress,
|
|
783
|
+
renderItem,
|
|
784
|
+
keyExtractor,
|
|
785
|
+
theme,
|
|
786
|
+
rootViewsRef,
|
|
787
|
+
fetchData,
|
|
788
|
+
localSearch,
|
|
789
|
+
pageSize,
|
|
790
|
+
handleDataUpdate,
|
|
791
|
+
selectedItemBackgroundColor,
|
|
792
|
+
removeRootView,
|
|
793
|
+
setContextSearchQuery,
|
|
794
|
+
addRootView,
|
|
795
|
+
centerDisplay,
|
|
796
|
+
setRootViewNativeStyle,
|
|
797
|
+
]);
|
|
798
|
+
|
|
799
|
+
// Render the component following project implementation
|
|
800
|
+
return useMemo(() => {
|
|
801
|
+
return (
|
|
802
|
+
<CustomRow>
|
|
803
|
+
<View style={[styles.contain, style]} ref={refAutoPositionedPopup}>
|
|
804
|
+
{!state.isFocus || !useTextInput ? (
|
|
805
|
+
<TouchableOpacity
|
|
806
|
+
style={[styles.AutoPositionedPopupBtn, AutoPositionedPopupBtnStyle]}
|
|
807
|
+
disabled={AutoPositionedPopupBtnDisabled}
|
|
808
|
+
onPress={handleButtonPress}
|
|
517
809
|
>
|
|
518
|
-
{
|
|
519
|
-
|
|
810
|
+
{!btwChildren ? (
|
|
811
|
+
<Text
|
|
812
|
+
style={[
|
|
813
|
+
styles.searchQueryTxt,
|
|
814
|
+
state.selectedItem && { color: theme.colors.text },
|
|
815
|
+
labelStyle,
|
|
816
|
+
]}
|
|
817
|
+
numberOfLines={1}
|
|
818
|
+
ellipsizeMode={'tail'}
|
|
819
|
+
>
|
|
820
|
+
{state.selectedItem?.title || placeholder}
|
|
821
|
+
</Text>
|
|
822
|
+
) : (
|
|
823
|
+
btwChildren()
|
|
824
|
+
)}
|
|
825
|
+
</TouchableOpacity>
|
|
826
|
+
) : (
|
|
827
|
+
useTextInput &&
|
|
828
|
+
state.isFocus && (
|
|
829
|
+
<RNTextInput
|
|
830
|
+
ref={textInputRef}
|
|
831
|
+
key="fixed-textinput-key"
|
|
832
|
+
style={[
|
|
833
|
+
styles.inputStyle,
|
|
834
|
+
{
|
|
835
|
+
textAlignVertical: 'center',
|
|
836
|
+
paddingVertical: 0,
|
|
837
|
+
paddingHorizontal: 0,
|
|
838
|
+
},
|
|
839
|
+
inputStyle,
|
|
840
|
+
]}
|
|
841
|
+
textAlign={TextInputProps['textAlign'] || 'left'}
|
|
842
|
+
multiline={TextInputProps['multiline'] || false}
|
|
843
|
+
numberOfLines={TextInputProps['numberOfLines'] || 1}
|
|
844
|
+
placeholder={placeholder}
|
|
845
|
+
placeholderTextColor={theme.colors.placeholderText}
|
|
846
|
+
defaultValue={searchQueryRef.current}
|
|
847
|
+
onChangeText={handleSearchChange}
|
|
848
|
+
onSubmitEditing={(e: NativeSyntheticEvent<TextInputSubmitEditingEventData>) => {
|
|
849
|
+
onSubmitEditing?.(e);
|
|
850
|
+
Keyboard.dismiss();
|
|
851
|
+
}}
|
|
852
|
+
returnKeyType="done"
|
|
853
|
+
{...TextInputProps}
|
|
854
|
+
/>
|
|
855
|
+
)
|
|
520
856
|
)}
|
|
521
|
-
</
|
|
522
|
-
</
|
|
523
|
-
|
|
524
|
-
);
|
|
857
|
+
</View>
|
|
858
|
+
</CustomRow>
|
|
859
|
+
);
|
|
860
|
+
}, [state.isFocus, useTextInput, AutoPositionedPopupBtnStyle, AutoPositionedPopupBtnDisabled, handleButtonPress, btwChildren, state.selectedItem, theme.colors.text, labelStyle, placeholder, textInputRef, inputStyle, TextInputProps, searchQueryRef, handleSearchChange, onSubmitEditing, style, refAutoPositionedPopup]);
|
|
525
861
|
}
|
|
526
862
|
)
|
|
527
863
|
);
|