]>
Commit | Line | Data |
---|---|---|
02de449a | 1 | import React, {PropTypes} from 'react'; |
2 | import ReactDOM from 'react-dom'; | |
3 | import Trigger from 'rc-trigger'; | |
4 | import {createChainedFunction} from 'rc-util'; | |
15bb18d9 | 5 | import Panel from './module/Panel'; |
02de449a | 6 | import placements from './util/placements'; |
7 | import CommonMixin from './mixin/CommonMixin'; | |
8 | ||
9 | function noop() { | |
10 | } | |
11 | ||
12 | function refFn(field, component) { | |
13 | this[field] = component; | |
14 | } | |
15 | ||
16 | const Picker = React.createClass({ | |
17 | propTypes: { | |
18 | prefixCls: PropTypes.string, | |
63541ed7 | 19 | inputClassName: PropTypes.string, |
4acbf95c | 20 | locale: PropTypes.object, |
02de449a | 21 | children: PropTypes.func, |
22 | disabled: PropTypes.bool, | |
63541ed7 | 23 | defaultValue: PropTypes.object, |
02de449a | 24 | open: PropTypes.bool, |
25 | align: PropTypes.object, | |
26 | placement: PropTypes.any, | |
27 | transitionName: PropTypes.string, | |
4acbf95c M |
28 | placeholder: PropTypes.string, |
29 | formatter: PropTypes.object, | |
30 | hourOptions: PropTypes.array, | |
31 | minuteOptions: PropTypes.array, | |
32 | secondOptions: PropTypes.array, | |
02de449a | 33 | onChange: PropTypes.func, |
34 | onOpen: PropTypes.func, | |
35 | onClose: PropTypes.func, | |
36 | }, | |
37 | ||
38 | mixins: [CommonMixin], | |
39 | ||
40 | getDefaultProps() { | |
41 | return { | |
42 | open: false, | |
43 | align: {}, | |
44 | placement: 'bottomLeft', | |
45 | onChange: noop, | |
46 | onOpen: noop, | |
47 | onClose: noop, | |
48 | }; | |
49 | }, | |
50 | ||
51 | getInitialState() { | |
52 | this.savePanelRef = refFn.bind(this, 'panelInstance'); | |
e75ed0c6 M |
53 | const { open, defaultValue } = this.props; |
54 | return { | |
55 | open: open, | |
56 | value: defaultValue, | |
57 | }; | |
02de449a | 58 | }, |
59 | ||
02de449a | 60 | componentWillReceiveProps(nextProps) { |
63541ed7 M |
61 | const { defaultValue, open } = nextProps; |
62 | if (defaultValue !== undefined) { | |
63 | this.setState({value: defaultValue}); | |
02de449a | 64 | } |
65 | if (open !== undefined) { | |
66 | this.setState({open}); | |
67 | } | |
68 | }, | |
69 | ||
02de449a | 70 | onPanelChange(value) { |
02de449a | 71 | this.setState({ |
72 | value: value, | |
73 | }); | |
63541ed7 | 74 | this.props.onChange(value); |
02de449a | 75 | }, |
76 | ||
77 | onPanelClear() { | |
63541ed7 M |
78 | this.setState({ |
79 | value: '', | |
80 | }); | |
81 | this.setOpen(false); | |
02de449a | 82 | }, |
83 | ||
84 | onVisibleChange(open) { | |
85 | this.setOpen(open, () => { | |
86 | if (open) { | |
4acbf95c | 87 | ReactDOM.findDOMNode(this.refs.picker).blur(); |
02de449a | 88 | ReactDOM.findDOMNode(this.panelInstance).focus(); |
89 | } | |
90 | }); | |
91 | }, | |
92 | ||
4acbf95c | 93 | getPanel() { |
63541ed7 | 94 | const { prefixCls, defaultValue, locale, formatter, placeholder, hourOptions, minuteOptions, secondOptions } = this.props; |
4acbf95c M |
95 | return ( |
96 | <Panel | |
15bb18d9 | 97 | prefixCls={prefixCls} |
63541ed7 | 98 | defaultValue={defaultValue} |
4acbf95c M |
99 | locale={locale} |
100 | formatter={formatter} | |
101 | placeholder={placeholder} | |
102 | hourOptions={hourOptions} | |
103 | minuteOptions={minuteOptions} | |
104 | secondOptions={secondOptions} | |
105 | /> | |
106 | ); | |
107 | }, | |
108 | ||
02de449a | 109 | getPanelElement() { |
4acbf95c | 110 | const panel = this.getPanel(); |
02de449a | 111 | const extraProps = { |
112 | ref: this.savePanelRef, | |
113 | defaultValue: this.state.value || panel.props.defaultValue, | |
114 | onChange: createChainedFunction(panel.props.onChange, this.onPanelChange), | |
115 | onClear: createChainedFunction(panel.props.onClear, this.onPanelClear), | |
116 | }; | |
117 | ||
118 | return React.cloneElement(panel, extraProps); | |
119 | }, | |
120 | ||
121 | setOpen(open, callback) { | |
122 | const {onOpen, onClose} = this.props; | |
123 | if (this.state.open !== open) { | |
124 | this.setState({ | |
125 | open: open, | |
126 | }, callback); | |
127 | const event = { | |
128 | open: open, | |
129 | }; | |
130 | if (open) { | |
131 | onOpen(event); | |
132 | } else { | |
133 | onClose(event); | |
134 | } | |
135 | } | |
136 | }, | |
137 | ||
02de449a | 138 | render() { |
63541ed7 | 139 | const { prefixCls, placeholder, placement, align, disabled, transitionName, children, formatter, inputClassName } = this.props; |
4acbf95c M |
140 | const { open, value } = this.state; |
141 | ||
02de449a | 142 | return ( |
143 | <Trigger | |
cadce7b2 | 144 | prefixCls={`${prefixCls}-picker-container`} |
02de449a | 145 | popup={this.getPanelElement()} |
146 | popupAlign={align} | |
147 | builtinPlacements={placements} | |
148 | popupPlacement={placement} | |
149 | action={disabled ? [] : ['click']} | |
150 | destroyPopupOnHide | |
151 | popupTransitionName={transitionName} | |
4acbf95c | 152 | popupVisible={open} |
02de449a | 153 | onPopupVisibleChange={this.onVisibleChange} |
154 | > | |
155 | <span className={`${prefixCls}-picker`}> | |
63541ed7 | 156 | <input className={inputClassName} ref="picker" type="text" placeholder={placeholder} readOnly disabled={disabled} value={value && formatter.format(value)} /> |
15bb18d9 | 157 | <span className={`${prefixCls}-picker-icon`} /> |
02de449a | 158 | </span> |
159 | </Trigger> | |
160 | ); | |
161 | }, | |
162 | }); | |
163 | ||
164 | export default Picker; |