UNPKG

@foo-software/react-toolbox

Version:

A set of React components implementing Google's Material Design specification with the power of CSS Modules.

153 lines (137 loc) 4.81 kB
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import time from '../utils/time'; const factory = (Dialog, Calendar) => { class CalendarDialog extends Component { static propTypes = { active: PropTypes.bool, autoOk: PropTypes.bool, cancelLabel: PropTypes.string, className: PropTypes.string, disabledDates: PropTypes.arrayOf(PropTypes.instanceOf(Date)), enabledDates: PropTypes.arrayOf(PropTypes.instanceOf(Date)), locale: PropTypes.oneOfType([ PropTypes.string, PropTypes.object, ]), maxDate: PropTypes.instanceOf(Date), minDate: PropTypes.instanceOf(Date), name: PropTypes.string, okLabel: PropTypes.string, onDismiss: PropTypes.func, onEscKeyDown: PropTypes.func, onOverlayClick: PropTypes.func, onSelect: PropTypes.func, sundayFirstDayOfWeek: PropTypes.bool, theme: PropTypes.shape({ button: PropTypes.string, calendarWrapper: PropTypes.string, date: PropTypes.string, dialog: PropTypes.string, header: PropTypes.string, monthsDisplay: PropTypes.string, year: PropTypes.string, yearsDisplay: PropTypes.string, }), value: PropTypes.instanceOf(Date), }; static defaultProps = { active: false, cancelLabel: 'Cancel', className: '', okLabel: 'Ok', value: new Date(), }; state = { display: 'months', date: this.props.value, }; componentWillMount() { this.updateStateDate(this.props.value); } componentWillReceiveProps(nextProps) { this.updateStateDate(nextProps.value); } handleNewDate = (value, dayClick) => { const state = { display: 'months', date: value }; if (time.dateOutOfRange(value, this.props.minDate, this.props.maxDate)) { if (this.props.maxDate && this.props.minDate) { state.date = time.closestDate(value, this.props.maxDate, this.props.minDate); } else { state.date = this.props.maxDate || this.props.minDate; } } this.setState(state); if (dayClick && this.props.autoOk && this.props.onSelect) { this.props.onSelect(value); } }; handleSelect = (event) => { if (this.props.onSelect) this.props.onSelect(this.state.date, event); }; handleSwitchDisplay = (event) => { this.setState({ display: event.target.id }); }; updateStateDate = (date) => { if (Object.prototype.toString.call(date) === '[object Date]') { this.handleNewDate(date, false); } }; actions = [{ label: this.props.cancelLabel, className: this.props.theme.button, onClick: this.props.onDismiss, }, { label: this.props.okLabel, className: this.props.theme.button, name: this.props.name, onClick: this.handleSelect, }]; render() { const { theme } = this.props; const display = `${this.state.display}Display`; const className = classnames(theme.dialog, this.props.className); const headerClassName = classnames(theme.header, theme[display]); const shortDayOfWeek = time.getShortDayOfWeek(this.state.date.getDay(), this.props.locale); const shortMonth = time.getShortMonth(this.state.date, this.props.locale); const date = this.state.date.getDate(); return ( <Dialog actions={this.actions} active={this.props.active} className={className} onEscKeyDown={this.props.onEscKeyDown} onOverlayClick={this.props.onOverlayClick} type="custom" > <header className={headerClassName}> <span id="years" className={theme.year} onClick={this.handleSwitchDisplay}> {this.state.date.getFullYear()} </span> <h3 id="months" className={theme.date} onClick={this.handleSwitchDisplay}> {shortDayOfWeek}, {shortMonth} {date} </h3> </header> <div className={theme.calendarWrapper}> <Calendar disabledDates={this.props.disabledDates} display={this.state.display} enabledDates={this.props.enabledDates} handleSelect={this.handleSelect} maxDate={this.props.maxDate} minDate={this.props.minDate} onChange={this.handleNewDate} selectedDate={this.state.date} theme={this.props.theme} locale={this.props.locale} sundayFirstDayOfWeek={this.props.sundayFirstDayOfWeek} /> </div> </Dialog> ); } } return CalendarDialog; }; export default factory;