react-native-auto-positioned-popup 1.0.2
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/LICENSE +21 -0
- package/README.md +425 -0
- package/README_zh.md +425 -0
- package/lib/AutoPositionedPopup.d.ts +5 -0
- package/lib/AutoPositionedPopup.d.ts.map +1 -0
- package/lib/AutoPositionedPopup.js +306 -0
- package/lib/AutoPositionedPopup.style.d.ts +80 -0
- package/lib/AutoPositionedPopup.style.d.ts.map +1 -0
- package/lib/AutoPositionedPopup.style.js +79 -0
- package/lib/AutoPositionedPopupProps.d.ts +58 -0
- package/lib/AutoPositionedPopupProps.d.ts.map +1 -0
- package/lib/AutoPositionedPopupProps.js +1 -0
- package/lib/RootViewContext.d.ts +31 -0
- package/lib/RootViewContext.d.ts.map +1 -0
- package/lib/RootViewContext.js +136 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +7 -0
- package/package.json +82 -0
- package/src/AutoPositionedPopup.style.ts +80 -0
- package/src/AutoPositionedPopup.tsx +529 -0
- package/src/AutoPositionedPopupProps.ts +61 -0
- package/src/RootViewContext.tsx +186 -0
- package/src/index.ts +16 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import React, { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
|
|
2
|
+
import { Dimensions, Keyboard, Text, TextInput as RNTextInput, TouchableOpacity, View, } from 'react-native';
|
|
3
|
+
import { AdvancedFlatList } from 'react-native-advanced-flatlist';
|
|
4
|
+
import styles from './AutoPositionedPopup.style';
|
|
5
|
+
import { useRootView } from './RootViewContext';
|
|
6
|
+
const queryChangeListeners = [];
|
|
7
|
+
const emitQueryChange = (query) => {
|
|
8
|
+
console.log('AutoPositionedPopup.tsx emitQueryChange query=', query, ' listeners=', queryChangeListeners.length);
|
|
9
|
+
queryChangeListeners.forEach((l) => l(query));
|
|
10
|
+
};
|
|
11
|
+
const subscribeQueryChange = (listener) => {
|
|
12
|
+
queryChangeListeners.push(listener);
|
|
13
|
+
return () => {
|
|
14
|
+
const idx = queryChangeListeners.indexOf(listener);
|
|
15
|
+
if (idx !== -1)
|
|
16
|
+
queryChangeListeners.splice(idx, 1);
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
// Default light theme
|
|
20
|
+
const defaultTheme = {
|
|
21
|
+
colors: {
|
|
22
|
+
text: '#333333',
|
|
23
|
+
placeholderText: '#999999',
|
|
24
|
+
background: '#FFFFFF',
|
|
25
|
+
border: '#E0E0E0',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
// List item component for rendering individual items
|
|
29
|
+
const ListItem = memo(({ item, index, selectedItem, onItemPress, theme, rootViewsRef, selectedItemBackgroundColor = 'rgba(116, 116, 128, 0.08)' }) => {
|
|
30
|
+
const isSelected = item.id === (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id);
|
|
31
|
+
return useMemo(() => (<TouchableOpacity key={item.id} style={[
|
|
32
|
+
styles.commonModalRow,
|
|
33
|
+
{
|
|
34
|
+
backgroundColor: isSelected ? selectedItemBackgroundColor : 'transparent',
|
|
35
|
+
borderColor: theme.colors.border,
|
|
36
|
+
},
|
|
37
|
+
]} onPress={() => {
|
|
38
|
+
console.log('AutoPositionedPopup.tsx ListItem onPress item=', item);
|
|
39
|
+
if (rootViewsRef) {
|
|
40
|
+
console.log('AutoPositionedPopup.tsx ListItem onPress rootViews=', rootViewsRef.current);
|
|
41
|
+
}
|
|
42
|
+
onItemPress(item);
|
|
43
|
+
}}>
|
|
44
|
+
<Text style={[styles.ListItemCode, { color: theme.colors.text }]} numberOfLines={1} ellipsizeMode="tail">
|
|
45
|
+
{item.title}
|
|
46
|
+
</Text>
|
|
47
|
+
</TouchableOpacity>), [item, index, selectedItem, onItemPress, theme, rootViewsRef, isSelected, selectedItemBackgroundColor]);
|
|
48
|
+
});
|
|
49
|
+
const PopupList = memo(({ data, selectedItem, onItemPress, renderItem, keyExtractor = (item) => String(item.id), theme, rootViewsRef, fetchData, localSearch = false, pageSize = 20, onDataUpdate, selectedItemBackgroundColor, }) => {
|
|
50
|
+
const [internalData, setInternalData] = useState(data);
|
|
51
|
+
const searchQueryRef = useRef('');
|
|
52
|
+
// Sync external data changes
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
setInternalData(data);
|
|
55
|
+
}, [data]);
|
|
56
|
+
// Listen to search query changes
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
const unsubscribe = subscribeQueryChange(async (newQuery) => {
|
|
59
|
+
console.log('PopupList subscribeQueryChange newQuery=', newQuery);
|
|
60
|
+
searchQueryRef.current = newQuery;
|
|
61
|
+
if (fetchData) {
|
|
62
|
+
try {
|
|
63
|
+
const result = await fetchData({
|
|
64
|
+
pageIndex: 0,
|
|
65
|
+
pageSize,
|
|
66
|
+
searchQuery: newQuery,
|
|
67
|
+
});
|
|
68
|
+
if (result === null || result === void 0 ? void 0 : result.items) {
|
|
69
|
+
setInternalData(result.items);
|
|
70
|
+
onDataUpdate === null || onDataUpdate === void 0 ? void 0 : onDataUpdate(result.items);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.error('PopupList fetchData error:', error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else if (localSearch) {
|
|
78
|
+
// Local filtering
|
|
79
|
+
const filtered = data.filter(item => item.title.toLowerCase().includes(newQuery.toLowerCase()));
|
|
80
|
+
setInternalData(filtered);
|
|
81
|
+
onDataUpdate === null || onDataUpdate === void 0 ? void 0 : onDataUpdate(filtered);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return unsubscribe;
|
|
85
|
+
}, [fetchData, localSearch, pageSize, data, onDataUpdate]);
|
|
86
|
+
const defaultRenderItem = useCallback(({ item, index }) => (<ListItem item={item} index={index} selectedItem={selectedItem} onItemPress={onItemPress} theme={theme} rootViewsRef={rootViewsRef} selectedItemBackgroundColor={selectedItemBackgroundColor}/>), [selectedItem, onItemPress, theme, rootViewsRef, selectedItemBackgroundColor]);
|
|
87
|
+
return (<View style={[styles.autoPositionedPopupList, { backgroundColor: theme.colors.background }]}>
|
|
88
|
+
<AdvancedFlatList data={internalData} keyExtractor={keyExtractor} renderItem={renderItem || defaultRenderItem} keyboardShouldPersistTaps="always" showsVerticalScrollIndicator={true} nestedScrollEnabled={true}/>
|
|
89
|
+
</View>);
|
|
90
|
+
});
|
|
91
|
+
// Main AutoPositionedPopup component
|
|
92
|
+
const AutoPositionedPopup = memo(forwardRef((props, parentRef) => {
|
|
93
|
+
const { tag, style, AutoPositionedPopupBtnStyle, placeholder = 'Please Select', textAlign = 'right', 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;
|
|
94
|
+
// Use RootView context
|
|
95
|
+
const { addRootView, removeRootView, rootViews, searchQuery: contextSearchQuery, setSearchQuery: setContextSearchQuery } = useRootView();
|
|
96
|
+
const rootViewsRef = useRef(rootViews);
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
rootViewsRef.current = rootViews;
|
|
99
|
+
}, [rootViews]);
|
|
100
|
+
// State management
|
|
101
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
102
|
+
const [data, setData] = useState([]);
|
|
103
|
+
const [loading, setLoading] = useState(false);
|
|
104
|
+
const [popupPosition, setPopupPosition] = useState({ top: 0, left: 0, width: 0 });
|
|
105
|
+
const popupId = useRef(`popup-${tag}-${Date.now()}`);
|
|
106
|
+
// Refs for performance optimization
|
|
107
|
+
const containerRef = useRef(null);
|
|
108
|
+
const textInputRef = useRef(null);
|
|
109
|
+
const debounceTimerRef = useRef(null);
|
|
110
|
+
const searchQueryRef = useRef(''); // Use ref instead of state to avoid re-renders
|
|
111
|
+
// Constants
|
|
112
|
+
const LIST_HEIGHT = 200;
|
|
113
|
+
const theme = defaultTheme;
|
|
114
|
+
// Fetch data function
|
|
115
|
+
const loadData = useCallback(async (query = '') => {
|
|
116
|
+
if (!fetchData)
|
|
117
|
+
return;
|
|
118
|
+
setLoading(true);
|
|
119
|
+
try {
|
|
120
|
+
const result = await fetchData({
|
|
121
|
+
pageIndex: 0,
|
|
122
|
+
pageSize,
|
|
123
|
+
searchQuery: query,
|
|
124
|
+
});
|
|
125
|
+
if (result === null || result === void 0 ? void 0 : result.items) {
|
|
126
|
+
setData(result.items);
|
|
127
|
+
}
|
|
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
|
|
153
|
+
}, []);
|
|
154
|
+
// Calculate popup position
|
|
155
|
+
const calculatePosition = useCallback(() => {
|
|
156
|
+
if (!containerRef.current)
|
|
157
|
+
return;
|
|
158
|
+
containerRef.current.measureInWindow((x, y, width, height) => {
|
|
159
|
+
const screenHeight = Dimensions.get('screen').height;
|
|
160
|
+
const screenWidth = Dimensions.get('screen').width;
|
|
161
|
+
let top = y + height;
|
|
162
|
+
let left = x;
|
|
163
|
+
let popupWidth = width;
|
|
164
|
+
// Check if popup should appear above the input
|
|
165
|
+
if (y + height + LIST_HEIGHT > screenHeight) {
|
|
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
|
|
187
|
+
}
|
|
188
|
+
removeRootView(popupId.current, forceRemoveAllRootViewOnItemSelected, rootViewsRef.current);
|
|
189
|
+
}, [removeRootView, forceRemoveAllRootViewOnItemSelected]);
|
|
190
|
+
// Handle data updates from PopupList
|
|
191
|
+
const handleDataUpdate = useCallback((newData) => {
|
|
192
|
+
setData(newData);
|
|
193
|
+
}, []);
|
|
194
|
+
// Handle item selection
|
|
195
|
+
const handleItemPress = useCallback((item) => {
|
|
196
|
+
onItemSelected === null || onItemSelected === void 0 ? void 0 : onItemSelected(item);
|
|
197
|
+
hidePopup();
|
|
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,
|
|
255
|
+
});
|
|
256
|
+
}, 100);
|
|
257
|
+
}, [calculatePosition, loadData, popupPosition, useTextInput, placeholder, theme, inputStyle, TextInputProps, data, selectedItem, renderItem, keyExtractor, centerDisplay, addRootView, hidePopup, handleSearchChange, handleItemPress, LIST_HEIGHT, selectedItemBackgroundColor]);
|
|
258
|
+
// Handle button press
|
|
259
|
+
const handleButtonPress = useCallback(() => {
|
|
260
|
+
if (AutoPositionedPopupBtnDisabled)
|
|
261
|
+
return;
|
|
262
|
+
if (useTextInput) {
|
|
263
|
+
showPopup();
|
|
264
|
+
// Focus text input after a short delay
|
|
265
|
+
setTimeout(() => {
|
|
266
|
+
var _a;
|
|
267
|
+
(_a = textInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
268
|
+
}, 100);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
showPopup();
|
|
272
|
+
}
|
|
273
|
+
}, [AutoPositionedPopupBtnDisabled, useTextInput, showPopup]);
|
|
274
|
+
// Imperative handle for parent component access
|
|
275
|
+
useImperativeHandle(parentRef, () => ({
|
|
276
|
+
clearSelectedItem: () => {
|
|
277
|
+
// Clear selection logic can be implemented here
|
|
278
|
+
console.log('Clearing selected item for:', tag);
|
|
279
|
+
},
|
|
280
|
+
showPopup,
|
|
281
|
+
hidePopup,
|
|
282
|
+
}), [tag, showPopup, hidePopup]);
|
|
283
|
+
// Cleanup
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
return () => {
|
|
286
|
+
if (debounceTimerRef.current) {
|
|
287
|
+
clearTimeout(debounceTimerRef.current);
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
}, []);
|
|
291
|
+
// Render the component
|
|
292
|
+
return (<CustomRow>
|
|
293
|
+
<View style={[styles.contain, style]} ref={containerRef}>
|
|
294
|
+
<TouchableOpacity style={[styles.AutoPositionedPopupBtn, AutoPositionedPopupBtnStyle]} disabled={AutoPositionedPopupBtnDisabled} onPress={handleButtonPress}>
|
|
295
|
+
{btwChildren ? (btwChildren()) : (<Text style={[
|
|
296
|
+
styles.searchQueryTxt,
|
|
297
|
+
selectedItem && { color: theme.colors.text },
|
|
298
|
+
labelStyle,
|
|
299
|
+
]} numberOfLines={1} ellipsizeMode="tail">
|
|
300
|
+
{(selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.title) || placeholder}
|
|
301
|
+
</Text>)}
|
|
302
|
+
</TouchableOpacity>
|
|
303
|
+
</View>
|
|
304
|
+
</CustomRow>);
|
|
305
|
+
}));
|
|
306
|
+
export default AutoPositionedPopup;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
des: {
|
|
3
|
+
fontSize: number;
|
|
4
|
+
lineHeight: number;
|
|
5
|
+
fontWeight: "400";
|
|
6
|
+
color: string;
|
|
7
|
+
marginLeft: number;
|
|
8
|
+
};
|
|
9
|
+
ListItemCode: {
|
|
10
|
+
fontSize: number;
|
|
11
|
+
lineHeight: number;
|
|
12
|
+
fontWeight: "600";
|
|
13
|
+
color: string;
|
|
14
|
+
};
|
|
15
|
+
commonModalRow: {
|
|
16
|
+
height: number;
|
|
17
|
+
borderBottomWidth: number;
|
|
18
|
+
overflow: "hidden";
|
|
19
|
+
alignItems: "center";
|
|
20
|
+
justifyContent: "center";
|
|
21
|
+
width: "100%";
|
|
22
|
+
flexDirection: "row";
|
|
23
|
+
borderRadius: number;
|
|
24
|
+
};
|
|
25
|
+
autoPositionedPopupList: {
|
|
26
|
+
flex: number;
|
|
27
|
+
height: "100%";
|
|
28
|
+
padding: number;
|
|
29
|
+
};
|
|
30
|
+
inputStyle: {
|
|
31
|
+
fontSize: number;
|
|
32
|
+
fontWeight: "400";
|
|
33
|
+
lineHeight: number;
|
|
34
|
+
color: string;
|
|
35
|
+
width: "90%";
|
|
36
|
+
textAlign: "right";
|
|
37
|
+
};
|
|
38
|
+
AutoPositionedPopupBtn: {
|
|
39
|
+
flex: number;
|
|
40
|
+
flexDirection: "row";
|
|
41
|
+
alignItems: "center";
|
|
42
|
+
};
|
|
43
|
+
searchQueryTxt: {
|
|
44
|
+
fontSize: number;
|
|
45
|
+
lineHeight: number;
|
|
46
|
+
color: string;
|
|
47
|
+
textAlign: "right";
|
|
48
|
+
};
|
|
49
|
+
contain: {
|
|
50
|
+
flex: number;
|
|
51
|
+
height: "100%";
|
|
52
|
+
};
|
|
53
|
+
selectArrow: {
|
|
54
|
+
marginLeft: number;
|
|
55
|
+
marginRight: number;
|
|
56
|
+
width: number;
|
|
57
|
+
height: number;
|
|
58
|
+
};
|
|
59
|
+
AutoDropdownBtnStyle1: {
|
|
60
|
+
justifyContent: "flex-start";
|
|
61
|
+
};
|
|
62
|
+
AutoDropdownBtnStyle: {
|
|
63
|
+
justifyContent: "flex-end";
|
|
64
|
+
};
|
|
65
|
+
usageRowText: {
|
|
66
|
+
fontSize: number;
|
|
67
|
+
lineHeight: number;
|
|
68
|
+
fontWeight: "400";
|
|
69
|
+
color: string;
|
|
70
|
+
};
|
|
71
|
+
AutoDropdownRow: {
|
|
72
|
+
flex: number;
|
|
73
|
+
height: number;
|
|
74
|
+
flexDirection: "row";
|
|
75
|
+
alignItems: "center";
|
|
76
|
+
justifyContent: "space-between";
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
export default _default;
|
|
80
|
+
//# sourceMappingURL=AutoPositionedPopup.style.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutoPositionedPopup.style.d.ts","sourceRoot":"","sources":["../src/AutoPositionedPopup.style.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,wBA6EG"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
export default StyleSheet.create({
|
|
3
|
+
des: {
|
|
4
|
+
fontSize: 12,
|
|
5
|
+
lineHeight: 20,
|
|
6
|
+
fontWeight: '400',
|
|
7
|
+
color: '#666666',
|
|
8
|
+
marginLeft: 4,
|
|
9
|
+
},
|
|
10
|
+
ListItemCode: {
|
|
11
|
+
fontSize: 15,
|
|
12
|
+
lineHeight: 20,
|
|
13
|
+
fontWeight: '600',
|
|
14
|
+
color: '#333333',
|
|
15
|
+
},
|
|
16
|
+
commonModalRow: {
|
|
17
|
+
height: 32,
|
|
18
|
+
borderBottomWidth: 0,
|
|
19
|
+
overflow: 'hidden',
|
|
20
|
+
alignItems: 'center',
|
|
21
|
+
justifyContent: 'center',
|
|
22
|
+
width: '100%',
|
|
23
|
+
flexDirection: 'row',
|
|
24
|
+
borderRadius: 8,
|
|
25
|
+
},
|
|
26
|
+
autoPositionedPopupList: {
|
|
27
|
+
flex: 1,
|
|
28
|
+
height: '100%',
|
|
29
|
+
padding: 12,
|
|
30
|
+
},
|
|
31
|
+
inputStyle: {
|
|
32
|
+
fontSize: 15,
|
|
33
|
+
fontWeight: '400',
|
|
34
|
+
lineHeight: 20,
|
|
35
|
+
color: '#333333',
|
|
36
|
+
width: '90%',
|
|
37
|
+
textAlign: 'right',
|
|
38
|
+
},
|
|
39
|
+
AutoPositionedPopupBtn: {
|
|
40
|
+
flex: 1,
|
|
41
|
+
flexDirection: 'row',
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
},
|
|
44
|
+
searchQueryTxt: {
|
|
45
|
+
fontSize: 17,
|
|
46
|
+
lineHeight: 24,
|
|
47
|
+
color: '#999999',
|
|
48
|
+
textAlign: 'right',
|
|
49
|
+
},
|
|
50
|
+
contain: {
|
|
51
|
+
flex: 1,
|
|
52
|
+
height: '100%',
|
|
53
|
+
},
|
|
54
|
+
selectArrow: {
|
|
55
|
+
marginLeft: 6,
|
|
56
|
+
marginRight: 8,
|
|
57
|
+
width: 8,
|
|
58
|
+
height: 14,
|
|
59
|
+
},
|
|
60
|
+
AutoDropdownBtnStyle1: {
|
|
61
|
+
justifyContent: 'flex-start',
|
|
62
|
+
},
|
|
63
|
+
AutoDropdownBtnStyle: {
|
|
64
|
+
justifyContent: 'flex-end',
|
|
65
|
+
},
|
|
66
|
+
usageRowText: {
|
|
67
|
+
fontSize: 17,
|
|
68
|
+
lineHeight: 21,
|
|
69
|
+
fontWeight: '400',
|
|
70
|
+
color: '#333333',
|
|
71
|
+
},
|
|
72
|
+
AutoDropdownRow: {
|
|
73
|
+
flex: 1,
|
|
74
|
+
height: 50,
|
|
75
|
+
flexDirection: 'row',
|
|
76
|
+
alignItems: 'center',
|
|
77
|
+
justifyContent: 'space-between',
|
|
78
|
+
},
|
|
79
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleProp, TextInputProps, TextStyle, ViewStyle } from 'react-native';
|
|
3
|
+
import { TextInputSubmitEditingEventData } from 'react-native/Libraries/Components/TextInput/TextInput';
|
|
4
|
+
import { NativeSyntheticEvent } from 'react-native/Libraries/Types/CoreEventTypes';
|
|
5
|
+
export interface Data {
|
|
6
|
+
items: any[];
|
|
7
|
+
pageIndex: number;
|
|
8
|
+
needLoadMore: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface SelectedItem {
|
|
11
|
+
id: string;
|
|
12
|
+
title: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Props interface for AutoPositionedPopup component
|
|
16
|
+
*/
|
|
17
|
+
export interface AutoPositionedPopupProps {
|
|
18
|
+
style?: ViewStyle;
|
|
19
|
+
labelStyle?: ViewStyle;
|
|
20
|
+
tag: string;
|
|
21
|
+
tagStyle?: ViewStyle;
|
|
22
|
+
fetchData?: ({ pageIndex, pageSize, searchQuery, }: {
|
|
23
|
+
pageIndex: number;
|
|
24
|
+
pageSize: number;
|
|
25
|
+
searchQuery?: string;
|
|
26
|
+
}) => Promise<Data | null>;
|
|
27
|
+
renderItem?: ({ item, index }: {
|
|
28
|
+
item: SelectedItem;
|
|
29
|
+
index: number;
|
|
30
|
+
}) => React.ReactElement;
|
|
31
|
+
onItemSelected?: (item: SelectedItem) => void;
|
|
32
|
+
onSubmitEditing?: (e: NativeSyntheticEvent<TextInputSubmitEditingEventData>) => void;
|
|
33
|
+
localSearch?: boolean;
|
|
34
|
+
placeholder?: string;
|
|
35
|
+
textAlign?: 'left' | 'center' | 'right' | undefined;
|
|
36
|
+
pageSize?: number;
|
|
37
|
+
selectedItem?: SelectedItem | any;
|
|
38
|
+
CustomRow?: React.ComponentType<ViewStyle & {
|
|
39
|
+
children?: React.ReactNode;
|
|
40
|
+
}>;
|
|
41
|
+
btwChildren?: () => React.ReactNode;
|
|
42
|
+
useTextInput?: boolean;
|
|
43
|
+
keyExtractor?: (item: SelectedItem) => string;
|
|
44
|
+
CustomPopView?: () => React.ComponentType<ViewStyle & {
|
|
45
|
+
children?: React.ReactNode;
|
|
46
|
+
selectedItem?: SelectedItem | any;
|
|
47
|
+
}>;
|
|
48
|
+
CustomPopViewStyle?: ViewStyle;
|
|
49
|
+
forceRemoveAllRootViewOnItemSelected?: boolean;
|
|
50
|
+
inputStyle?: StyleProp<TextStyle>;
|
|
51
|
+
TextInputProps?: TextInputProps;
|
|
52
|
+
popUpViewStyle?: ViewStyle;
|
|
53
|
+
AutoPositionedPopupBtnStyle?: ViewStyle;
|
|
54
|
+
AutoPositionedPopupBtnDisabled?: boolean;
|
|
55
|
+
centerDisplay?: boolean;
|
|
56
|
+
selectedItemBackgroundColor?: string;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=AutoPositionedPopupProps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutoPositionedPopupProps.d.ts","sourceRoot":"","sources":["../src/AutoPositionedPopupProps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,+BAA+B,EAAE,MAAM,uDAAuD,CAAC;AACxG,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AAEnF,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,GAAG,EAAE,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,CAAC,EACX,SAAS,EACT,QAAQ,EACR,WAAW,GACZ,EAAE;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAC3B,UAAU,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,KAAK,CAAC,YAAY,CAAC;IAC5F,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9C,eAAe,CAAC,EAAE,CAAC,CAAC,EAAE,oBAAoB,CAAC,+BAA+B,CAAC,KAAK,IAAI,CAAC;IACrF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,YAAY,GAAG,GAAG,CAAC;IAClC,SAAS,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,SAAS,GAAG;QAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;KAAE,CAAC,CAAC;IAC5E,WAAW,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAC;IAC9C,aAAa,CAAC,EAAE,MAAM,KAAK,CAAC,aAAa,CACvC,SAAS,GAAG;QACV,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;QAC3B,YAAY,CAAC,EAAE,YAAY,GAAG,GAAG,CAAC;KACnC,CACF,CAAC;IACF,kBAAkB,CAAC,EAAE,SAAS,CAAC;IAC/B,oCAAoC,CAAC,EAAE,OAAO,CAAC;IAC/C,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,2BAA2B,CAAC,EAAE,SAAS,CAAC;IACxC,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { ViewStyle } from 'react-native';
|
|
3
|
+
interface DynamicViewBase {
|
|
4
|
+
id: string;
|
|
5
|
+
style: ViewStyle;
|
|
6
|
+
component: ReactNode;
|
|
7
|
+
useModal?: boolean;
|
|
8
|
+
onModalClose?: () => void;
|
|
9
|
+
centerDisplay?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface RootViewContextType {
|
|
12
|
+
addRootView: (view: DynamicViewBase) => void;
|
|
13
|
+
setRootViewNativeStyle: (id: string, style: ViewStyle) => void;
|
|
14
|
+
updateRootView: (id: string, update: Partial<DynamicViewBase>) => void;
|
|
15
|
+
removeRootView: (id?: string, force?: boolean, _rootViews?: DynamicViewBase[]) => void;
|
|
16
|
+
rootViews: DynamicViewBase[];
|
|
17
|
+
searchQuery: string;
|
|
18
|
+
setSearchQuery: (searchQuery: string) => void;
|
|
19
|
+
}
|
|
20
|
+
interface RootViewProviderProps {
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Dynamically add or remove views on the root view.
|
|
25
|
+
* @param children
|
|
26
|
+
* @constructor
|
|
27
|
+
*/
|
|
28
|
+
export declare const RootViewProvider: React.FC<RootViewProviderProps>;
|
|
29
|
+
export declare const useRootView: () => RootViewContextType;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=RootViewContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RootViewContext.d.ts","sourceRoot":"","sources":["../src/RootViewContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAmE,MAAM,OAAO,CAAC;AAC1G,OAAO,EAAmB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE1D,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,UAAU,mBAAmB;IAC3B,WAAW,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C,sBAAsB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC/D,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IACvE,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;IACvF,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C;AAED,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,SAAS,CAAC;CACrB;AAGD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA+I5D,CAAC;AAIF,eAAO,MAAM,WAAW,QAAO,mBAM9B,CAAC"}
|