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