-import React, {PropTypes} from 'react';
-import ReactDOM from 'react-dom';
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
import Trigger from 'rc-trigger';
-import {createChainedFunction} from 'rc-util';
-import placements from './util/placements';
-import CommonMixin from './mixin/CommonMixin';
+import Panel from './Panel';
+import placements from './placements';
+import moment from 'moment';
function noop() {
}
this[field] = component;
}
-const Picker = React.createClass({
- propTypes: {
+export default class Picker extends Component {
+ static propTypes = {
prefixCls: PropTypes.string,
- panel: PropTypes.element,
- children: PropTypes.func,
- disabled: PropTypes.bool,
+ clearText: PropTypes.string,
value: PropTypes.object,
+ defaultOpenValue: PropTypes.object,
+ disabled: PropTypes.bool,
+ allowEmpty: PropTypes.bool,
+ defaultValue: PropTypes.object,
open: PropTypes.bool,
+ defaultOpen: PropTypes.bool,
align: PropTypes.object,
placement: PropTypes.any,
transitionName: PropTypes.string,
+ getPopupContainer: PropTypes.func,
+ placeholder: PropTypes.string,
+ format: PropTypes.string,
+ showHour: PropTypes.bool,
+ showMinute: PropTypes.bool,
+ showSecond: PropTypes.bool,
+ style: PropTypes.object,
+ className: PropTypes.string,
+ popupClassName: PropTypes.string,
+ disabledHours: PropTypes.func,
+ disabledMinutes: PropTypes.func,
+ disabledSeconds: PropTypes.func,
+ hideDisabledOptions: PropTypes.bool,
onChange: PropTypes.func,
onOpen: PropTypes.func,
onClose: PropTypes.func,
- },
-
- mixins: [CommonMixin],
-
- getDefaultProps() {
- return {
- open: false,
- align: {},
- placement: 'bottomLeft',
- onChange: noop,
- onOpen: noop,
- onClose: noop,
- };
- },
+ addon: PropTypes.func,
+ name: PropTypes.string,
+ autoComplete: PropTypes.string,
+ use12Hours: PropTypes.bool,
+ focusOnOpen: PropTypes.bool,
+ };
- getInitialState() {
+ static defaultProps = {
+ clearText: 'clear',
+ prefixCls: 'rc-time-picker',
+ defaultOpen: false,
+ style: {},
+ className: '',
+ popupClassName: '',
+ align: {},
+ defaultOpenValue: moment(),
+ allowEmpty: true,
+ showHour: true,
+ showMinute: true,
+ showSecond: true,
+ disabledHours: noop,
+ disabledMinutes: noop,
+ disabledSeconds: noop,
+ hideDisabledOptions: false,
+ placement: 'bottomLeft',
+ onChange: noop,
+ onOpen: noop,
+ onClose: noop,
+ addon: noop,
+ use12Hours: false,
+ focusOnOpen: false,
+ };
+
+ constructor(props) {
+ super(props);
+ this.saveInputRef = refFn.bind(this, 'picker');
this.savePanelRef = refFn.bind(this, 'panelInstance');
- const { open, value } = this.props;
- return { open, value };
- },
+ const { defaultOpen, defaultValue, open = defaultOpen, value = defaultValue } = props;
+ this.state = {
+ open,
+ value,
+ };
+ }
componentWillReceiveProps(nextProps) {
const { value, open } = nextProps;
- if (value !== undefined) {
- this.setState({value});
+ if ('value' in nextProps) {
+ this.setState({
+ value,
+ });
}
if (open !== undefined) {
- this.setState({open});
+ this.setState({ open });
}
- },
-
- onPanelChange(value) {
- const props = this.props;
- this.setState({
- value: value,
- });
- props.onChange(value);
- },
-
- onPanelClear() {
- this.setOpen(false, this.focus);
- },
-
- onVisibleChange(open) {
- this.setOpen(open, () => {
- if (open) {
- ReactDOM.findDOMNode(this.panelInstance).focus();
- }
- });
- },
+ }
+
+ onPanelChange = (value) => {
+ this.setValue(value);
+ }
+
+ onPanelClear = () => {
+ this.setValue(null);
+ this.setOpen(false);
+ }
+
+ onVisibleChange = (open) => {
+ this.setOpen(open);
+ }
+
+ onEsc = () => {
+ this.setOpen(false);
+ this.focus();
+ }
+
+ onKeyDown = (e) => {
+ if (e.keyCode === 40) {
+ this.setOpen(true);
+ }
+ }
+
+ setValue(value) {
+ if (!('value' in this.props)) {
+ this.setState({
+ value,
+ });
+ }
+ this.props.onChange(value);
+ }
+
+ getFormat() {
+ const { format, showHour, showMinute, showSecond, use12Hours } = this.props;
+ if (format) {
+ return format;
+ }
+
+ if (use12Hours) {
+ const fmtString = ([
+ showHour ? 'h' : '',
+ showMinute ? 'mm' : '',
+ showSecond ? 'ss' : '',
+ ].filter(item => !!item).join(':'));
+
+ return fmtString.concat(' a');
+ }
+
+ return [
+ showHour ? 'HH' : '',
+ showMinute ? 'mm' : '',
+ showSecond ? 'ss' : '',
+ ].filter(item => !!item).join(':');
+ }
getPanelElement() {
- const panel = this.props.panel;
- const extraProps = {
- ref: this.savePanelRef,
- defaultValue: this.state.value || panel.props.defaultValue,
- onChange: createChainedFunction(panel.props.onChange, this.onPanelChange),
- onClear: createChainedFunction(panel.props.onClear, this.onPanelClear),
- };
+ const {
+ prefixCls, placeholder, disabledHours,
+ disabledMinutes, disabledSeconds, hideDisabledOptions,
+ allowEmpty, showHour, showMinute, showSecond, defaultOpenValue, clearText,
+ addon, use12Hours, focusOnOpen,
+ } = this.props;
+ return (
+ <Panel
+ clearText={clearText}
+ prefixCls={`${prefixCls}-panel`}
+ ref={this.savePanelRef}
+ value={this.state.value}
+ onChange={this.onPanelChange}
+ onClear={this.onPanelClear}
+ defaultOpenValue={defaultOpenValue}
+ showHour={showHour}
+ showMinute={showMinute}
+ showSecond={showSecond}
+ onEsc={this.onEsc}
+ allowEmpty={allowEmpty}
+ format={this.getFormat()}
+ placeholder={placeholder}
+ disabledHours={disabledHours}
+ disabledMinutes={disabledMinutes}
+ disabledSeconds={disabledSeconds}
+ hideDisabledOptions={hideDisabledOptions}
+ use12Hours={use12Hours}
+ addon={addon}
+ focusOnOpen={focusOnOpen}
+ />
+ );
+ }
- return React.cloneElement(panel, extraProps);
- },
+ getPopupClassName() {
+ const { showHour, showMinute, showSecond, use12Hours, prefixCls } = this.props;
+ let popupClassName = this.props.popupClassName;
+ // Keep it for old compatibility
+ if ((!showHour || !showMinute || !showSecond) && !use12Hours) {
+ popupClassName += ` ${prefixCls}-panel-narrow`;
+ }
+ let selectColumnCount = 0;
+ if (showHour) {
+ selectColumnCount += 1;
+ }
+ if (showMinute) {
+ selectColumnCount += 1;
+ }
+ if (showSecond) {
+ selectColumnCount += 1;
+ }
+ if (use12Hours) {
+ selectColumnCount += 1;
+ }
+ popupClassName += ` ${prefixCls}-panel-column-${selectColumnCount}`;
+ return popupClassName;
+ }
- setOpen(open, callback) {
- const {onOpen, onClose} = this.props;
+ setOpen(open) {
+ const { onOpen, onClose } = this.props;
if (this.state.open !== open) {
- this.setState({
- open: open,
- }, callback);
- const event = {
- open: open,
- };
+ if (!('open' in this.props)) {
+ this.setState({ open });
+ }
if (open) {
- onOpen(event);
+ onOpen({ open });
} else {
- onClose(event);
+ onClose({ open });
}
}
- },
+ }
focus() {
- if (!this.state.open) {
- ReactDOM.findDOMNode(this).focus();
- }
- },
+ this.picker.focus();
+ }
render() {
- const state = this.state;
- const props = this.props;
- const { prefixCls, placement, align, disabled, transitionName, children } = props;
+ const {
+ prefixCls, placeholder, placement, align,
+ disabled, transitionName, style, className, getPopupContainer, name, autoComplete,
+ } = this.props;
+ const { open, value } = this.state;
+ const popupClassName = this.getPopupClassName();
return (
<Trigger
- prefixCls={prefixCls}
+ prefixCls={`${prefixCls}-panel`}
+ popupClassName={popupClassName}
popup={this.getPanelElement()}
popupAlign={align}
builtinPlacements={placements}
popupPlacement={placement}
action={disabled ? [] : ['click']}
destroyPopupOnHide
+ getPopupContainer={getPopupContainer}
popupTransitionName={transitionName}
- popupVisible={state.open}
+ popupVisible={open}
onPopupVisibleChange={this.onVisibleChange}
>
- <span className={`${prefixCls}-picker`}>
- {children(state, props)}
+ <span className={`${prefixCls} ${className}`} style={style}>
+ <input
+ className={`${prefixCls}-input`}
+ ref={this.saveInputRef}
+ type="text"
+ placeholder={placeholder}
+ name={name}
+ readOnly
+ onKeyDown={this.onKeyDown}
+ disabled={disabled} value={value && value.format(this.getFormat()) || ''}
+ autoComplete={autoComplete}
+ />
+ <span className={`${prefixCls}-icon`}/>
</span>
</Trigger>
);
- },
-});
-
-export default Picker;
+ }
+}