|
1 | 1 | /**
|
2 |
| - * Created by TinySymphony on 2017-01-03. |
| 2 | + * Created by TinySymphony on 2017-01-03. edited by Yonimdo at 2020-04-28 corona time |
3 | 3 | */
|
4 |
| - |
5 |
| -import React, {Component, PropTypes} from 'react'; |
6 |
| -import { |
7 |
| - View, |
8 |
| - Text, |
9 |
| - Image, |
10 |
| - Modal, |
11 |
| - ScrollView, |
12 |
| - TouchableHighlight |
13 |
| -} from 'react-native'; |
| 4 | +import React, { useState } from 'react'; |
| 5 | +import { View, Text, Image, Modal, ScrollView, StyleSheet, TouchableHighlight, Dimensions } from 'react-native'; |
14 | 6 | import Styles, {IMG} from './LabelSelectStyle';
|
15 | 7 |
|
16 |
| -class LabelSelect extends Component { |
17 |
| - addIcon = { |
18 |
| - uri: IMG.addIcon |
19 |
| - } |
20 |
| - static propTypes = { |
21 |
| - title: PropTypes.string, |
22 |
| - readOnly: PropTypes.bool, |
23 |
| - enable: PropTypes.bool, |
24 |
| - onConfirm: PropTypes.func, |
25 |
| - enableAddBtn: PropTypes.bool, |
26 |
| - confirmText: PropTypes.string, |
27 |
| - cancelText: PropTypes.string |
28 |
| - } |
29 |
| - static defaultProps = { |
30 |
| - style: {}, |
31 |
| - customStyle: {}, |
32 |
| - title: ' ', |
33 |
| - enable: true, |
34 |
| - readOnly: false, |
35 |
| - onConfirm: () => {}, |
36 |
| - enableAddBtn: true, |
37 |
| - confirmText: 'Confirm', |
38 |
| - cancelText: 'Cancel' |
39 |
| - } |
40 |
| - constructor(props) { |
41 |
| - super(props); |
42 |
| - // 初始状态 |
43 |
| - this.state = { |
44 |
| - isModalVisible: false |
45 |
| - }; |
46 |
| - this.selectedList = []; |
47 |
| - this.toggleSelect = this.toggleSelect.bind(this); |
48 |
| - this.cancelSelect = this.cancelSelect.bind(this); |
49 |
| - this.confirmSelect = this.confirmSelect.bind(this); |
50 |
| - this.openModal = this.openModal.bind(this); |
51 |
| - } |
52 |
| - setModalVisible(isVisible) { |
53 |
| - this.setState({isModalVisible: isVisible}); |
54 |
| - } |
55 |
| - cancelSelect() { |
56 |
| - this.selectedList = []; |
57 |
| - this.setModalVisible(false); |
58 |
| - } |
59 |
| - confirmSelect() { |
60 |
| - const {onConfirm} = this.props; |
61 |
| - onConfirm(this.selectedList); |
62 |
| - this.selectedList = []; |
63 |
| - this.cancelSelect(); |
64 |
| - } |
65 |
| - openModal() { |
66 |
| - if (!React.Children.toArray(this.props.children).filter(item => item.type === ModalItem).length) { |
67 |
| - // TODO |
68 |
| - } |
69 |
| - this.props.enable && !this.props.readOnly && this.setModalVisible(true); |
70 |
| - } |
71 |
| - toggleSelect(time) { |
72 |
| - let index = this.selectedList.findIndex(item => item === time); |
73 |
| - if (~index) {this.selectedList.splice(index, 1);} |
74 |
| - else {this.selectedList.push(time);} |
75 |
| - } |
76 |
| - render() { |
77 |
| - const { |
78 |
| - readOnly, |
79 |
| - enable, |
80 |
| - title, |
81 |
| - style, |
82 |
| - enableAddBtn, |
83 |
| - customStyle, |
84 |
| - confirmText, |
85 |
| - cancelText |
86 |
| - } = this.props; |
87 |
| - let selectedLabels = React.Children.toArray(this.props.children) |
88 |
| - .filter(item => item.type === Label) |
89 |
| - .map((child, index) => { |
90 |
| - return React.cloneElement(child, { |
91 |
| - enable: enable, |
92 |
| - readOnly: readOnly |
93 |
| - }); |
94 |
| - }); |
95 | 8 |
|
96 |
| - let modalItems = this.state.isModalVisible ? React.Children.toArray(this.props.children) |
97 |
| - .filter(item => item.type === ModalItem) |
98 |
| - .map((child, index) => { |
99 |
| - return React.cloneElement(child, { |
100 |
| - toggleSelect: this.toggleSelect |
101 |
| - }); |
102 |
| - }) : null; |
| 9 | +function LabelSelect(props) { |
| 10 | + const [isModalVisible, setIsModalVisible] = useState(false); |
| 11 | + const addIcon = { uri: IMG.addIcon } |
103 | 12 |
|
| 13 | + let tempSelected = [] |
| 14 | + |
| 15 | + props.options.map((option) => { |
| 16 | + option.isSelected = props.selectedOptions.includes(option); |
| 17 | + }); |
| 18 | + const toggleSelect = (data) => { |
| 19 | + // if(tempSelected.includes(data)) |
| 20 | + if (data.isSelected) { |
| 21 | + tempSelected.filter(d => { data.code == d.code }) |
| 22 | + } else { |
| 23 | + tempSelected.push(data); |
| 24 | + }; |
| 25 | + } |
104 | 26 | return (
|
105 |
| - <View style={[Styles.selectedView, style]}> |
106 |
| - {selectedLabels} |
107 |
| - {enable && !readOnly && enableAddBtn && |
108 |
| - <TouchableHighlight |
109 |
| - style={[Styles.selectedItem, Styles.addItem]} |
110 |
| - underlayColor="transparent" |
111 |
| - onPress={this.openModal}> |
112 |
| - <Image |
113 |
| - style={Styles.addIcon} |
114 |
| - source={this.addIcon} |
115 |
| - resizeMode="cover" |
116 |
| - /> |
117 |
| - </TouchableHighlight> |
118 |
| - } |
119 |
| - <Modal |
120 |
| - transparent={true} |
121 |
| - visible={this.state.isModalVisible} |
122 |
| - onRequestClose={() => {}}> |
123 |
| - <View style={{flex: 1}}> |
124 |
| - <TouchableHighlight |
125 |
| - style={Styles.modalMask} |
126 |
| - activeOpacity={1} |
127 |
| - underlayColor="#00000077" |
128 |
| - onPress={this.cancelSelect}> |
129 |
| - <View style={Styles.modalContainer}> |
130 |
| - <View style={[Styles.modal, customStyle.modal || {}]}> |
131 |
| - <View style={Styles.title}><Text style={Styles.titleText}>{title}</Text></View> |
132 |
| - <View style={Styles.scrollView}> |
133 |
| - <ScrollView> |
134 |
| - {modalItems} |
135 |
| - </ScrollView> |
136 |
| - </View> |
137 |
| - <View style={[Styles.buttonView, customStyle.buttonView || {}]}> |
138 |
| - <TouchableHighlight |
139 |
| - underlayColor="transparent" |
140 |
| - activeOpacity={0.8} |
141 |
| - onPress={this.cancelSelect}> |
142 |
| - <View style={[Styles.modalButton, customStyle.cancelButton || {}]}> |
143 |
| - <Text style={[Styles.buttonText, customStyle.cancelText || {}]}>{cancelText}</Text> |
144 |
| - </View> |
145 |
| - </TouchableHighlight> |
| 27 | + <View style={[Styles.selectedView]}> |
| 28 | + {props.selectedOptions.map((item) => ( |
| 29 | + <Label key={item.code} data={item} onCancel={()=>{props.onCancelItem}}>{item.title}</Label> |
| 30 | + ))} |
| 31 | + |
| 32 | + {!props.readOnly &&<TouchableHighlight |
| 33 | + style={[Styles.selectedItem, Styles.addItem]} |
| 34 | + underlayColor="transparent" |
| 35 | + onPress={() => setIsModalVisible(true)}> |
| 36 | + <Image |
| 37 | + style={Styles.addIcon} |
| 38 | + source={addIcon} |
| 39 | + resizeMode="cover" |
| 40 | + /> |
| 41 | + </TouchableHighlight>} |
| 42 | + {!props.readOnly && <Modal |
| 43 | + transparent={true} |
| 44 | + visible={isModalVisible} |
| 45 | + onRequestClose={() => { }}> |
| 46 | + <View style={{ flex: 1 }}> |
146 | 47 | <TouchableHighlight
|
147 |
| - underlayColor="transparent" |
148 |
| - activeOpacity={0.8} |
149 |
| - onPress={this.confirmSelect}> |
150 |
| - <View style={[Styles.modalButton, Styles.confirmButton, customStyle.confirmButton || {}]}> |
151 |
| - <Text style={[Styles.buttonText, customStyle.confirmText || {}]}>{confirmText}</Text> |
152 |
| - </View> |
| 48 | + style={Styles.modalMask} |
| 49 | + activeOpacity={1} |
| 50 | + underlayColor="#00000077" |
| 51 | + onPress={() => setIsModalVisible(false)}> |
| 52 | + <View style={Styles.modalContainer}> |
| 53 | + <View style={Styles.modal}> |
| 54 | + <View style={Styles.title}><Text style={Styles.titleText}>{props.title}</Text></View> |
| 55 | + <View style={Styles.scrollView}> |
| 56 | + <ScrollView> |
| 57 | + {props.options.map((item) => (<ModalItem key={item.key} |
| 58 | + isSelected={item.isSelected} data={item} toggleSelect={toggleSelect} > |
| 59 | + {item.title}</ModalItem>))} |
| 60 | + </ScrollView> |
| 61 | + </View> |
| 62 | + <View style={[Styles.buttonView]}> |
| 63 | + <TouchableHighlight |
| 64 | + underlayColor="transparent" |
| 65 | + activeOpacity={0.8} |
| 66 | + onPress={() => setIsModalVisible(false)}> |
| 67 | + <View style={[Styles.modalButton, props.cancelButton || {}]}> |
| 68 | + <Text style={[Styles.buttonText, props.cancelText || {}]}>Cancel</Text> |
| 69 | + </View> |
| 70 | + </TouchableHighlight> |
| 71 | + <TouchableHighlight |
| 72 | + underlayColor="transparent" |
| 73 | + activeOpacity={0.8} |
| 74 | + onPress={() => { |
| 75 | + setIsModalVisible(false) |
| 76 | + props.onConfirm(tempSelected); |
| 77 | + tempSelected = []; |
| 78 | + }}> |
| 79 | + <View style={[Styles.modalButton, Styles.confirmButton, props.confirmButton || {}]}> |
| 80 | + <Text style={[Styles.buttonText, props.confirmText || {}]}>Confirm</Text> |
| 81 | + </View> |
| 82 | + </TouchableHighlight> |
| 83 | + </View> |
| 84 | + </View> |
| 85 | + </View> |
153 | 86 | </TouchableHighlight>
|
154 |
| - </View> |
155 | 87 | </View>
|
156 |
| - </View> |
157 |
| - </TouchableHighlight> |
158 |
| - </View> |
159 |
| - </Modal> |
160 |
| - </View> |
| 88 | + </Modal>} |
| 89 | + </View> |
161 | 90 | );
|
162 |
| - } |
163 | 91 | }
|
164 | 92 |
|
165 |
| -class Label extends Component { |
166 |
| - closeIcon = { |
167 |
| - uri: IMG.closeIcon |
168 |
| - } |
169 |
| - static propTypes = { |
170 |
| - onCancel: PropTypes.func, |
171 |
| - readOnly: PropTypes.bool, |
172 |
| - enable: PropTypes.bool |
173 |
| - } |
174 |
| - static defaultProps = { |
175 |
| - onCancel: () => {}, |
176 |
| - enable: true, |
177 |
| - readOnly: false, |
178 |
| - customStyle: {} |
179 |
| - } |
180 |
| - constructor(props) { |
181 |
| - super(props); |
182 |
| - } |
183 |
| - render() { |
184 |
| - const {enable, readOnly, onCancel, customStyle} = this.props; |
| 93 | +function Label(props) { |
| 94 | + const closeIcon = { uri: IMG.closeIcon }; |
185 | 95 | return (
|
186 |
| - <View style={[Styles.selectedItem, !enable && Styles.disableColor]}> |
187 |
| - <Text style={[Styles.labelText, !enable && Styles.disableText, customStyle.text || {}]} |
188 |
| - numberOfLines={1} ellipsisMode="tail">{this.props.children}</Text> |
189 |
| - {enable && !readOnly && <TouchableHighlight |
190 |
| - style={Styles.closeContainer} |
191 |
| - underlayColor="transparent" |
192 |
| - activeOpacity={0.5} |
193 |
| - onPress={onCancel}> |
194 |
| - <View> |
195 |
| - <Image |
196 |
| - style={Styles.closeIcon} |
197 |
| - source={this.closeIcon} |
198 |
| - resizeMode="cover"/> |
199 |
| - </View> |
200 |
| - </TouchableHighlight>} |
201 |
| - </View> |
| 96 | + <View style={[Styles.selectedItem, !props.enable && Styles.disableColor]}> |
| 97 | + <Text style={[Styles.labelText, !props.enable && Styles.disableText || {}]} |
| 98 | + numberOfLines={1} > |
| 99 | + {props.children} |
| 100 | + </Text> |
| 101 | + {!props.readOnly && <TouchableHighlight |
| 102 | + style={Styles.closeContainer} |
| 103 | + underlayColor="transparent" |
| 104 | + activeOpacity={0.5} |
| 105 | + onPress={()=>{props.onCancel(props.data)}}> |
| 106 | + <View> |
| 107 | + <Image |
| 108 | + style={Styles.closeIcon} |
| 109 | + source={closeIcon} |
| 110 | + resizeMode="cover" /> |
| 111 | + </View> |
| 112 | + </TouchableHighlight>} |
| 113 | + </View> |
202 | 114 | );
|
203 |
| - } |
204 | 115 | }
|
205 | 116 |
|
206 |
| -class ModalItem extends Component { |
207 |
| - static propTypes = { |
208 |
| - toggleSelect: PropTypes.func |
209 |
| - } |
210 |
| - static defaultProps = { |
211 |
| - customStyle: {} |
212 |
| - } |
213 |
| - constructor (props) { |
214 |
| - super(props); |
215 |
| - this.isSelected = false; |
216 |
| - this._toggleSelect = this._toggleSelect.bind(this); |
217 |
| - } |
218 |
| - _toggleSelect() { |
219 |
| - const {toggleSelect, data} = this.props; |
220 |
| - this.isSelected = !this.isSelected; |
221 |
| - this.forceUpdate(); |
222 |
| - toggleSelect(data); |
223 |
| - } |
224 |
| - render () { |
225 |
| - const { |
226 |
| - customStyle |
227 |
| - } = this.props; |
| 117 | +function ModalItem(props) { |
| 118 | + const [isSelected, setIsSelected] = useState(props.isSelected); |
228 | 119 | return (
|
229 |
| - <TouchableHighlight |
230 |
| - activeOpacity={0.5} |
231 |
| - underlayColor="transparent" |
232 |
| - onPress={this._toggleSelect}> |
233 |
| - <View style={Styles.modalItem}> |
234 |
| - <Text |
235 |
| - style={[Styles.modalText, customStyle.modalText || {}]} |
236 |
| - numberOfLines={1} |
237 |
| - ellipsisMode="tail"> |
238 |
| - {this.props.children} |
239 |
| - </Text> |
240 |
| - <View style={[Styles.outerCircle, this.isSelected ? Styles.enableCircle : {}, customStyle.outerCircle || {}]}> |
241 |
| - {this.isSelected && <View style={[Styles.innerCircle, customStyle.innerCircle || {}]}/>} |
242 |
| - </View> |
243 |
| - </View> |
244 |
| - </TouchableHighlight> |
| 120 | + <TouchableHighlight |
| 121 | + activeOpacity={0.5} |
| 122 | + underlayColor="transparent" |
| 123 | + onPress={() => { |
| 124 | + setIsSelected(!isSelected); |
| 125 | + props.toggleSelect(props.data); |
| 126 | + }}> |
| 127 | + <View style={Styles.modalItem}> |
| 128 | + <Text |
| 129 | + style={[Styles.modalText]} |
| 130 | + numberOfLines={1}> |
| 131 | + {props.children} |
| 132 | + </Text> |
| 133 | + <View style={[Styles.outerCircle, isSelected ? Styles.enableCircle : {}]}> |
| 134 | + {isSelected && <View style={[Styles.innerCircle]} />} |
| 135 | + </View> |
| 136 | + </View> |
| 137 | + </TouchableHighlight> |
245 | 138 | );
|
246 |
| - } |
247 | 139 | }
|
248 | 140 |
|
249 |
| -LabelSelect.Label = Label; |
250 |
| -LabelSelect.ModalItem = ModalItem; |
251 |
| - |
252 | 141 | export default LabelSelect;
|
0 commit comments