]> git.immae.eu Git - github/fretlink/time-picker.git/blame - src/TimePicker.jsx
Add id to input element
[github/fretlink/time-picker.git] / src / TimePicker.jsx
CommitLineData
3ab3a128 1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
02de449a 3import Trigger from 'rc-trigger';
4984ed85 4import Panel from './Panel';
5import placements from './placements';
6import moment from 'moment';
02de449a 7
8function noop() {
9}
10
11function refFn(field, component) {
12 this[field] = component;
13}
14
cfe8e36c 15export default class Picker extends Component {
3ab3a128 16 static propTypes = {
02de449a 17 prefixCls: PropTypes.string,
4984ed85 18 clearText: PropTypes.string,
9f9f39e4 19 value: PropTypes.object,
4984ed85 20 defaultOpenValue: PropTypes.object,
4e70ea0d 21 inputReadOnly: PropTypes.bool,
02de449a 22 disabled: PropTypes.bool,
8133e8cf 23 allowEmpty: PropTypes.bool,
63541ed7 24 defaultValue: PropTypes.object,
02de449a 25 open: PropTypes.bool,
8133e8cf 26 defaultOpen: PropTypes.bool,
02de449a 27 align: PropTypes.object,
28 placement: PropTypes.any,
29 transitionName: PropTypes.string,
8133e8cf 30 getPopupContainer: PropTypes.func,
4acbf95c 31 placeholder: PropTypes.string,
4984ed85 32 format: PropTypes.string,
8133e8cf 33 showHour: PropTypes.bool,
37c36c09 34 showMinute: PropTypes.bool,
3b3350d5 35 showSecond: PropTypes.bool,
8133e8cf 36 style: PropTypes.object,
96d366af 37 className: PropTypes.string,
a7c6e7bb 38 popupClassName: PropTypes.string,
71bd9bc1
M
39 disabledHours: PropTypes.func,
40 disabledMinutes: PropTypes.func,
41 disabledSeconds: PropTypes.func,
518b852e 42 hideDisabledOptions: PropTypes.bool,
02de449a 43 onChange: PropTypes.func,
44 onOpen: PropTypes.func,
45 onClose: PropTypes.func,
e30387ab
CS
46 onFocus: PropTypes.func,
47 onBlur: PropTypes.func,
b86fe1d1 48 addon: PropTypes.func,
6d1ad104 49 name: PropTypes.string,
73e6cf78 50 autoComplete: PropTypes.string,
dd275f7d 51 use12Hours: PropTypes.bool,
5827568e
MP
52 hourStep: PropTypes.number,
53 minuteStep: PropTypes.number,
54 secondStep: PropTypes.number,
d18ecfb6 55 focusOnOpen: PropTypes.bool,
0e4fd162 56 onKeyDown: PropTypes.func,
d9a9b691 57 autoFocus: PropTypes.bool,
0414a016 58 id: PropTypes.string,
3ab3a128 59 };
60
61 static defaultProps = {
62 clearText: 'clear',
63 prefixCls: 'rc-time-picker',
64 defaultOpen: false,
4e70ea0d 65 inputReadOnly: false,
3ab3a128 66 style: {},
67 className: '',
a7c6e7bb 68 popupClassName: '',
3ab3a128 69 align: {},
70 defaultOpenValue: moment(),
71 allowEmpty: true,
72 showHour: true,
73 showMinute: true,
74 showSecond: true,
75 disabledHours: noop,
76 disabledMinutes: noop,
77 disabledSeconds: noop,
78 hideDisabledOptions: false,
79 placement: 'bottomLeft',
80 onChange: noop,
81 onOpen: noop,
82 onClose: noop,
e30387ab
CS
83 onFocus: noop,
84 onBlur: noop,
3ab3a128 85 addon: noop,
86 use12Hours: false,
d18ecfb6 87 focusOnOpen: false,
0e4fd162 88 onKeyDown: noop,
0414a016 89 id: '',
3ab3a128 90 };
91
92 constructor(props) {
93 super(props);
fa912931 94 this.saveInputRef = refFn.bind(this, 'picker');
02de449a 95 this.savePanelRef = refFn.bind(this, 'panelInstance');
3ab3a128 96 const { defaultOpen, defaultValue, open = defaultOpen, value = defaultValue } = props;
97 this.state = {
8133e8cf 98 open,
99 value,
e75ed0c6 100 };
3ab3a128 101 }
02de449a 102
02de449a 103 componentWillReceiveProps(nextProps) {
9f9f39e4 104 const { value, open } = nextProps;
6fc4e0e8 105 if ('value' in nextProps) {
9f9f39e4 106 this.setState({
107 value,
108 });
02de449a 109 }
110 if (open !== undefined) {
1882f74d 111 this.setState({ open });
02de449a 112 }
3ab3a128 113 }
02de449a 114
3ab3a128 115 onPanelChange = (value) => {
9f9f39e4 116 this.setValue(value);
3ab3a128 117 }
02de449a 118
3ab3a128 119 onPanelClear = () => {
7702bb67 120 this.setValue(null);
63541ed7 121 this.setOpen(false);
3ab3a128 122 }
02de449a 123
3ab3a128 124 onVisibleChange = (open) => {
8133e8cf 125 this.setOpen(open);
3ab3a128 126 }
8133e8cf 127
3ab3a128 128 onEsc = () => {
8133e8cf 129 this.setOpen(false);
ed849606 130 this.focus();
3ab3a128 131 }
8133e8cf 132
3ab3a128 133 onKeyDown = (e) => {
8133e8cf 134 if (e.keyCode === 40) {
135 this.setOpen(true);
136 }
3ab3a128 137 }
02de449a 138
9f9f39e4 139 setValue(value) {
140 if (!('value' in this.props)) {
141 this.setState({
142 value,
143 });
144 }
145 this.props.onChange(value);
3ab3a128 146 }
9f9f39e4 147
4984ed85 148 getFormat() {
dd2f6abd 149 const { format, showHour, showMinute, showSecond, use12Hours } = this.props;
4984ed85 150 if (format) {
151 return format;
8133e8cf 152 }
dd2f6abd
AS
153
154 if (use12Hours) {
155 const fmtString = ([
156 showHour ? 'h' : '',
157 showMinute ? 'mm' : '',
158 showSecond ? 'ss' : '',
159 ].filter(item => !!item).join(':'));
160
161 return fmtString.concat(' a');
162 }
163
37c36c09 164 return [
165 showHour ? 'HH' : '',
166 showMinute ? 'mm' : '',
167 showSecond ? 'ss' : '',
168 ].filter(item => !!item).join(':');
3ab3a128 169 }
8133e8cf 170
171 getPanelElement() {
1882f74d 172 const {
4984ed85 173 prefixCls, placeholder, disabledHours,
4e70ea0d 174 disabledMinutes, disabledSeconds, hideDisabledOptions, inputReadOnly,
37c36c09 175 allowEmpty, showHour, showMinute, showSecond, defaultOpenValue, clearText,
f0ac29c6 176 addon, use12Hours, focusOnOpen, onKeyDown, hourStep, minuteStep, secondStep,
1882f74d 177 } = this.props;
4acbf95c
M
178 return (
179 <Panel
4984ed85 180 clearText={clearText}
8133e8cf 181 prefixCls={`${prefixCls}-panel`}
182 ref={this.savePanelRef}
183 value={this.state.value}
4e70ea0d 184 inputReadOnly={inputReadOnly}
8133e8cf 185 onChange={this.onPanelChange}
8133e8cf 186 onClear={this.onPanelClear}
4984ed85 187 defaultOpenValue={defaultOpenValue}
8133e8cf 188 showHour={showHour}
37c36c09 189 showMinute={showMinute}
8133e8cf 190 showSecond={showSecond}
3b3350d5 191 onEsc={this.onEsc}
8133e8cf 192 allowEmpty={allowEmpty}
4984ed85 193 format={this.getFormat()}
4acbf95c 194 placeholder={placeholder}
518b852e
M
195 disabledHours={disabledHours}
196 disabledMinutes={disabledMinutes}
197 disabledSeconds={disabledSeconds}
198 hideDisabledOptions={hideDisabledOptions}
dd275f7d 199 use12Hours={use12Hours}
5827568e
MP
200 hourStep={hourStep}
201 minuteStep={minuteStep}
202 secondStep={secondStep}
b86fe1d1 203 addon={addon}
d18ecfb6 204 focusOnOpen={focusOnOpen}
0e4fd162 205 onKeyDown={onKeyDown}
4acbf95c
M
206 />
207 );
3ab3a128 208 }
4acbf95c 209
a7c6e7bb 210 getPopupClassName() {
211 const { showHour, showMinute, showSecond, use12Hours, prefixCls } = this.props;
212 let popupClassName = this.props.popupClassName;
213 // Keep it for old compatibility
214 if ((!showHour || !showMinute || !showSecond) && !use12Hours) {
215 popupClassName += ` ${prefixCls}-panel-narrow`;
216 }
217 let selectColumnCount = 0;
218 if (showHour) {
219 selectColumnCount += 1;
220 }
221 if (showMinute) {
222 selectColumnCount += 1;
223 }
224 if (showSecond) {
225 selectColumnCount += 1;
226 }
227 if (use12Hours) {
228 selectColumnCount += 1;
229 }
230 popupClassName += ` ${prefixCls}-panel-column-${selectColumnCount}`;
231 return popupClassName;
232 }
233
71c3a196 234 setOpen(open) {
1882f74d 235 const { onOpen, onClose } = this.props;
02de449a 236 if (this.state.open !== open) {
71c3a196 237 if (!('open' in this.props)) {
238 this.setState({ open });
239 }
02de449a 240 if (open) {
71c3a196 241 onOpen({ open });
02de449a 242 } else {
71c3a196 243 onClose({ open });
02de449a 244 }
245 }
3ab3a128 246 }
02de449a 247
ed849606 248 focus() {
dd63e6e7 249 this.picker.focus();
3ab3a128 250 }
ed849606 251
d9a9b691
WZ
252 blur() {
253 this.picker.blur();
254 }
255
02de449a 256 render() {
4984ed85 257 const {
0414a016 258 prefixCls, placeholder, placement, align, id,
a7c6e7bb 259 disabled, transitionName, style, className, getPopupContainer, name, autoComplete,
543a5211 260 onFocus, onBlur, autoFocus, inputReadOnly,
4984ed85 261 } = this.props;
4acbf95c 262 const { open, value } = this.state;
a7c6e7bb 263 const popupClassName = this.getPopupClassName();
02de449a 264 return (
265 <Trigger
96a4cefc 266 prefixCls={`${prefixCls}-panel`}
8133e8cf 267 popupClassName={popupClassName}
02de449a 268 popup={this.getPanelElement()}
269 popupAlign={align}
270 builtinPlacements={placements}
271 popupPlacement={placement}
272 action={disabled ? [] : ['click']}
273 destroyPopupOnHide
8133e8cf 274 getPopupContainer={getPopupContainer}
02de449a 275 popupTransitionName={transitionName}
4acbf95c 276 popupVisible={open}
02de449a 277 onPopupVisibleChange={this.onVisibleChange}
278 >
96d366af 279 <span className={`${prefixCls} ${className}`} style={style}>
1882f74d 280 <input
281 className={`${prefixCls}-input`}
66c7bc36 282 ref={this.saveInputRef}
283 type="text"
284 placeholder={placeholder}
6d1ad104 285 name={name}
1882f74d 286 onKeyDown={this.onKeyDown}
d9a9b691
WZ
287 disabled={disabled}
288 value={value && value.format(this.getFormat()) || ''}
73e6cf78 289 autoComplete={autoComplete}
e30387ab
CS
290 onFocus={onFocus}
291 onBlur={onBlur}
d9a9b691 292 autoFocus={autoFocus}
fdead5ab 293 onChange={noop}
b6a1d52b 294 readOnly={!!inputReadOnly}
0414a016 295 id={id}
543a5211 296 />
9f9f39e4 297 <span className={`${prefixCls}-icon`}/>
02de449a 298 </span>
299 </Trigger>
300 );
3ab3a128 301 }
302}