react-native-auto-positioned-popup 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.
- package/lib/AutoPositionedPopup.d.ts.map +1 -1
- package/lib/AutoPositionedPopup.js +523 -244
- package/lib/AutoPositionedPopup.js.map +1 -0
- package/lib/AutoPositionedPopup.style.d.ts +29 -0
- package/lib/AutoPositionedPopup.style.d.ts.map +1 -1
- package/lib/AutoPositionedPopup.style.js +20 -2
- package/lib/AutoPositionedPopup.style.js.map +1 -0
- package/lib/AutoPositionedPopupProps.js +1 -0
- package/lib/AutoPositionedPopupProps.js.map +1 -0
- package/lib/KeyboardManager.d.ts +2 -0
- package/lib/KeyboardManager.d.ts.map +1 -0
- package/lib/KeyboardManager.js +57 -0
- package/lib/KeyboardManager.js.map +1 -0
- package/lib/RootViewContext.d.ts.map +1 -1
- package/lib/RootViewContext.js +1 -1
- package/lib/RootViewContext.js.map +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -0
- package/package.json +6 -5
- package/src/AutoPositionedPopup.style.ts +24 -3
- package/src/AutoPositionedPopup.tsx +747 -383
- package/src/KeyboardManager.tsx +82 -0
- package/src/RootViewContext.tsx +0 -1
- package/src/types/react-native-advanced-flatlist.d.ts +19 -0
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import React, { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
|
|
2
2
|
import { Dimensions, Keyboard, Text, TextInput as RNTextInput, TouchableOpacity, View, } from 'react-native';
|
|
3
|
-
|
|
3
|
+
// @ts-ignore - Skip type checking for third-party library with type issues
|
|
4
|
+
import { AdvancedFlatList as AdvancedFlatListLib } from 'react-native-advanced-flatlist';
|
|
5
|
+
// @ts-ignore - Direct import from source when using fake data
|
|
6
|
+
import AdvancedFlatListSource from 'react-native-advanced-flatlist/src/AdvancedFlatList.tsx';
|
|
4
7
|
import styles from './AutoPositionedPopup.style';
|
|
5
8
|
import { useRootView } from './RootViewContext';
|
|
9
|
+
import { useKeyboardStatus } from './KeyboardManager';
|
|
10
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
6
11
|
const queryChangeListeners = [];
|
|
7
12
|
const emitQueryChange = (query) => {
|
|
8
13
|
console.log('AutoPositionedPopup.tsx emitQueryChange query=', query, ' listeners=', queryChangeListeners.length);
|
|
@@ -26,281 +31,555 @@ const defaultTheme = {
|
|
|
26
31
|
},
|
|
27
32
|
};
|
|
28
33
|
// List item component for rendering individual items
|
|
29
|
-
const ListItem = memo(({ item, index, selectedItem,
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
34
|
+
const ListItem = memo(({ updateState, item, index, selectedItem, }) => {
|
|
35
|
+
const { addRootView, setRootViewNativeStyle, removeRootView, rootViews } = useRootView();
|
|
36
|
+
const rootViewsRef = useRef(rootViews);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
rootViewsRef.current = rootViews;
|
|
39
|
+
}, [rootViews]);
|
|
40
|
+
return useMemo(() => {
|
|
41
|
+
// console.log('AutoPositionedPopup.tsx ListItem index=', index);
|
|
42
|
+
// console.log('AutoPositionedPopup.tsx ListItem item=', item);
|
|
43
|
+
const isSelected = item.id === (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id);
|
|
44
|
+
return (<TouchableOpacity key={item.id} style={[
|
|
45
|
+
styles.commonModalRow,
|
|
46
|
+
{ backgroundColor: isSelected ? 'rgba(116, 116, 128, 0.08)' : 'transparent' },
|
|
47
|
+
]} onPress={() => {
|
|
48
|
+
// console.log('AutoPositionedPopup.tsx ListItem onPress item=', item); // Commented to prevent spam
|
|
49
|
+
// console.log('AutoPositionedPopup.tsx ListItem onPress rootViews=', rootViewsRef.current); // Commented to prevent spam
|
|
50
|
+
updateState('selectedItem', item);
|
|
51
|
+
}}>
|
|
52
|
+
<Text style={styles.ListItemCode} numberOfLines={1} ellipsizeMode="tail">
|
|
53
|
+
{item.title}
|
|
54
|
+
</Text>
|
|
55
|
+
</TouchableOpacity>);
|
|
56
|
+
}, [updateState, item, index, selectedItem, rootViewsRef]);
|
|
48
57
|
});
|
|
49
|
-
const
|
|
50
|
-
const [
|
|
51
|
-
|
|
52
|
-
|
|
58
|
+
const AutoPositionedPopupList = memo(({ tag, updateState, fetchData, keyExtractor = (item) => String(item.id), renderItem, selectedItem, localSearch, pageSize, }) => {
|
|
59
|
+
const [state, setState] = useState({
|
|
60
|
+
selectedItem: selectedItem,
|
|
61
|
+
localData: [],
|
|
62
|
+
});
|
|
63
|
+
// Define an interface that matches the methods we need from CsxFlatList
|
|
64
|
+
const ref_list = useRef(null);
|
|
65
|
+
const ref_searchQuery = useRef('');
|
|
66
|
+
const { searchQuery, setSearchQuery, rootViews } = useRootView();
|
|
67
|
+
const rootViewsRef = useRef(rootViews);
|
|
53
68
|
useEffect(() => {
|
|
54
|
-
|
|
55
|
-
}, [
|
|
56
|
-
|
|
69
|
+
rootViewsRef.current = rootViews;
|
|
70
|
+
}, [rootViews]);
|
|
71
|
+
/**
|
|
72
|
+
* componentDidMount && componentWillUnmount
|
|
73
|
+
*/
|
|
57
74
|
useEffect(() => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
(async () => {
|
|
76
|
+
})();
|
|
77
|
+
console.log(`AutoPositionedPopupList componentDidMount`);
|
|
78
|
+
//componentWillUnmount
|
|
79
|
+
return () => {
|
|
80
|
+
console.log(`AutoPositionedPopupList componentWillUnmount`);
|
|
81
|
+
setSearchQuery('');
|
|
82
|
+
};
|
|
83
|
+
}, []);
|
|
84
|
+
// useEffect(() => {
|
|
85
|
+
// // 監聽 TextInput 事件,收到就刷新列表,不依賴 global searchQuery
|
|
86
|
+
// // 將最新的 searchQuery 同步到 list 專用的 ref,供 _fetchData 使用
|
|
87
|
+
// ref_searchQuery.current = searchQuery;
|
|
88
|
+
// console.log('AutoPositionedPopupList useEffect searchQuery=', searchQuery);
|
|
89
|
+
// console.log('AutoPositionedPopupList useEffect state.localData=', state.localData);
|
|
90
|
+
// console.log('AutoPositionedPopupList useEffect ref_list.current=', ref_list.current);
|
|
91
|
+
// console.log('AutoPositionedPopupList useEffect localSearch=', localSearch);
|
|
92
|
+
// if (ref_list.current && (localSearch && state.localData.length > 0 || !localSearch)) {
|
|
93
|
+
// ref_list.current.scrollToTop();
|
|
94
|
+
// ref_list.current.refresh();
|
|
95
|
+
// }
|
|
96
|
+
// }, [searchQuery, state.localData, localSearch]);
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
const unsubscribe = subscribeQueryChange((newQuery) => {
|
|
99
|
+
console.log('AutoPositionedPopupList useEffect subscribeQueryChange newQuery=', newQuery);
|
|
100
|
+
ref_searchQuery.current = newQuery;
|
|
101
|
+
if (ref_list.current) {
|
|
102
|
+
ref_list.current.scrollToTop();
|
|
103
|
+
ref_list.current.refresh();
|
|
82
104
|
}
|
|
83
105
|
});
|
|
84
106
|
return unsubscribe;
|
|
85
|
-
}, [
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
107
|
+
}, []);
|
|
108
|
+
const _updateState = (key, value) => {
|
|
109
|
+
console.log('AutoPositionedPopupList _updateState key=', key, ' value=', value);
|
|
110
|
+
setState((prevState) => (Object.assign(Object.assign({}, prevState), { [key]: value })));
|
|
111
|
+
console.log('AutoPositionedPopupList _updateState rootViews=', rootViewsRef.current);
|
|
112
|
+
updateState(key, value);
|
|
113
|
+
};
|
|
114
|
+
const _fetchData = async ({ pageIndex, pageSize: currentPageSize, }) => {
|
|
115
|
+
console.log('AutoPositionedPopupList _fetchData pageIndex=', pageIndex, ' pageSize=', currentPageSize);
|
|
116
|
+
console.log('AutoPositionedPopupList _fetchData state.localData=', state.localData);
|
|
117
|
+
console.log('AutoPositionedPopupList _fetchData ref_searchQuery.current=', ref_searchQuery.current);
|
|
118
|
+
console.log('AutoPositionedPopupList _fetchData localSearch=', localSearch);
|
|
119
|
+
if (localSearch && state.localData.length > 0) {
|
|
120
|
+
const result = state.localData.filter((item) => {
|
|
121
|
+
var _a;
|
|
122
|
+
return (_a = item.title) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(ref_searchQuery.current.toLowerCase());
|
|
123
|
+
});
|
|
124
|
+
console.log('AutoPositionedPopupList _fetchData localSearch result=', result);
|
|
125
|
+
return Promise.resolve({
|
|
126
|
+
items: result,
|
|
127
|
+
pageIndex: 0,
|
|
128
|
+
needLoadMore: false,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
try {
|
|
132
|
+
const res = await fetchData({
|
|
133
|
+
pageIndex,
|
|
134
|
+
pageSize: pageSize || 10,
|
|
135
|
+
searchQuery: ref_searchQuery.current,
|
|
136
|
+
});
|
|
137
|
+
console.log('AutoPositionedPopupList _fetchData res=', res);
|
|
138
|
+
if ((res === null || res === void 0 ? void 0 : res.items) && localSearch) {
|
|
139
|
+
setState((prevState) => {
|
|
140
|
+
return Object.assign(Object.assign({}, prevState), { localData: res.items });
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return Promise.resolve(res);
|
|
144
|
+
}
|
|
145
|
+
catch (e) {
|
|
146
|
+
console.warn('Error in fetchData:', e);
|
|
147
|
+
}
|
|
148
|
+
console.log('AutoPositionedPopupList _fetchData res=', null);
|
|
149
|
+
return null;
|
|
150
|
+
};
|
|
151
|
+
const _renderItem = useCallback(({ item, index }) => {
|
|
152
|
+
return <ListItem item={item} index={index} updateState={_updateState} selectedItem={state.selectedItem}/>;
|
|
153
|
+
}, [state.selectedItem]);
|
|
154
|
+
return useMemo(() => {
|
|
155
|
+
console.log('AutoPositionedPopupList (global as any)?.$fake=', global === null || global === void 0 ? void 0 : global.$fake);
|
|
156
|
+
// Choose AdvancedFlatList version based on global.$fake
|
|
157
|
+
const AdvancedFlatListComponent = (global === null || global === void 0 ? void 0 : global.$fake) ? AdvancedFlatListSource : AdvancedFlatListLib;
|
|
158
|
+
return (<View style={[styles.baseModalView, styles.autoPositionedPopupList]}>
|
|
159
|
+
{/* @ts-ignore - Type assertion to bypass third-party library type issues */}
|
|
160
|
+
<AdvancedFlatListComponent style={[{ borderRadius: 0 }]} {...(ref_list && { ref: ref_list })} keyExtractor={keyExtractor} keyboardShouldPersistTaps={'always'} {...({ fetchData: _fetchData })} renderItem={renderItem || _renderItem}/>
|
|
161
|
+
</View>);
|
|
162
|
+
}, [tag,
|
|
163
|
+
updateState,
|
|
164
|
+
fetchData,
|
|
165
|
+
keyExtractor,
|
|
166
|
+
renderItem,
|
|
167
|
+
state.selectedItem,
|
|
168
|
+
state.localData,
|
|
169
|
+
searchQuery,
|
|
170
|
+
localSearch,
|
|
171
|
+
pageSize,
|
|
172
|
+
rootViewsRef,
|
|
173
|
+
]);
|
|
90
174
|
});
|
|
175
|
+
// List layout constants
|
|
176
|
+
const listLayout = {
|
|
177
|
+
height: 200,
|
|
178
|
+
};
|
|
91
179
|
// Main AutoPositionedPopup component
|
|
92
180
|
const AutoPositionedPopup = memo(forwardRef((props, parentRef) => {
|
|
93
|
-
|
|
181
|
+
console.log('AutoPositionedPopup props=', props);
|
|
182
|
+
const { tag, style, AutoPositionedPopupBtnStyle, placeholder = 'Please Select', onSubmitEditing, TextInputProps = {}, inputStyle, labelStyle, popUpViewStyle = { left: '5%', width: '90%' }, fetchData = async ({ pageIndex, pageSize, searchQuery, }) => {
|
|
183
|
+
const res = {
|
|
184
|
+
items: [],
|
|
185
|
+
pageIndex,
|
|
186
|
+
needLoadMore: false,
|
|
187
|
+
};
|
|
188
|
+
try {
|
|
189
|
+
// const res1: any[] = await $api.xxx(pageSize)
|
|
190
|
+
// console.log('${NAME} xxx res=', res)
|
|
191
|
+
// res.items = res1
|
|
192
|
+
// res.needLoadMore = res1.length === pageSize
|
|
193
|
+
}
|
|
194
|
+
catch (e) {
|
|
195
|
+
console.warn('Error in fetch operation:', e);
|
|
196
|
+
}
|
|
197
|
+
return res;
|
|
198
|
+
}, renderItem, onItemSelected, localSearch = false, pageSize = 20, selectedItem, useTextInput = false, btwChildren, CustomRow = ({ children }) => <View>{children}</View>, keyExtractor = (item) => String((item === null || item === void 0 ? void 0 : item.id) || ''), AutoPositionedPopupBtnDisabled = false, forceRemoveAllRootViewOnItemSelected = false, centerDisplay = false, selectedItemBackgroundColor = 'rgba(116, 116, 128, 0.08)', textAlign = 'right', CustomPopView = undefined, CustomPopViewStyle } = props;
|
|
199
|
+
// State management similar to project implementation
|
|
200
|
+
const [state, setState] = useState({
|
|
201
|
+
isFocus: false,
|
|
202
|
+
selectedItem: selectedItem,
|
|
203
|
+
});
|
|
94
204
|
// Use RootView context
|
|
95
|
-
const { addRootView, removeRootView, rootViews,
|
|
205
|
+
const { addRootView, setRootViewNativeStyle, removeRootView, rootViews, setSearchQuery } = useRootView();
|
|
206
|
+
const insets = useSafeAreaInsets();
|
|
96
207
|
const rootViewsRef = useRef(rootViews);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
208
|
+
// Track TextInput focus and RootView states like project implementation
|
|
209
|
+
const hasTriggeredFocus = useRef(false);
|
|
210
|
+
const hasAddedRootView = useRef(false);
|
|
211
|
+
const hasShownRootView = useRef(false);
|
|
212
|
+
// Additional refs for keyboard and position tracking
|
|
213
|
+
const ref_isFocus = useRef();
|
|
214
|
+
const ref_isKeyboardFullyShown = useRef();
|
|
215
|
+
const ref_listPos = useRef();
|
|
216
|
+
const keyboardVisibleRef = useRef(false);
|
|
217
|
+
const refAutoPositionedPopup = useRef(null);
|
|
218
|
+
const ref_searchQuery = useRef('');
|
|
219
|
+
// Simple keyboard status tracking (alternative to useKeyboardStatus hook)
|
|
220
|
+
// Legacy state for compatibility
|
|
101
221
|
const [isVisible, setIsVisible] = useState(false);
|
|
102
222
|
const [data, setData] = useState([]);
|
|
103
223
|
const [loading, setLoading] = useState(false);
|
|
104
224
|
const [popupPosition, setPopupPosition] = useState({ top: 0, left: 0, width: 0 });
|
|
105
|
-
const popupId = useRef(`popup-${tag}-${Date.now()}`);
|
|
106
225
|
// Refs for performance optimization
|
|
107
226
|
const containerRef = useRef(null);
|
|
108
227
|
const textInputRef = useRef(null);
|
|
109
228
|
const debounceTimerRef = useRef(null);
|
|
110
229
|
const searchQueryRef = useRef(''); // Use ref instead of state to avoid re-renders
|
|
111
|
-
//
|
|
112
|
-
const
|
|
230
|
+
// Refs to store latest values for useEffect without adding to dependency array
|
|
231
|
+
const dataRef = useRef(data);
|
|
232
|
+
const isKeyboardFullyShown = useKeyboardStatus();
|
|
113
233
|
const theme = defaultTheme;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
234
|
+
/**
|
|
235
|
+
* componentDidMount && componentWillUnmount
|
|
236
|
+
*/
|
|
237
|
+
useEffect(() => {
|
|
238
|
+
(async () => {
|
|
239
|
+
})();
|
|
240
|
+
console.log(`AutoPositionedPopup componentDidMount tag=`, tag);
|
|
241
|
+
console.log('AutoPositionedPopup componentDidMount CustomPopView=', CustomPopView);
|
|
242
|
+
//componentWillUnmount
|
|
243
|
+
return () => {
|
|
244
|
+
console.log(`AutoPositionedPopup componentWillUnmount tag=`, tag);
|
|
245
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected, rootViewsRef.current);
|
|
246
|
+
setSearchQuery('');
|
|
247
|
+
if (textInputRef.current) {
|
|
248
|
+
textInputRef.current.blur();
|
|
249
|
+
hasTriggeredFocus.current = false;
|
|
250
|
+
hasAddedRootView.current = false;
|
|
251
|
+
hasShownRootView.current = false;
|
|
252
|
+
ref_isFocus.current = false;
|
|
127
253
|
}
|
|
128
|
-
}
|
|
129
|
-
catch (error) {
|
|
130
|
-
console.error('Error loading data:', error);
|
|
131
|
-
}
|
|
132
|
-
finally {
|
|
133
|
-
setLoading(false);
|
|
134
|
-
}
|
|
135
|
-
}, [fetchData, pageSize]);
|
|
136
|
-
// Handle search query change with debounce and event emission
|
|
137
|
-
const handleSearchChange = useCallback((query) => {
|
|
138
|
-
// Store in ref to avoid re-renders
|
|
139
|
-
searchQueryRef.current = query;
|
|
140
|
-
// Update TextInput value directly if needed
|
|
141
|
-
if (textInputRef.current) {
|
|
142
|
-
// The TextInput's value will be controlled by its own state
|
|
143
|
-
}
|
|
144
|
-
// Clear previous debounce timer
|
|
145
|
-
if (debounceTimerRef.current) {
|
|
146
|
-
clearTimeout(debounceTimerRef.current);
|
|
147
|
-
}
|
|
148
|
-
// Use debounce for performance optimization
|
|
149
|
-
debounceTimerRef.current = setTimeout(() => {
|
|
150
|
-
// Emit query change event to decouple components and avoid context re-rendering
|
|
151
|
-
emitQueryChange(searchQueryRef.current);
|
|
152
|
-
}, 300); // Use 300ms debounce like the original
|
|
254
|
+
};
|
|
153
255
|
}, []);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
top = y - LIST_HEIGHT;
|
|
167
|
-
}
|
|
168
|
-
// Adjust horizontal position if needed
|
|
169
|
-
if ((popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.left) && (popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.width)) {
|
|
170
|
-
const leftPercent = parseFloat(String(popUpViewStyle.left).replace('%', '')) / 100;
|
|
171
|
-
const widthPercent = parseFloat(String(popUpViewStyle.width).replace('%', '')) / 100;
|
|
172
|
-
left = screenWidth * leftPercent;
|
|
173
|
-
popupWidth = screenWidth * widthPercent;
|
|
174
|
-
}
|
|
175
|
-
setPopupPosition({ top, left, width: popupWidth });
|
|
176
|
-
});
|
|
177
|
-
}, [popUpViewStyle]);
|
|
178
|
-
// Hide popup using RootView
|
|
179
|
-
const hidePopup = useCallback(() => {
|
|
180
|
-
var _a, _b;
|
|
181
|
-
setIsVisible(false);
|
|
182
|
-
// Reset search query
|
|
183
|
-
searchQueryRef.current = '';
|
|
184
|
-
if (textInputRef.current) {
|
|
185
|
-
textInputRef.current.blur();
|
|
186
|
-
(_b = (_a = textInputRef.current).clear) === null || _b === void 0 ? void 0 : _b.call(_a); // Clear the TextInput
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
console.log('AutoPositionedPopup rootViews=', rootViews);
|
|
258
|
+
rootViewsRef.current = rootViews;
|
|
259
|
+
if (rootViews.length === 0) {
|
|
260
|
+
hasAddedRootView.current = false;
|
|
261
|
+
hasShownRootView.current = false;
|
|
262
|
+
ref_isFocus.current = false;
|
|
263
|
+
ref_isKeyboardFullyShown.current = false;
|
|
264
|
+
hasTriggeredFocus.current = false;
|
|
265
|
+
setState((prevState) => {
|
|
266
|
+
return Object.assign(Object.assign({}, prevState), { isFocus: false });
|
|
267
|
+
});
|
|
187
268
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}, [onItemSelected, hidePopup]);
|
|
199
|
-
// Show popup using RootView
|
|
200
|
-
const showPopup = useCallback(() => {
|
|
201
|
-
calculatePosition();
|
|
202
|
-
setIsVisible(true);
|
|
203
|
-
loadData(searchQueryRef.current);
|
|
204
|
-
// Wait for position to be calculated
|
|
205
|
-
setTimeout(() => {
|
|
206
|
-
const popupComponent = (<TouchableOpacity style={{
|
|
207
|
-
flex: 1,
|
|
208
|
-
backgroundColor: 'rgba(0, 0, 0, 0.3)',
|
|
209
|
-
}} activeOpacity={1} onPress={hidePopup}>
|
|
210
|
-
<View style={{
|
|
211
|
-
position: 'absolute',
|
|
212
|
-
top: popupPosition.top,
|
|
213
|
-
left: popupPosition.left,
|
|
214
|
-
width: popupPosition.width,
|
|
215
|
-
height: LIST_HEIGHT,
|
|
216
|
-
backgroundColor: theme.colors.background,
|
|
217
|
-
borderRadius: 8,
|
|
218
|
-
shadowColor: '#000',
|
|
219
|
-
shadowOffset: { width: 0, height: 2 },
|
|
220
|
-
shadowOpacity: 0.25,
|
|
221
|
-
shadowRadius: 3.84,
|
|
222
|
-
elevation: 5,
|
|
223
|
-
}}>
|
|
224
|
-
{useTextInput && (<RNTextInput ref={textInputRef} style={[
|
|
225
|
-
styles.inputStyle,
|
|
226
|
-
{
|
|
227
|
-
height: 40,
|
|
228
|
-
borderBottomWidth: 1,
|
|
229
|
-
borderBottomColor: theme.colors.border,
|
|
230
|
-
paddingHorizontal: 12,
|
|
231
|
-
color: theme.colors.text,
|
|
232
|
-
},
|
|
233
|
-
inputStyle,
|
|
234
|
-
]} placeholder={placeholder} placeholderTextColor={theme.colors.placeholderText} defaultValue={searchQueryRef.current} onChangeText={handleSearchChange} onSubmitEditing={(e) => {
|
|
235
|
-
onSubmitEditing === null || onSubmitEditing === void 0 ? void 0 : onSubmitEditing(e);
|
|
236
|
-
Keyboard.dismiss();
|
|
237
|
-
}} returnKeyType="done" {...TextInputProps}/>)}
|
|
238
|
-
|
|
239
|
-
<PopupList data={data} selectedItem={selectedItem} onItemPress={handleItemPress} renderItem={renderItem} keyExtractor={keyExtractor} theme={theme} rootViewsRef={rootViewsRef} fetchData={fetchData} localSearch={localSearch} pageSize={pageSize} onDataUpdate={handleDataUpdate} selectedItemBackgroundColor={selectedItemBackgroundColor}/>
|
|
240
|
-
</View>
|
|
241
|
-
</TouchableOpacity>);
|
|
242
|
-
addRootView({
|
|
243
|
-
id: popupId.current,
|
|
244
|
-
style: {
|
|
245
|
-
position: 'absolute',
|
|
246
|
-
top: 0,
|
|
247
|
-
left: 0,
|
|
248
|
-
right: 0,
|
|
249
|
-
bottom: 0,
|
|
250
|
-
},
|
|
251
|
-
component: popupComponent,
|
|
252
|
-
useModal: true,
|
|
253
|
-
onModalClose: hidePopup,
|
|
254
|
-
centerDisplay: centerDisplay,
|
|
269
|
+
}, [rootViews]);
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
var _a, _b;
|
|
272
|
+
console.log('AutoPositionedPopup useEffect tag=', tag);
|
|
273
|
+
console.log('AutoPositionedPopup useEffect selectedItem=', selectedItem);
|
|
274
|
+
console.log('AutoPositionedPopup useEffect state.selectedItem=', state.selectedItem);
|
|
275
|
+
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)) {
|
|
276
|
+
console.log('AutoPositionedPopup useEffect selectedItem!=state.selectedItem');
|
|
277
|
+
setState((prevState) => {
|
|
278
|
+
return Object.assign(Object.assign({}, prevState), { selectedItem: selectedItem });
|
|
255
279
|
});
|
|
256
|
-
}
|
|
257
|
-
}, [
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
280
|
+
}
|
|
281
|
+
}, [selectedItem, state.selectedItem, tag]);
|
|
282
|
+
useEffect(() => {
|
|
283
|
+
var _a, _b;
|
|
284
|
+
console.log('AutoPositionedPopup useEffect tag=', tag);
|
|
285
|
+
console.log('AutoPositionedPopup useEffect state.isFocus=', state.isFocus);
|
|
286
|
+
console.log('AutoPositionedPopup useEffect isKeyboardFullyShown=', isKeyboardFullyShown);
|
|
287
|
+
console.log('AutoPositionedPopup useEffect ref_isFocus.current=', ref_isFocus.current);
|
|
288
|
+
console.log('AutoPositionedPopup useEffect ref_isKeyboardFullyShown.current=', ref_isKeyboardFullyShown.current);
|
|
289
|
+
console.log('AutoPositionedPopup useEffect useTextInput=', useTextInput);
|
|
290
|
+
console.log('AutoPositionedPopup useEffect TextInputProps=', TextInputProps);
|
|
291
|
+
console.log('AutoPositionedPopup useEffect hasAddedRootView.current=', hasAddedRootView.current);
|
|
292
|
+
console.log('AutoPositionedPopup useEffect hasShownRootView.current=', hasShownRootView.current);
|
|
262
293
|
if (useTextInput) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
294
|
+
if (isKeyboardFullyShown && hasAddedRootView.current && !hasShownRootView.current && state.isFocus) {
|
|
295
|
+
(_a = refAutoPositionedPopup.current) === null || _a === void 0 ? void 0 : _a.measureInWindow((x, y, width, height) => {
|
|
296
|
+
var _a;
|
|
297
|
+
console.log('AutoPositionedPopup measureInWindow x=', x, ' y=', y, ' width=', width, ' height=', height);
|
|
298
|
+
// SIMPLE CENTER-BASED POSITIONING STRATEGY
|
|
299
|
+
const screenHeight = Dimensions.get('screen').height;
|
|
300
|
+
const screenCenter = screenHeight / 2;
|
|
301
|
+
console.log('AutoPositionedPopup screenHeight=', screenHeight, ' screenCenter=', screenCenter, ' componentY=', y);
|
|
302
|
+
// Simple rule: if component Y > screen center, show popup above; otherwise show below
|
|
303
|
+
if (y > screenCenter) {
|
|
304
|
+
console.log('AutoPositionedPopup with keyboard: showing above (Y > center)');
|
|
305
|
+
ref_listPos.current = { x: x, y: y - listLayout.height, width: width };
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
console.log('AutoPositionedPopup with keyboard: showing below (Y <= center)');
|
|
309
|
+
ref_listPos.current = { x: x, y: y + height, width: width };
|
|
310
|
+
}
|
|
311
|
+
console.log('AutoPositionedPopup ref_listPos.current=', ref_listPos.current);
|
|
312
|
+
setRootViewNativeStyle(tag, {
|
|
313
|
+
top: (_a = ref_listPos.current) === null || _a === void 0 ? void 0 : _a.y,
|
|
314
|
+
left: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.left,
|
|
315
|
+
width: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.width,
|
|
316
|
+
height: listLayout.height,
|
|
317
|
+
opacity: 1,
|
|
318
|
+
});
|
|
319
|
+
hasShownRootView.current = true;
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
else if (!isKeyboardFullyShown && ref_isFocus.current) {
|
|
323
|
+
console.log('AutoPositionedPopup isKeyboardFullyShown useEffect removeRootView tag=', tag, ' forceRemoveAllRootViewOnItemSelected=', forceRemoveAllRootViewOnItemSelected);
|
|
324
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected);
|
|
325
|
+
setState((prevState) => {
|
|
326
|
+
return Object.assign(Object.assign({}, prevState), { isFocus: false });
|
|
327
|
+
});
|
|
328
|
+
setSearchQuery('');
|
|
329
|
+
hasAddedRootView.current = false;
|
|
330
|
+
hasShownRootView.current = false;
|
|
331
|
+
}
|
|
269
332
|
}
|
|
270
333
|
else {
|
|
271
|
-
|
|
334
|
+
if (state.isFocus) {
|
|
335
|
+
(_b = refAutoPositionedPopup.current) === null || _b === void 0 ? void 0 : _b.measureInWindow((x, y, width, height) => {
|
|
336
|
+
console.log('AutoPositionedPopup measureInWindow x=', x, ' y=', y, ' width=', width, ' height=', height);
|
|
337
|
+
// SIMPLE CENTER-BASED POSITIONING STRATEGY
|
|
338
|
+
const screenHeight = Dimensions.get('screen').height;
|
|
339
|
+
const screenCenter = screenHeight / 2;
|
|
340
|
+
console.log('AutoPositionedPopup screenHeight=', screenHeight, ' screenCenter=', screenCenter, ' componentY=', y);
|
|
341
|
+
// Simple rule: if component Y > screen center, show popup above; otherwise show below
|
|
342
|
+
if (y + insets.top > screenCenter) {
|
|
343
|
+
console.log('AutoPositionedPopup: showing above (Y > center)');
|
|
344
|
+
ref_listPos.current = { x: x, y: y - listLayout.height, width: width };
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
console.log('AutoPositionedPopup: showing below (Y <= center)');
|
|
348
|
+
ref_listPos.current = { x: x, y: y + height + insets.top, width: width };
|
|
349
|
+
}
|
|
350
|
+
console.log('AutoPositionedPopup ref_listPos.current=', ref_listPos.current);
|
|
351
|
+
if (CustomPopView && CustomPopViewStyle) {
|
|
352
|
+
console.log('AutoPositionedPopup CustomPopViewStyle=', CustomPopViewStyle);
|
|
353
|
+
// Ensure CustomPopViewStyle.height is a number before using it in calculations
|
|
354
|
+
const customHeight = typeof CustomPopViewStyle.height === 'number' ? CustomPopViewStyle.height : listLayout.height;
|
|
355
|
+
// Apply same simple center-based strategy for CustomPopView
|
|
356
|
+
console.log('AutoPositionedPopup CustomPopView using center-based positioning, customHeight=', customHeight);
|
|
357
|
+
// Simple rule: if component Y > screen center, show popup above; otherwise show below
|
|
358
|
+
if (y > screenCenter) {
|
|
359
|
+
console.log('AutoPositionedPopup CustomPopView: showing above (Y > center), tag=', tag);
|
|
360
|
+
ref_listPos.current = { x: x, y: y - customHeight, width: width };
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
console.log('AutoPositionedPopup CustomPopView: showing below (Y <= center), tag=', tag);
|
|
364
|
+
ref_listPos.current = { x: x, y: y + height, width: width };
|
|
365
|
+
}
|
|
366
|
+
const PopViewComponent = CustomPopView();
|
|
367
|
+
console.log('AutoPositionedPopup addRootView PopViewComponent=', PopViewComponent);
|
|
368
|
+
console.log('AutoPositionedPopup addRootView state.selectedItem=', state.selectedItem);
|
|
369
|
+
addRootView({
|
|
370
|
+
id: tag,
|
|
371
|
+
style: !centerDisplay
|
|
372
|
+
? Object.assign({ top: ref_listPos.current.y, left: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.left, width: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.width, height: listLayout.height, opacity: 1 }, CustomPopViewStyle) : Object.assign({ width: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.width, height: listLayout.height }, CustomPopViewStyle),
|
|
373
|
+
component: <PopViewComponent selectedItem={state.selectedItem}></PopViewComponent>,
|
|
374
|
+
useModal: true,
|
|
375
|
+
onModalClose: () => {
|
|
376
|
+
console.log('AutoPositionedPopup onModalClose');
|
|
377
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected, rootViewsRef.current);
|
|
378
|
+
setState((prevState) => {
|
|
379
|
+
return Object.assign(Object.assign({}, prevState), { isFocus: false });
|
|
380
|
+
});
|
|
381
|
+
hasAddedRootView.current = false;
|
|
382
|
+
hasShownRootView.current = false;
|
|
383
|
+
hasTriggeredFocus.current = false;
|
|
384
|
+
setSearchQuery('');
|
|
385
|
+
},
|
|
386
|
+
centerDisplay,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
console.log('AutoPositionedPopup addRootView tag=', tag);
|
|
391
|
+
addRootView({
|
|
392
|
+
id: tag,
|
|
393
|
+
style: {
|
|
394
|
+
top: ref_listPos.current.y,
|
|
395
|
+
left: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.left,
|
|
396
|
+
width: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.width,
|
|
397
|
+
height: listLayout.height,
|
|
398
|
+
opacity: 1,
|
|
399
|
+
},
|
|
400
|
+
component: (<AutoPositionedPopupList tag={tag} updateState={updateState} fetchData={fetchData} pageSize={pageSize} renderItem={renderItem} selectedItem={state.selectedItem} localSearch={localSearch}/>),
|
|
401
|
+
useModal: true,
|
|
402
|
+
onModalClose: () => {
|
|
403
|
+
console.log('AutoPositionedPopup onModalClose tag=', tag);
|
|
404
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected, rootViewsRef.current);
|
|
405
|
+
setState((prevState) => {
|
|
406
|
+
return Object.assign({}, prevState);
|
|
407
|
+
});
|
|
408
|
+
setSearchQuery('');
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (isKeyboardFullyShown) {
|
|
416
|
+
ref_isFocus.current = state.isFocus;
|
|
417
|
+
if (isKeyboardFullyShown !== keyboardVisibleRef.current) {
|
|
418
|
+
keyboardVisibleRef.current = isKeyboardFullyShown;
|
|
419
|
+
if (isKeyboardFullyShown && textInputRef.current) {
|
|
420
|
+
if (ref_searchQuery.current) {
|
|
421
|
+
textInputRef.current.setNativeProps({ text: ref_searchQuery.current });
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
272
425
|
}
|
|
273
|
-
}, [
|
|
426
|
+
}, [insets,
|
|
427
|
+
isKeyboardFullyShown,
|
|
428
|
+
state.isFocus,
|
|
429
|
+
useTextInput,
|
|
430
|
+
CustomPopView,
|
|
431
|
+
CustomPopViewStyle,
|
|
432
|
+
forceRemoveAllRootViewOnItemSelected,
|
|
433
|
+
tag,
|
|
434
|
+
state.selectedItem,
|
|
435
|
+
]);
|
|
274
436
|
// Imperative handle for parent component access
|
|
275
437
|
useImperativeHandle(parentRef, () => ({
|
|
276
438
|
clearSelectedItem: () => {
|
|
277
|
-
|
|
278
|
-
|
|
439
|
+
console.log('AutoPositionedPopup clearSelectedItem tag=', tag);
|
|
440
|
+
setState((prevState) => {
|
|
441
|
+
return Object.assign(Object.assign({}, prevState), { selectedItem: undefined });
|
|
442
|
+
});
|
|
279
443
|
},
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
444
|
+
}), []);
|
|
445
|
+
const updateState = (key, value) => {
|
|
446
|
+
console.log('AutoPositionedPopup updateState key=', key, ' value=', value);
|
|
447
|
+
setState((prevState) => (Object.assign(Object.assign({}, prevState), { [key]: value })));
|
|
448
|
+
if (key === 'selectedItem' && onItemSelected) {
|
|
449
|
+
onItemSelected(value);
|
|
450
|
+
console.log('AutoPositionedPopup updateState onItemSelected rootViewsRef.current=', rootViewsRef.current);
|
|
451
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected, rootViewsRef.current);
|
|
452
|
+
hasAddedRootView.current = false;
|
|
453
|
+
hasShownRootView.current = false;
|
|
454
|
+
hasTriggeredFocus.current = false;
|
|
455
|
+
setState((prevState) => {
|
|
456
|
+
return Object.assign(Object.assign({}, prevState), { isFocus: false });
|
|
457
|
+
});
|
|
458
|
+
setSearchQuery('');
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
// Render the component following project implementation
|
|
462
|
+
return useMemo(() => {
|
|
463
|
+
var _a;
|
|
464
|
+
console.log('AutoPositionedPopup render tag=', tag); // Now safe - circular dependency fixed
|
|
465
|
+
return (<CustomRow>
|
|
466
|
+
<View style={[styles.contain, style]} ref={refAutoPositionedPopup}>
|
|
467
|
+
{!state.isFocus || !useTextInput ? (<TouchableOpacity style={[styles.AutoPositionedPopupBtn, AutoPositionedPopupBtnStyle]} disabled={AutoPositionedPopupBtnDisabled} onPress={() => {
|
|
468
|
+
console.log('AutoPositionedPopup onPress tag=', tag);
|
|
469
|
+
console.log('AutoPositionedPopup onPress state.isFocus=', state.isFocus);
|
|
470
|
+
console.log('AutoPositionedPopup onPress useTextInput=', useTextInput);
|
|
471
|
+
console.log('AutoPositionedPopup onPress hasAddedRootView.current=', hasAddedRootView.current);
|
|
472
|
+
console.log('AutoPositionedPopup onPress hasShownRootView.current=', hasShownRootView.current);
|
|
473
|
+
console.log('AutoPositionedPopup onPress hasTriggeredFocus.current=', hasTriggeredFocus.current);
|
|
474
|
+
console.log('AutoPositionedPopup onPress state.selectedItem=', state.selectedItem);
|
|
475
|
+
setState((prevState) => {
|
|
476
|
+
return Object.assign(Object.assign({}, prevState), { isFocus: true });
|
|
477
|
+
});
|
|
478
|
+
if (!hasAddedRootView.current && useTextInput) {
|
|
479
|
+
hasAddedRootView.current = true;
|
|
480
|
+
hasShownRootView.current = false;
|
|
481
|
+
addRootView({
|
|
482
|
+
id: tag,
|
|
483
|
+
style: {
|
|
484
|
+
top: 0,
|
|
485
|
+
left: 0,
|
|
486
|
+
width: popUpViewStyle === null || popUpViewStyle === void 0 ? void 0 : popUpViewStyle.width,
|
|
487
|
+
height: listLayout.height,
|
|
488
|
+
opacity: 0,
|
|
489
|
+
},
|
|
490
|
+
component: (<AutoPositionedPopupList tag={tag} updateState={updateState} fetchData={fetchData} pageSize={pageSize} renderItem={renderItem} selectedItem={state.selectedItem} localSearch={localSearch}/>),
|
|
491
|
+
useModal: false,
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
}}>
|
|
495
|
+
{!btwChildren ? (<Text style={[
|
|
496
|
+
styles.searchQueryTxt,
|
|
497
|
+
state.selectedItem && { color: theme.colors.text },
|
|
498
|
+
labelStyle,
|
|
499
|
+
]} numberOfLines={1} ellipsizeMode={'tail'}>
|
|
500
|
+
{((_a = state.selectedItem) === null || _a === void 0 ? void 0 : _a.title) || placeholder}
|
|
501
|
+
</Text>) : (btwChildren())}
|
|
502
|
+
</TouchableOpacity>) : (useTextInput &&
|
|
503
|
+
state.isFocus && (<RNTextInput ref={textInputRef} key="fixed-textinput-key" style={[
|
|
504
|
+
styles.inputStyle,
|
|
505
|
+
inputStyle,
|
|
506
|
+
]} textAlign={TextInputProps['textAlign'] || 'left'} multiline={TextInputProps['multiline'] || false} numberOfLines={TextInputProps['numberOfLines'] || 1} onChangeText={(searchQuery) => {
|
|
507
|
+
ref_searchQuery.current = searchQuery;
|
|
508
|
+
console.log('AutoPositionedPopup onChangeText rootViews=', rootViews);
|
|
509
|
+
if (!localSearch) {
|
|
510
|
+
if (debounceTimerRef.current) {
|
|
511
|
+
clearTimeout(debounceTimerRef.current);
|
|
512
|
+
}
|
|
513
|
+
debounceTimerRef.current = setTimeout(() => {
|
|
514
|
+
emitQueryChange(ref_searchQuery.current);
|
|
515
|
+
}, 500);
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
emitQueryChange(ref_searchQuery.current);
|
|
519
|
+
}
|
|
520
|
+
}} placeholderTextColor={theme.colors.placeholderText} placeholder={placeholder} onKeyPress={(e) => {
|
|
521
|
+
if (e.nativeEvent.key === 'Enter') {
|
|
522
|
+
Keyboard.dismiss();
|
|
523
|
+
}
|
|
524
|
+
}} keyboardType={TextInputProps['keyboardType'] || 'default'} clearButtonMode="while-editing" returnKeyType={TextInputProps['returnKeyType'] || 'done'} maxLength={TextInputProps['maxLength'] || 100} accessibilityLabel="selectInput" accessible={true} autoFocus={TextInputProps['autoFocus'] || false} autoCorrect={false} underlineColorAndroid="transparent" editable={TextInputProps['editable'] || true} secureTextEntry={TextInputProps['secureTextEntry'] || false} defaultValue="" caretHidden={false} enablesReturnKeyAutomatically onFocus={() => {
|
|
525
|
+
console.log('AutoPositionedPopup onFocus tag=', tag, ' selectedItem=', state.selectedItem, ' hasTriggeredFocus.current=', hasTriggeredFocus.current, ' textInputRef.current=', textInputRef.current, ' ref_searchQuery.current=', ref_searchQuery.current);
|
|
526
|
+
if (!hasTriggeredFocus.current) {
|
|
527
|
+
hasTriggeredFocus.current = true;
|
|
528
|
+
ref_isFocus.current = true;
|
|
529
|
+
if (state.selectedItem) {
|
|
530
|
+
ref_searchQuery.current = state.selectedItem.title;
|
|
531
|
+
}
|
|
532
|
+
if (textInputRef.current && ref_searchQuery.current) {
|
|
533
|
+
textInputRef.current.setNativeProps({
|
|
534
|
+
text: ref_searchQuery.current,
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}} onBlur={() => {
|
|
539
|
+
console.log('AutoPositionedPopup onBlur tag=', tag, 'textInputRef.current=', textInputRef.current);
|
|
540
|
+
hasTriggeredFocus.current = false;
|
|
541
|
+
hasAddedRootView.current = false; // 重置 RootView 狀態
|
|
542
|
+
hasShownRootView.current = false;
|
|
543
|
+
ref_isFocus.current = false;
|
|
544
|
+
setState((prevState) => {
|
|
545
|
+
return Object.assign(Object.assign({}, prevState), { isFocus: false });
|
|
546
|
+
});
|
|
547
|
+
removeRootView(tag, forceRemoveAllRootViewOnItemSelected);
|
|
548
|
+
setSearchQuery('');
|
|
549
|
+
if (textInputRef.current) {
|
|
550
|
+
textInputRef.current.setNativeProps({ text: '' });
|
|
551
|
+
ref_searchQuery.current = '';
|
|
552
|
+
textInputRef.current.blur();
|
|
553
|
+
}
|
|
554
|
+
Keyboard.dismiss();
|
|
555
|
+
}} selectTextOnFocus={TextInputProps['selectTextOnFocus'] || false} onSubmitEditing={(e) => {
|
|
556
|
+
console.log('AutoPositionedPopup.tsx onSubmitEditing e.nativeEvent.text=', e.nativeEvent.text);
|
|
557
|
+
onSubmitEditing && onSubmitEditing(e);
|
|
558
|
+
}}/>))}
|
|
559
|
+
</View>
|
|
560
|
+
</CustomRow>);
|
|
561
|
+
}, [tag,
|
|
562
|
+
fetchData,
|
|
563
|
+
renderItem,
|
|
564
|
+
onItemSelected,
|
|
565
|
+
onSubmitEditing,
|
|
566
|
+
localSearch,
|
|
567
|
+
placeholder,
|
|
568
|
+
textAlign,
|
|
569
|
+
pageSize,
|
|
570
|
+
selectedItem,
|
|
571
|
+
CustomRow,
|
|
572
|
+
useTextInput,
|
|
573
|
+
btwChildren,
|
|
574
|
+
selectedItem,
|
|
575
|
+
keyExtractor,
|
|
576
|
+
AutoPositionedPopupBtnStyle,
|
|
577
|
+
CustomPopView,
|
|
578
|
+
CustomPopViewStyle,
|
|
579
|
+
forceRemoveAllRootViewOnItemSelected,
|
|
580
|
+
inputStyle,
|
|
581
|
+
TextInputProps,
|
|
582
|
+
state.isFocus,]);
|
|
305
583
|
}));
|
|
306
584
|
export default AutoPositionedPopup;
|
|
585
|
+
//# sourceMappingURL=AutoPositionedPopup.js.map
|