react-dates
Version:
A responsive and accessible date range picker component built with React
157 lines (136 loc) • 3.73 kB
JSX
import React, { PropTypes } from 'react';
import cx from 'classnames';
import isTouchDevice from '../utils/isTouchDevice';
const propTypes = {
id: PropTypes.string.isRequired,
placeholder: PropTypes.string, // also used as label
displayValue: PropTypes.string,
inputValue: PropTypes.string,
screenReaderMessage: PropTypes.string,
focused: PropTypes.bool,
disabled: PropTypes.bool,
required: PropTypes.bool,
showCaret: PropTypes.bool,
onChange: PropTypes.func,
onFocus: PropTypes.func,
onKeyDownShiftTab: PropTypes.func,
onKeyDownTab: PropTypes.func,
};
const defaultProps = {
placeholder: 'Select Date',
displayValue: '',
inputValue: '',
screenReaderMessage: '',
focused: false,
disabled: false,
required: false,
showCaret: false,
onChange() {},
onFocus() {},
onKeyDownShiftTab() {},
onKeyDownTab() {},
};
export default class DateInput extends React.Component {
constructor(props) {
super(props);
this.state = {
dateString: '',
};
this.onChange = this.onChange.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this.isTouchDevice = isTouchDevice();
}
componentWillReceiveProps(nextProps) {
if (!this.props.displayValue && nextProps.displayValue) {
this.setState({
dateString: '',
});
}
}
componentDidUpdate(prevProps) {
const { focused } = this.props;
if (prevProps.focused === focused) return;
if (focused) {
this.inputRef.focus();
this.inputRef.select();
} else {
this.inputRef.blur();
}
}
onChange(e) {
const dateString = e.target.value;
this.setState({ dateString });
this.props.onChange(dateString);
}
onKeyDown(e) {
const { onKeyDownShiftTab, onKeyDownTab } = this.props;
if (e.key === 'Tab') {
if (e.shiftKey) {
onKeyDownShiftTab(e);
} else {
onKeyDownTab(e);
}
}
}
render() {
const { dateString } = this.state;
const {
id,
placeholder,
displayValue,
inputValue,
screenReaderMessage,
focused,
showCaret,
onFocus,
disabled,
required,
} = this.props;
const displayText = displayValue || inputValue || dateString || placeholder || '';
const value = inputValue || displayValue || dateString || '';
const screenReaderMessageId = `DateInput__screen-reader-message-${id}`;
return (
<div
className={cx('DateInput', {
'DateInput--with-caret': showCaret && focused,
'DateInput--disabled': disabled,
})}
>
<input
aria-label={placeholder}
className="DateInput__input"
type="text"
id={id}
name={id}
ref={(ref) => { this.inputRef = ref; }}
value={value}
onChange={this.onChange}
onKeyDown={this.onKeyDown}
onFocus={onFocus}
placeholder={placeholder}
autoComplete="off"
disabled={disabled}
readOnly={this.isTouchDevice}
required={required}
aria-describedby={screenReaderMessage && screenReaderMessageId}
/>
{screenReaderMessage &&
<p id={screenReaderMessageId} className="screen-reader-only">
{screenReaderMessage}
</p>
}
<div
className={cx('DateInput__display-text', {
'DateInput__display-text--has-input': !!value,
'DateInput__display-text--focused': focused,
'DateInput__display-text--disabled': disabled,
})}
>
{displayText}
</div>
</div>
);
}
}
DateInput.propTypes = propTypes;
DateInput.defaultProps = defaultProps;