aboutsummaryrefslogblamecommitdiffhomepage
path: root/src/TimePicker.jsx
blob: 2c6a1f16ea69f5825fd7b7f30963ea308a3528ca (plain) (tree)
1
2
3
4
5
6

                                         
                                 


                                      







                                  
                                               
                      
                                
                                
                            
                                       
                             
                               
                                   
                         
                                


                                     
                                      
                                  
                             
                             
                               
                               
                            
                                
                                     


                                    
                                        


                             
                          
                           
                                   
                               







                                
                       



















                               
                                                   
                                                          

                                                                                          

            
      
   
 
                                        
                                      
                               


                     

                             
                              
     
   
 
                              
                         
   
 
                        
                        
                        
   
 
                               
                       
   
 
                 
                        
                 
   
 
                      


                           
   
 






                                   
   
 
               
                                                                                

                    
     










                                          




                                       
   

                     
           
                                            
                                                            
                                                                                
                        
                   

            
                             



                                        
                                   
                                           
                           
                               
                               
                          
                               
                                 
                                 



                                                 
                               
                     

        
   
 























                                                                                   
                 
                                           
                                   


                                    
                 
                         
              
                          

       
   
 
           
                        
   
 
            

                                               
                                                                                        
                   
                                       
                                                    

              
                                        
                                       





                                          
                                             
                                            
                           

                                                   
                                                                    

                                            


                                     
                       

                                      
                                                                                     
                                       
            
                                                 


                

   
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Trigger from 'rc-trigger';
import Panel from './Panel';
import placements from './placements';
import moment from 'moment';

function noop() {
}

function refFn(field, component) {
  this[field] = component;
}

export default class Picker extends Component {
  static propTypes = {
    prefixCls: PropTypes.string,
    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,
    addon: PropTypes.func,
    name: PropTypes.string,
    autoComplete: PropTypes.string,
    use12Hours: PropTypes.bool,
  };

  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,
  };

  constructor(props) {
    super(props);
    this.saveInputRef = refFn.bind(this, 'picker');
    this.savePanelRef = refFn.bind(this, 'panelInstance');
    const { defaultOpen, defaultValue, open = defaultOpen, value = defaultValue } = props;
    this.state = {
      open,
      value,
    };
  }

  componentWillReceiveProps(nextProps) {
    const { value, open } = nextProps;
    if ('value' in nextProps) {
      this.setState({
        value,
      });
    }
    if (open !== undefined) {
      this.setState({ open });
    }
  }

  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 {
      prefixCls, placeholder, disabledHours,
      disabledMinutes, disabledSeconds, hideDisabledOptions,
      allowEmpty, showHour, showMinute, showSecond, defaultOpenValue, clearText,
      addon, use12Hours,
    } = 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}
      />
    );
  }

  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) {
    const { onOpen, onClose } = this.props;
    if (this.state.open !== open) {
      if (!('open' in this.props)) {
        this.setState({ open });
      }
      if (open) {
        onOpen({ open });
      } else {
        onClose({ open });
      }
    }
  }

  focus() {
    this.picker.focus();
  }

  render() {
    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}-panel`}
        popupClassName={popupClassName}
        popup={this.getPanelElement()}
        popupAlign={align}
        builtinPlacements={placements}
        popupPlacement={placement}
        action={disabled ? [] : ['click']}
        destroyPopupOnHide
        getPopupContainer={getPopupContainer}
        popupTransitionName={transitionName}
        popupVisible={open}
        onPopupVisibleChange={this.onVisibleChange}
      >
        <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>
    );
  }
}