Dropdown.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import React, { useEffect, useRef, useState } from 'react';
  2. import { FlatList, Keyboard, Pressable, StyleSheet, Text, View } from 'react-native';
  3. import Modal from 'react-native-modal';
  4. import Button from './Button';
  5. import Dialog, { getDialogWidth } from './Dialog';
  6. //const DialogMaxWidth = $vw(85) > 500 ? 500 : $vw(85);
  7. //const DialogIOSWidth = $vw(75) > 450 ? 450 : $vw(75);
  8. export default Dropdown = ({
  9. list = [],
  10. title = '',
  11. value,
  12. onChange,
  13. nameKey,
  14. valueKey,
  15. extraText='',
  16. itemHeight=50,
  17. rippleStyle,
  18. style = styles.valueView,
  19. textStyle = styles.valueText,
  20. placeholderStyle=styles.placeText,
  21. placeholder='',
  22. showIcon = true,
  23. iconColor = '#888',
  24. iconStyle = styles.iconStyle,
  25. autoSelect = true,
  26. customerItemView
  27. }) => {
  28. const refFlat = useRef();
  29. const [visible, showDialog] = useState(false);
  30. const [selected, changeValue] = useState('');
  31. const [currentIndex, setCurrent] = useState(0);
  32. useEffect(() => {
  33. if (value !== selected) {
  34. if (nameKey && valueKey) {
  35. for (var i = 0; i < list.length; i++) {
  36. let item = list[i];
  37. if (item[valueKey] == value) {
  38. changeValue(extraText+item[nameKey]);
  39. if (list.length > 20) {
  40. setCurrent(i > 5 ? i - 4 : 0);
  41. }
  42. break;
  43. }
  44. }
  45. } else {
  46. changeValue(extraText+value);
  47. }
  48. }
  49. }, [value, []]);
  50. useEffect(() => {
  51. if (autoSelect && list.length > 0) {
  52. if (!value) {
  53. const item = list[0];
  54. /*if (nameKey) {
  55. changeValue(item[nameKey]);
  56. } else {
  57. changeValue(item);
  58. }*/
  59. if (onChange) {
  60. onChange(valueKey ? item[valueKey] : item, 0)
  61. }
  62. }
  63. }
  64. }, [list]);
  65. const showList = () => {
  66. Keyboard.dismiss();
  67. showDialog(true);
  68. /*if (currentIndex > 0) {
  69. console.log(refFlat.current);
  70. setTimeout(() => {
  71. if (refFlat.current) {
  72. refFlat.current.scrollToIndex({
  73. animated: false,
  74. index: currentIndex,
  75. viewPosition: 0.5
  76. })
  77. }
  78. }, 100)
  79. }*/
  80. }
  81. const renderItem = ({ item, index, separators }) => {
  82. if (customerItemView) {
  83. return customerItemView(item, index, () => {
  84. showDialog(false);
  85. if (onChange) {
  86. onChange(valueKey ? item[valueKey] : item, index)
  87. }
  88. })
  89. } else {
  90. return (
  91. <Button
  92. text={nameKey ? item[nameKey] : item}
  93. style={styles.itemView}
  94. textStyle={styles.itemText}
  95. onClick={() => {
  96. showDialog(false);
  97. if (onChange) {
  98. onChange(valueKey ? item[valueKey] : item, index)
  99. }
  100. }
  101. }/>
  102. )
  103. }
  104. }
  105. return (
  106. <>
  107. <Pressable
  108. style={style}
  109. android_ripple={rippleStyle}
  110. onPress={() => showList()}>
  111. { selected
  112. ? <Text style={[ui.flex1, textStyle]} numberOfLines={1}>{selected}</Text>
  113. : <Text style={[textStyle, placeholderStyle]} numberOfLines={1}>{placeholder}</Text>
  114. }
  115. { showIcon &&
  116. <Entypo
  117. name={'chevron-thin-down'}
  118. size={14}
  119. color={iconColor}
  120. style={iconStyle}
  121. />
  122. }
  123. </Pressable>
  124. <Modal
  125. isVisible={visible}
  126. onTouchOutside={() => showDialog(false)}
  127. onBackdropPress={() => showDialog(false)}
  128. onBackButtonPress={() => showDialog(false)}
  129. {...Dialog.modalProps}
  130. >
  131. <View style={styles.dialog}>
  132. { title !== '' && <Text style={styles.title}>{title}</Text> }
  133. <FlatList
  134. data={list}
  135. ref={refFlat}
  136. renderItem={renderItem}
  137. initialScrollIndex={currentIndex}
  138. keyExtractor={(item, index) => index}
  139. style={{maxHeight: $vh(55)}}
  140. getItemLayout={(data, index) => (
  141. {length: itemHeight, offset: itemHeight * index, index}
  142. )}
  143. />
  144. </View>
  145. </Modal>
  146. </>
  147. );
  148. }
  149. const styles = StyleSheet.create({
  150. dialog: {
  151. width: getDialogWidth(),
  152. marginLeft: 'auto',
  153. marginRight: 'auto',
  154. paddingTop: isIOS ? 12 : 8,
  155. paddingBottom: isIOS ? 12 : 8,
  156. backgroundColor: 'white',
  157. borderRadius: isIOS ? 10 : 3
  158. },
  159. title: {
  160. color: '#000',
  161. paddingTop: 8,
  162. paddingLeft: 16,
  163. paddingBottom: 16,
  164. fontSize: 17,
  165. fontWeight: 'bold'
  166. },
  167. valueView: {
  168. paddingLeft: 16,
  169. paddingRight: 32,
  170. alignItems: 'center',
  171. flexDirection: 'row'
  172. },
  173. valueText: {
  174. color: '#000',
  175. fontSize: 16
  176. },
  177. itemView: {
  178. borderRadius: 0,
  179. backgroundColor: 'white'
  180. },
  181. itemText: {
  182. flex: 1,
  183. color: '#333',
  184. fontSize: 14,
  185. textAlign: 'left',
  186. fontWeight: 'normal'
  187. },
  188. placeText: {
  189. flex: 1,
  190. color: '#aaa'
  191. },
  192. iconStyle: {
  193. top: '50%',
  194. right: 16,
  195. marginTop: -7,
  196. position: 'absolute',
  197. }
  198. });