diff options
Diffstat (limited to 'src/module')
-rw-r--r-- | src/module/Combobox.jsx | 141 | ||||
-rw-r--r-- | src/module/Header.jsx | 204 | ||||
-rw-r--r-- | src/module/Panel.jsx | 130 | ||||
-rw-r--r-- | src/module/Select.jsx | 97 |
4 files changed, 0 insertions, 572 deletions
diff --git a/src/module/Combobox.jsx b/src/module/Combobox.jsx deleted file mode 100644 index f1e7c5b..0000000 --- a/src/module/Combobox.jsx +++ /dev/null | |||
@@ -1,141 +0,0 @@ | |||
1 | import React, {PropTypes} from 'react'; | ||
2 | import Select from './Select'; | ||
3 | import GregorianCalendar from 'gregorian-calendar'; | ||
4 | |||
5 | const formatOption = (option, disabledOptions) => { | ||
6 | let value = `${option}`; | ||
7 | if (option < 10) { | ||
8 | value = `0${option}`; | ||
9 | } | ||
10 | |||
11 | let disabled = false; | ||
12 | if (disabledOptions && disabledOptions.indexOf(option) >= 0) { | ||
13 | disabled = true; | ||
14 | } | ||
15 | |||
16 | return { | ||
17 | value, | ||
18 | disabled, | ||
19 | }; | ||
20 | }; | ||
21 | |||
22 | const Combobox = React.createClass({ | ||
23 | propTypes: { | ||
24 | formatter: PropTypes.object, | ||
25 | prefixCls: PropTypes.string, | ||
26 | value: PropTypes.object, | ||
27 | onChange: PropTypes.func, | ||
28 | showHour: PropTypes.bool, | ||
29 | gregorianCalendarLocale: PropTypes.object, | ||
30 | showSecond: PropTypes.bool, | ||
31 | hourOptions: PropTypes.array, | ||
32 | minuteOptions: PropTypes.array, | ||
33 | secondOptions: PropTypes.array, | ||
34 | disabledHours: PropTypes.func, | ||
35 | disabledMinutes: PropTypes.func, | ||
36 | disabledSeconds: PropTypes.func, | ||
37 | onCurrentSelectPanelChange: PropTypes.func, | ||
38 | }, | ||
39 | |||
40 | onItemChange(type, itemValue) { | ||
41 | const { onChange } = this.props; | ||
42 | let value = this.props.value; | ||
43 | if (value) { | ||
44 | value = value.clone(); | ||
45 | } else { | ||
46 | value = this.getNow().clone(); | ||
47 | } | ||
48 | if (type === 'hour') { | ||
49 | value.setHourOfDay(itemValue); | ||
50 | } else if (type === 'minute') { | ||
51 | value.setMinutes(itemValue); | ||
52 | } else { | ||
53 | value.setSeconds(itemValue); | ||
54 | } | ||
55 | onChange(value); | ||
56 | }, | ||
57 | |||
58 | onEnterSelectPanel(range) { | ||
59 | this.props.onCurrentSelectPanelChange(range); | ||
60 | }, | ||
61 | |||
62 | getHourSelect(hour) { | ||
63 | const { prefixCls, hourOptions, disabledHours, showHour } = this.props; | ||
64 | if (!showHour) { | ||
65 | return null; | ||
66 | } | ||
67 | const disabledOptions = disabledHours(); | ||
68 | |||
69 | return ( | ||
70 | <Select | ||
71 | prefixCls={prefixCls} | ||
72 | options={hourOptions.map(option => formatOption(option, disabledOptions))} | ||
73 | selectedIndex={hourOptions.indexOf(hour)} | ||
74 | type="hour" | ||
75 | onSelect={this.onItemChange} | ||
76 | onMouseEnter={this.onEnterSelectPanel.bind(this, 'hour')} | ||
77 | /> | ||
78 | ); | ||
79 | }, | ||
80 | |||
81 | getMinuteSelect(minute) { | ||
82 | const { prefixCls, minuteOptions, disabledMinutes } = this.props; | ||
83 | const value = this.props.value || this.getNow(); | ||
84 | const disabledOptions = disabledMinutes(value.getHourOfDay()); | ||
85 | |||
86 | return ( | ||
87 | <Select | ||
88 | prefixCls={prefixCls} | ||
89 | options={minuteOptions.map(option => formatOption(option, disabledOptions))} | ||
90 | selectedIndex={minuteOptions.indexOf(minute)} | ||
91 | type="minute" | ||
92 | onSelect={this.onItemChange} | ||
93 | onMouseEnter={this.onEnterSelectPanel.bind(this, 'minute')} | ||
94 | /> | ||
95 | ); | ||
96 | }, | ||
97 | |||
98 | getSecondSelect(second) { | ||
99 | const { prefixCls, secondOptions, disabledSeconds, showSecond } = this.props; | ||
100 | if (!showSecond) { | ||
101 | return null; | ||
102 | } | ||
103 | const value = this.props.value || this.getNow(); | ||
104 | const disabledOptions = disabledSeconds(value.getHourOfDay(), value.getMinutes()); | ||
105 | |||
106 | return ( | ||
107 | <Select | ||
108 | prefixCls={prefixCls} | ||
109 | options={secondOptions.map(option => formatOption(option, disabledOptions))} | ||
110 | selectedIndex={secondOptions.indexOf(second)} | ||
111 | type="second" | ||
112 | onSelect={this.onItemChange} | ||
113 | onMouseEnter={this.onEnterSelectPanel.bind(this, 'second')} | ||
114 | /> | ||
115 | ); | ||
116 | }, | ||
117 | |||
118 | getNow() { | ||
119 | if (this.showNow) { | ||
120 | return this.showNow; | ||
121 | } | ||
122 | const value = new GregorianCalendar(this.props.gregorianCalendarLocale); | ||
123 | value.setTime(Date.now()); | ||
124 | this.showNow = value; | ||
125 | return value; | ||
126 | }, | ||
127 | |||
128 | render() { | ||
129 | const { prefixCls } = this.props; | ||
130 | const value = this.props.value || this.getNow(); | ||
131 | return ( | ||
132 | <div className={`${prefixCls}-combobox`}> | ||
133 | {this.getHourSelect(value.getHourOfDay())} | ||
134 | {this.getMinuteSelect(value.getMinutes())} | ||
135 | {this.getSecondSelect(value.getSeconds())} | ||
136 | </div> | ||
137 | ); | ||
138 | }, | ||
139 | }); | ||
140 | |||
141 | export default Combobox; | ||
diff --git a/src/module/Header.jsx b/src/module/Header.jsx deleted file mode 100644 index a926e98..0000000 --- a/src/module/Header.jsx +++ /dev/null | |||
@@ -1,204 +0,0 @@ | |||
1 | import React, { PropTypes } from 'react'; | ||
2 | import createSelection from '../util/selection'; | ||
3 | |||
4 | const Header = React.createClass({ | ||
5 | propTypes: { | ||
6 | formatter: PropTypes.object, | ||
7 | prefixCls: PropTypes.string, | ||
8 | gregorianCalendarLocale: PropTypes.object, | ||
9 | locale: PropTypes.object, | ||
10 | disabledDate: PropTypes.func, | ||
11 | placeholder: PropTypes.string, | ||
12 | value: PropTypes.object, | ||
13 | hourOptions: PropTypes.array, | ||
14 | minuteOptions: PropTypes.array, | ||
15 | secondOptions: PropTypes.array, | ||
16 | disabledHours: PropTypes.func, | ||
17 | disabledMinutes: PropTypes.func, | ||
18 | disabledSeconds: PropTypes.func, | ||
19 | onChange: PropTypes.func, | ||
20 | onClear: PropTypes.func, | ||
21 | onEsc: PropTypes.func, | ||
22 | allowEmpty: PropTypes.bool, | ||
23 | currentSelectPanel: PropTypes.string, | ||
24 | }, | ||
25 | |||
26 | getInitialState() { | ||
27 | const value = this.props.value; | ||
28 | return { | ||
29 | str: value && this.props.formatter.format(value) || '', | ||
30 | invalid: false, | ||
31 | }; | ||
32 | }, | ||
33 | |||
34 | componentDidMount() { | ||
35 | this.timer = setTimeout(this.selectRange, 0); | ||
36 | }, | ||
37 | |||
38 | componentWillReceiveProps(nextProps) { | ||
39 | const value = nextProps.value; | ||
40 | this.setState({ | ||
41 | str: value && nextProps.formatter.format(value) || '', | ||
42 | invalid: false, | ||
43 | }); | ||
44 | }, | ||
45 | |||
46 | componentDidUpdate() { | ||
47 | this.timer = setTimeout(this.selectRange, 0); | ||
48 | }, | ||
49 | |||
50 | componentWillUnmount() { | ||
51 | clearTimeout(this.timer); | ||
52 | }, | ||
53 | |||
54 | onInputChange(event) { | ||
55 | const str = event.target.value; | ||
56 | this.setState({ | ||
57 | str, | ||
58 | }); | ||
59 | let value = null; | ||
60 | const { formatter, gregorianCalendarLocale, hourOptions, minuteOptions, secondOptions, disabledHours, disabledMinutes, disabledSeconds, onChange, allowEmpty } = this.props; | ||
61 | |||
62 | if (str) { | ||
63 | const originalValue = this.props.value; | ||
64 | try { | ||
65 | value = formatter.parse(str, { | ||
66 | locale: gregorianCalendarLocale, | ||
67 | obeyCount: true, | ||
68 | }); | ||
69 | } catch (ex) { | ||
70 | this.setState({ | ||
71 | invalid: true, | ||
72 | }); | ||
73 | return; | ||
74 | } | ||
75 | |||
76 | if (value) { | ||
77 | // if time value not allowed, response warning. | ||
78 | if ( | ||
79 | hourOptions.indexOf(value.getHourOfDay()) < 0 || | ||
80 | minuteOptions.indexOf(value.getMinutes()) < 0 || | ||
81 | secondOptions.indexOf(value.getSeconds()) < 0 | ||
82 | ) { | ||
83 | this.setState({ | ||
84 | invalid: true, | ||
85 | }); | ||
86 | return; | ||
87 | } | ||
88 | |||
89 | // if time value is disabled, response warning. | ||
90 | const disabledHourOptions = disabledHours(); | ||
91 | const disabledMinuteOptions = disabledMinutes(value.getHourOfDay()); | ||
92 | const disabledSecondOptions = disabledSeconds(value.getHourOfDay(), value.getMinutes()); | ||
93 | if ( | ||
94 | (disabledHourOptions && disabledHourOptions.indexOf(value.getHourOfDay()) >= 0) || | ||
95 | (disabledMinuteOptions && disabledMinuteOptions.indexOf(value.getMinutes()) >= 0) || | ||
96 | (disabledSecondOptions && disabledSecondOptions.indexOf(value.getSeconds()) >= 0) | ||
97 | ) { | ||
98 | this.setState({ | ||
99 | invalid: true, | ||
100 | }); | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | if (originalValue && value) { | ||
105 | if ( | ||
106 | originalValue.getHourOfDay() !== value.getHourOfDay() || | ||
107 | originalValue.getMinutes() !== value.getMinutes() || | ||
108 | originalValue.getSeconds() !== value.getSeconds() | ||
109 | ) { | ||
110 | // keep other fields for rc-calendar | ||
111 | const changedValue = originalValue.clone(); | ||
112 | changedValue.setHourOfDay(value.getHourOfDay()); | ||
113 | changedValue.setMinutes(value.getMinutes()); | ||
114 | changedValue.setSeconds(value.getSeconds()); | ||
115 | onChange(changedValue); | ||
116 | } | ||
117 | } else if (originalValue !== value) { | ||
118 | onChange(value); | ||
119 | } | ||
120 | } else { | ||
121 | this.setState({ | ||
122 | invalid: true, | ||
123 | }); | ||
124 | return; | ||
125 | } | ||
126 | } else if (allowEmpty) { | ||
127 | onChange(null); | ||
128 | } else { | ||
129 | this.setState({ | ||
130 | invalid: true, | ||
131 | }); | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | this.setState({ | ||
136 | invalid: false, | ||
137 | }); | ||
138 | }, | ||
139 | |||
140 | onKeyDown(e) { | ||
141 | if (e.keyCode === 27) { | ||
142 | this.props.onEsc(); | ||
143 | } | ||
144 | }, | ||
145 | |||
146 | onClear() { | ||
147 | this.setState({ str: '' }); | ||
148 | this.props.onClear(); | ||
149 | }, | ||
150 | |||
151 | getClearButton() { | ||
152 | const { locale, prefixCls, allowEmpty } = this.props; | ||
153 | if (!allowEmpty) { | ||
154 | return null; | ||
155 | } | ||
156 | return <a className={`${prefixCls}-clear-btn`} role="button" title={locale.clear} onMouseDown={this.onClear}/>; | ||
157 | }, | ||
158 | |||
159 | getInput() { | ||
160 | const { prefixCls, placeholder } = this.props; | ||
161 | const { invalid, str } = this.state; | ||
162 | const invalidClass = invalid ? `${prefixCls}-input-invalid` : ''; | ||
163 | return (<input | ||
164 | className={`${prefixCls}-input ${invalidClass}`} | ||
165 | ref="input" | ||
166 | onKeyDown={this.onKeyDown} | ||
167 | value={str} | ||
168 | placeholder={placeholder} onChange={this.onInputChange} | ||
169 | />); | ||
170 | }, | ||
171 | |||
172 | selectRange() { | ||
173 | this.refs.input.select(); | ||
174 | if (this.props.currentSelectPanel && this.refs.input.value) { | ||
175 | let selectionRangeStart = 0; | ||
176 | let selectionRangeEnd = 0; | ||
177 | if (this.props.currentSelectPanel === 'hour') { | ||
178 | selectionRangeStart = 0; | ||
179 | selectionRangeEnd = this.refs.input.value.indexOf(':'); | ||
180 | } else if (this.props.currentSelectPanel === 'minute') { | ||
181 | selectionRangeStart = this.refs.input.value.indexOf(':') + 1; | ||
182 | selectionRangeEnd = this.refs.input.value.lastIndexOf(':'); | ||
183 | } else if (this.props.currentSelectPanel === 'second') { | ||
184 | selectionRangeStart = this.refs.input.value.lastIndexOf(':') + 1; | ||
185 | selectionRangeEnd = this.refs.input.value.length; | ||
186 | } | ||
187 | if (selectionRangeEnd - selectionRangeStart === 2) { | ||
188 | createSelection(this.refs.input, selectionRangeStart, selectionRangeEnd); | ||
189 | } | ||
190 | } | ||
191 | }, | ||
192 | |||
193 | render() { | ||
194 | const { prefixCls } = this.props; | ||
195 | return ( | ||
196 | <div className={`${prefixCls}-input-wrap`}> | ||
197 | {this.getInput()} | ||
198 | {this.getClearButton()} | ||
199 | </div> | ||
200 | ); | ||
201 | }, | ||
202 | }); | ||
203 | |||
204 | export default Header; | ||
diff --git a/src/module/Panel.jsx b/src/module/Panel.jsx deleted file mode 100644 index 137ec2f..0000000 --- a/src/module/Panel.jsx +++ /dev/null | |||
@@ -1,130 +0,0 @@ | |||
1 | import React, {PropTypes} from 'react'; | ||
2 | import CommonMixin from '../mixin/CommonMixin'; | ||
3 | import Header from './Header'; | ||
4 | import Combobox from './Combobox'; | ||
5 | |||
6 | function noop() { | ||
7 | } | ||
8 | |||
9 | function generateOptions(length, disabledOptions, hideDisabledOptions) { | ||
10 | const arr = []; | ||
11 | for (let value = 0; value < length; value++) { | ||
12 | if (!disabledOptions || disabledOptions.indexOf(value) < 0 || !hideDisabledOptions) { | ||
13 | arr.push(value); | ||
14 | } | ||
15 | } | ||
16 | return arr; | ||
17 | } | ||
18 | |||
19 | const Panel = React.createClass({ | ||
20 | propTypes: { | ||
21 | prefixCls: PropTypes.string, | ||
22 | value: PropTypes.object, | ||
23 | locale: PropTypes.object, | ||
24 | placeholder: PropTypes.string, | ||
25 | gregorianCalendarLocale: PropTypes.object, | ||
26 | formatter: PropTypes.object, | ||
27 | disabledHours: PropTypes.func, | ||
28 | disabledMinutes: PropTypes.func, | ||
29 | disabledSeconds: PropTypes.func, | ||
30 | hideDisabledOptions: PropTypes.bool, | ||
31 | onChange: PropTypes.func, | ||
32 | onEsc: PropTypes.func, | ||
33 | allowEmpty: PropTypes.bool, | ||
34 | showHour: PropTypes.bool, | ||
35 | showSecond: PropTypes.bool, | ||
36 | onClear: PropTypes.func, | ||
37 | }, | ||
38 | |||
39 | mixins: [CommonMixin], | ||
40 | |||
41 | getDefaultProps() { | ||
42 | return { | ||
43 | prefixCls: 'rc-time-picker-panel', | ||
44 | onChange: noop, | ||
45 | onClear: noop, | ||
46 | }; | ||
47 | }, | ||
48 | |||
49 | getInitialState() { | ||
50 | return { | ||
51 | value: this.props.value, | ||
52 | selectionRange: [], | ||
53 | }; | ||
54 | }, | ||
55 | |||
56 | componentWillReceiveProps(nextProps) { | ||
57 | const value = nextProps.value; | ||
58 | if (value) { | ||
59 | this.setState({ | ||
60 | value, | ||
61 | }); | ||
62 | } | ||
63 | }, | ||
64 | |||
65 | onChange(newValue) { | ||
66 | this.setState({ value: newValue }); | ||
67 | this.props.onChange(newValue); | ||
68 | }, | ||
69 | |||
70 | onClear() { | ||
71 | this.props.onClear(); | ||
72 | }, | ||
73 | |||
74 | onCurrentSelectPanelChange(currentSelectPanel) { | ||
75 | this.setState({ currentSelectPanel }); | ||
76 | }, | ||
77 | |||
78 | render() { | ||
79 | const { locale, prefixCls, placeholder, disabledHours, disabledMinutes, disabledSeconds, hideDisabledOptions, allowEmpty, showHour, showSecond, formatter, gregorianCalendarLocale } = this.props; | ||
80 | const value = this.state.value; | ||
81 | const disabledHourOptions = disabledHours(); | ||
82 | const disabledMinuteOptions = disabledMinutes(value ? value.getHourOfDay() : null); | ||
83 | const disabledSecondOptions = disabledSeconds(value ? value.getHourOfDay() : null, value ? value.getMinutes() : null); | ||
84 | const hourOptions = generateOptions(24, disabledHourOptions, hideDisabledOptions); | ||
85 | const minuteOptions = generateOptions(60, disabledMinuteOptions, hideDisabledOptions); | ||
86 | const secondOptions = generateOptions(60, disabledSecondOptions, hideDisabledOptions); | ||
87 | |||
88 | return ( | ||
89 | <div className={`${prefixCls}-inner`}> | ||
90 | <Header | ||
91 | prefixCls={prefixCls} | ||
92 | gregorianCalendarLocale={gregorianCalendarLocale} | ||
93 | locale={locale} | ||
94 | value={value} | ||
95 | currentSelectPanel={this.state.currentSelectPanel} | ||
96 | onEsc={this.props.onEsc} | ||
97 | formatter={formatter} | ||
98 | placeholder={placeholder} | ||
99 | hourOptions={hourOptions} | ||
100 | minuteOptions={minuteOptions} | ||
101 | secondOptions={secondOptions} | ||
102 | disabledHours={disabledHours} | ||
103 | disabledMinutes={disabledMinutes} | ||
104 | disabledSeconds={disabledSeconds} | ||
105 | onChange={this.onChange} | ||
106 | onClear={this.onClear} | ||
107 | allowEmpty={allowEmpty} | ||
108 | /> | ||
109 | <Combobox | ||
110 | prefixCls={prefixCls} | ||
111 | value={value} | ||
112 | gregorianCalendarLocale={gregorianCalendarLocale} | ||
113 | formatter={formatter} | ||
114 | onChange={this.onChange} | ||
115 | showHour={showHour} | ||
116 | showSecond={showSecond} | ||
117 | hourOptions={hourOptions} | ||
118 | minuteOptions={minuteOptions} | ||
119 | secondOptions={secondOptions} | ||
120 | disabledHours={disabledHours} | ||
121 | disabledMinutes={disabledMinutes} | ||
122 | disabledSeconds={disabledSeconds} | ||
123 | onCurrentSelectPanelChange={this.onCurrentSelectPanelChange} | ||
124 | /> | ||
125 | </div> | ||
126 | ); | ||
127 | }, | ||
128 | }); | ||
129 | |||
130 | export default Panel; | ||
diff --git a/src/module/Select.jsx b/src/module/Select.jsx deleted file mode 100644 index 2ab9e61..0000000 --- a/src/module/Select.jsx +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | import React, {PropTypes} from 'react'; | ||
2 | import ReactDom from 'react-dom'; | ||
3 | import classnames from 'classnames'; | ||
4 | |||
5 | const scrollTo = (element, to, duration) => { | ||
6 | const requestAnimationFrame = window.requestAnimationFrame || | ||
7 | function requestAnimationFrameTimeout() { | ||
8 | return setTimeout(arguments[0], 10); | ||
9 | }; | ||
10 | // jump to target if duration zero | ||
11 | if (duration <= 0) { | ||
12 | element.scrollTop = to; | ||
13 | return; | ||
14 | } | ||
15 | const difference = to - element.scrollTop; | ||
16 | const perTick = difference / duration * 10; | ||
17 | |||
18 | requestAnimationFrame(() => { | ||
19 | element.scrollTop = element.scrollTop + perTick; | ||
20 | if (element.scrollTop === to) return; | ||
21 | scrollTo(element, to, duration - 10); | ||
22 | }); | ||
23 | }; | ||
24 | |||
25 | const Select = React.createClass({ | ||
26 | propTypes: { | ||
27 | prefixCls: PropTypes.string, | ||
28 | options: PropTypes.array, | ||
29 | gregorianCalendarLocale: PropTypes.object, | ||
30 | selectedIndex: PropTypes.number, | ||
31 | type: PropTypes.string, | ||
32 | onSelect: PropTypes.func, | ||
33 | onMouseEnter: PropTypes.func, | ||
34 | }, | ||
35 | |||
36 | componentDidMount() { | ||
37 | // jump to selected option | ||
38 | this.scrollToSelected(0); | ||
39 | }, | ||
40 | |||
41 | componentDidUpdate(prevProps) { | ||
42 | // smooth scroll to selected option | ||
43 | if (prevProps.selectedIndex !== this.props.selectedIndex) { | ||
44 | this.scrollToSelected(120); | ||
45 | } | ||
46 | }, | ||
47 | |||
48 | onSelect(value) { | ||
49 | const { onSelect, type } = this.props; | ||
50 | onSelect(type, value); | ||
51 | }, | ||
52 | |||
53 | getOptions() { | ||
54 | const { options, selectedIndex, prefixCls } = this.props; | ||
55 | return options.map((item, index) => { | ||
56 | const cls = classnames({ | ||
57 | [`${prefixCls}-select-option-selected`]: selectedIndex === index, | ||
58 | [`${prefixCls}-select-option-disabled`]: item.disabled, | ||
59 | }); | ||
60 | let onclick = null; | ||
61 | if (!item.disabled) { | ||
62 | onclick = this.onSelect.bind(this, +item.value); | ||
63 | } | ||
64 | return <li className={cls} key={index} onClick={onclick} disabled={item.disabled}>{item.value}</li>; | ||
65 | }); | ||
66 | }, | ||
67 | |||
68 | scrollToSelected(duration) { | ||
69 | // move to selected item | ||
70 | const select = ReactDom.findDOMNode(this); | ||
71 | const list = ReactDom.findDOMNode(this.refs.list); | ||
72 | let index = this.props.selectedIndex; | ||
73 | if (index < 0) { | ||
74 | index = 0; | ||
75 | } | ||
76 | const topOption = list.children[index]; | ||
77 | const to = topOption.offsetTop; | ||
78 | scrollTo(select, to, duration); | ||
79 | }, | ||
80 | |||
81 | render() { | ||
82 | if (this.props.options.length === 0) { | ||
83 | return null; | ||
84 | } | ||
85 | |||
86 | const { prefixCls } = this.props; | ||
87 | |||
88 | return ( | ||
89 | <div className={`${prefixCls}-select`} | ||
90 | onMouseEnter={this.props.onMouseEnter}> | ||
91 | <ul ref="list">{this.getOptions()}</ul> | ||
92 | </div> | ||
93 | ); | ||
94 | }, | ||
95 | }); | ||
96 | |||
97 | export default Select; | ||