@uiw/react-native
Version:
UIW for React Native
165 lines (163 loc) • 4.8 kB
JavaScript
import React, { useState, useEffect, memo } from 'react';
import { View, SafeAreaView, StyleSheet, TouchableWithoutFeedback, ActivityIndicator, Pressable } from 'react-native';
import MaskLayer from '../MaskLayer';
import SearchInputBar from '../SearchInputBar';
import List from '../List';
import Icon from '../Icon';
import Text from '../Typography/Text';
import { useTheme } from '@shopify/restyle';
// 搜索组件
function SearchBar({
onChangeText,
options = [],
onChange,
labelInValue,
disabled,
value,
onFocus,
onBlur,
loading,
placeholder,
extra,
showClear = true,
contentStyle = {},
placeholderColor,
...searchInputBarProps
}) {
const theme = useTheme();
const styles = createStyles({
maskBgColor: theme.colors.mask || '#F5F5F5',
bgColor: theme.colors.background || '#F5F5F5',
disabledColor: theme.colors.disabled || '#F5F5F5',
iconColor: theme.colors.primary_text || '#fff',
cancelColor: theme.colors.primary_text || '#7C7D7E'
});
const [curValue, setCurValue] = useState(value);
const [visible, setVisivble] = useState(false);
let textValue;
if (labelInValue) {
textValue = curValue?.label;
} else {
const {
label
} = options.find(item => item.value === curValue);
textValue = label;
}
useEffect(() => {
setCurValue(value);
}, [value]);
// 搜索
const onHandleChangeText = val => {
onChangeText && onChangeText(val);
};
// 点击打开遮罩层
const showSearchBar = () => {
if (disabled) {
return;
}
setVisivble(true);
};
const placeholderStyle = placeholderColor ? {
color: placeholderColor
} : {};
return !visible ? <Pressable onPress={showSearchBar}>
<View style={[disabled ? styles.disabled : styles.content, contentStyle]}>
<Text color="text" style={{
fontSize: 16,
...placeholderStyle
}}>
{textValue ? textValue : placeholder}
</Text>
{React.isValidElement(extra) ? extra : curValue && showClear ? <Pressable onPress={() => {
onChange && onChange(null);
setCurValue(null);
}} style={{
paddingRight: 3
}}>
<Icon name="circle-close-o" size={18} color={theme.colors.primary_text || '#ccc'} />
</Pressable> : <Icon name="right" size={18} color={theme.colors.primary_text || '#A19EA0'} />}
</View>
</Pressable> : <MaskLayer visible={visible}>
<SafeAreaView style={styles.container}>
<SearchInputBar loading={loading} containerStyle={{
marginHorizontal: 10
}} autoFocus showActionButton placeholder="输入搜索..." onChangeText={onHandleChangeText} onFocus={onFocus && onFocus} onBlur={onBlur && onBlur} searchRender={<TouchableWithoutFeedback onPress={() => {
setVisivble(false);
}}>
<View style={styles.cancel}>
<Text color="primary_background">取消</Text>
</View>
</TouchableWithoutFeedback>} {...searchInputBarProps} />
{loading ? <ActivityIndicator color={theme.colors.primary_background || '#0A0258'} size="large" style={styles.loading} /> : <List style={styles.list}>
{options.map(itm => <List.Item key={itm.value} onPress={() => {
const selectValue = labelInValue ? {
key: itm.value,
label: itm.label
} : itm.value;
onChange && onChange(selectValue);
setCurValue(selectValue);
setVisivble(false);
}}>
<Text color="primary_text" style={{
fontSize: 16
}}>
{itm.label}
</Text>
</List.Item>)}
</List>}
</SafeAreaView>
</MaskLayer>;
}
export default memo(SearchBar);
function createStyles({
maskBgColor,
bgColor,
disabledColor,
iconColor,
cancelColor
}) {
return StyleSheet.create({
container: {
flex: 1,
backgroundColor: bgColor
},
icon: {
backgroundColor: iconColor,
paddingLeft: 10,
justifyContent: 'center'
},
cancel: {
color: cancelColor,
paddingRight: 10,
justifyContent: 'center'
},
list: {
marginLeft: 10,
marginTop: 10,
marginRight: 10
},
loading: {
position: 'absolute',
top: '20%',
left: '45%'
},
content: {
flexDirection: 'row',
height: 35,
alignItems: 'center',
justifyContent: 'space-between',
paddingRight: 5,
backgroundColor: maskBgColor,
paddingHorizontal: 16
},
disabled: {
flexDirection: 'row',
height: 35,
alignItems: 'center',
justifyContent: 'space-between',
paddingRight: 5,
backgroundColor: disabledColor,
paddingHorizontal: 16
}
});
}