UNPKG

react-date-picker

Version:

A carefully crafted date picker for React

419 lines (322 loc) 10.1 kB
import React from 'react' import Component from 'react-class' import assign from 'object-assign' import { Flex } from 'react-flex' import toMoment from './toMoment' import join from './join' import joinFunctions from './joinFunctions' import bemFactory from './bemFactory' import Footer from './Footer' import YearView from './YearView' import assignDefined from './assignDefined' const bem = bemFactory('react-date-picker__history-view') const preventDefault = (e) => { e.preventDefault() } import DecadeView, { prepareDateProps, getInitialState, onViewDateChange, onActiveDateChange, onChange, navigate, select, confirm, gotoViewDate } from './DecadeView' export default class HistoryView extends Component { constructor(props) { super(props) this.state = getInitialState(props) } componentWillUnmount() { this.unmounted = true } toMoment(date, format) { return toMoment(date, format, this.props) } render() { const dateProps = prepareDateProps(this.props, this.state) const props = this.p = assign({}, this.props, dateProps) props.children = React.Children.toArray(props.children) const className = join( props.className, bem(), props.theme && bem(null, `theme-${props.theme}`) ) const commonProps = assignDefined({}, { locale: props.locale, theme: props.theme, minDate: props.minDate, maxDate: props.maxDate, viewDate: props.viewMoment, activeDate: props.activeDate, date: props.date, dateFormat: props.dateFormat }) const yearViewProps = assign({}, commonProps) const decadeViewProps = assign({}, commonProps, { ref: view => { this.decadeView = view } }) const flexProps = assign({}, this.props) delete flexProps.activeDate delete flexProps.adjustDateStartOf delete flexProps.adjustMaxDateStartOf delete flexProps.adjustMinDateStartOf delete flexProps.cleanup delete flexProps.date delete flexProps.dateFormat delete flexProps.defaultDate delete flexProps.defaultViewDate delete flexProps.focusDecadeView delete flexProps.focusYearView delete flexProps.footer delete flexProps.locale delete flexProps.maxDate delete flexProps.minDate delete flexProps.onOkClick delete flexProps.onCancelClick delete flexProps.okOnEnter delete flexProps.navigation delete flexProps.theme delete flexProps.viewMoment if (typeof props.cleanup == 'function') { props.cleanup(flexProps) } return <Flex inline column alignItems="stretch" {...flexProps} className={className} > {this.renderYearView(yearViewProps)} {this.renderDecadeView(decadeViewProps)} {this.renderFooter()} </Flex> } renderFooter() { const props = this.p const children = props.children if (!props.footer) { return null } const footerChild = children.filter(c => c && c.props && c.props.isDatePickerFooter)[0] if (footerChild) { const newFooterProps = { onOkClick: joinFunctions(this.onOkClick, footerChild.props.onOkClick), onCancelClick: joinFunctions(this.onCancelClick, footerChild.props.onCancelClick) } if (footerChild.props.centerButtons === undefined) { newFooterProps.centerButtons = true } if (footerChild.props.todayButton === undefined) { newFooterProps.todayButton = false } if (footerChild.props.clearButton === undefined) { newFooterProps.clearButton = false } return React.cloneElement(footerChild, newFooterProps) } return <Footer todayButton={false} clearButton={false} onOkClick={this.onOkClick} onCancelClick={this.onCancelClick} centerButtons /> } onOkClick() { if (this.props.onOkClick) { const dateMoment = this.p.activeMoment const dateString = this.format(dateMoment) const timestamp = +dateMoment this.props.onOkClick(dateString, { dateMoment, timestamp }) } } onCancelClick() { if (this.props.onCancelClick) { this.props.onCancelClick() } } renderYearView(yearViewProps) { const props = this.p const children = props.children const yearViewChild = children.filter(c => c && c.props && c.props.isYearView)[0] const yearViewChildProps = yearViewChild ? yearViewChild.props : {} const tabIndex = yearViewChildProps.tabIndex == null ? null : yearViewChildProps.tabIndex yearViewProps.tabIndex = tabIndex if (props.focusYearView === false || tabIndex == null) { yearViewProps.tabIndex = null yearViewProps.onFocus = this.onYearViewFocus yearViewProps.onMouseDown = this.onYearViewMouseDown } assign(yearViewProps, { // viewDate: props.moment || props.viewDate, onViewDateChange: joinFunctions( this.onViewDateChange, yearViewChildProps.onViewDateChange ), onActiveDateChange: joinFunctions( this.onActiveDateChange, yearViewChildProps.onActiveDateChange ), onChange: joinFunctions( this.handleYearViewOnChange, yearViewChildProps.onChange ) }) if (yearViewChild) { return React.cloneElement(yearViewChild, yearViewProps) } return <YearView {...yearViewProps} /> } renderDecadeView(decadeViewProps) { const props = this.p const children = props.children const decadeViewChild = children.filter(c => c && c.props && c.props.isDecadeView)[0] const decadeViewChildProps = decadeViewChild ? decadeViewChild.props : {} const tabIndex = decadeViewChildProps.tabIndex == null ? null : decadeViewChildProps.tabIndex decadeViewProps.tabIndex = tabIndex if (props.focusDecadeView === false || tabIndex == null) { decadeViewProps.tabIndex = null decadeViewProps.onMouseDown = this.onDecadeViewMouseDown } assign(decadeViewProps, { onConfirm: joinFunctions( this.handleDecadeViewOnConfirm, decadeViewChildProps.onConfirm ), onViewDateChange: joinFunctions( this.handleDecadeOnViewDateChange, decadeViewChildProps.onViewDateChange ), onActiveDateChange: joinFunctions( this.handleDecadeOnActiveDateChange, decadeViewChildProps.onActiveDateChange ), onChange: joinFunctions( this.handleDecadeOnChange, decadeViewChildProps.onChange ) }) if (decadeViewChild) { return React.cloneElement(decadeViewChild, decadeViewProps) } return <DecadeView {...decadeViewProps} /> } onYearViewFocus() { if (this.props.focusYearView === false) { this.focus() } } focus() { if (this.decadeView && this.props.focusDecadeView) { this.decadeView.focus() } } onYearViewMouseDown(e) { preventDefault(e) this.focus() } onDecadeViewMouseDown(e) { preventDefault(e) } format(mom, format) { format = format || this.props.dateFormat return mom.format(format) } handleDecadeViewOnConfirm() { if (this.props.okOnEnter) { this.onOkClick() } } onKeyDown(event) { if (event.key == 'Escape') { return this.onCancelClick() } if (this.decadeView) { this.decadeView.onKeyDown(event) } return undefined } confirm(date, event) { return confirm.call(this, date, event) } navigate(direction, event) { return navigate.call(this, direction, event) } select({ dateMoment, timestamp }, event) { return select.call(this, { dateMoment, timestamp }, event) } handleDecadeOnViewDateChange(dateString, { dateMoment, timestamp }) { const props = this.p const currentViewMoment = props.viewMoment if (currentViewMoment) { dateMoment.set('month', currentViewMoment.get('month')) dateString = this.format(dateMoment) timestamp = +dateMoment } this.onViewDateChange(dateString, { dateMoment, timestamp }) } handleDecadeOnActiveDateChange(dateString, { dateMoment, timestamp }) { const props = this.p const currentViewMoment = props.viewMoment if (currentViewMoment) { dateMoment.set('month', currentViewMoment.get('month')) dateString = this.format(dateMoment) timestamp = +dateMoment } this.onActiveDateChange(dateString, { dateMoment, timestamp }) } handleDecadeOnChange(dateString, { dateMoment, timestamp }, event) { const props = this.p const currentViewMoment = props.viewMoment if (currentViewMoment) { dateMoment.set('month', currentViewMoment.get('month')) dateString = this.format(dateMoment) timestamp = +dateMoment } this.onChange(dateString, { dateMoment, timestamp }, event) } handleYearViewOnChange(dateString, { dateMoment, timestamp }, event) { const props = this.p const currentMoment = props.moment if (currentMoment) { dateMoment.set('year', currentMoment.get('year')) dateString = this.format(dateMoment) timestamp = +dateMoment } this.onChange(dateString, { dateMoment, timestamp }, event) } onViewDateChange(dateString, { dateMoment, timestamp }) { return onViewDateChange.call(this, { dateMoment, timestamp }) } gotoViewDate({ dateMoment, timestamp }) { return gotoViewDate.call(this, { dateMoment, timestamp }) } onActiveDateChange(dateString, { dateMoment, timestamp }) { return onActiveDateChange.call(this, { dateMoment, timestamp }) } onChange(dateString, { dateMoment, timestamp }, event) { return onChange.call(this, { dateMoment, timestamp }, event) } } HistoryView.defaultProps = { okOnEnter: true, footer: true, theme: 'default', navigation: true, focusYearView: false, focusDecadeView: true, dateFormat: 'YYYY-MM-DD', adjustDateStartOf: 'month', adjustMinDateStartOf: 'month', adjustMaxDateStartOf: 'month' }