UNPKG

d2-ui

Version:
339 lines (288 loc) 8.79 kB
import React from 'react'; import StylePropable from '../mixins/style-propable'; import WindowListenable from '../mixins/window-listenable'; import DateTime from '../utils/date-time'; import DatePickerDialog from './date-picker-dialog'; import TextField from '../text-field'; import getMuiTheme from '../styles/getMuiTheme'; import deprecated from '../utils/deprecatedPropType'; import warning from 'warning'; const DatePicker = React.createClass({ propTypes: { /** * Constructor for time formatting. * Follow this specificaction: ECMAScript Internationalization API 1.0 (ECMA-402). */ DateTimeFormat: React.PropTypes.func, /** * If true, automatically accept and close the picker on select a date. */ autoOk: React.PropTypes.bool, /** * Used to control how the DatePicker will be displayed when a user tries to set a date. * `dialog` (default) displays the DatePicker as a dialog with a modal. * `inline` displays the DatePicker below the input field (similar to auto complete). */ container: React.PropTypes.oneOf(['dialog', 'inline']), /** * This is the initial date value of the component. * If either `value` or `valueLink` is provided they will override this * prop with `value` taking precedence. */ defaultDate: React.PropTypes.object, /** * Disables the year selection in the date picker. */ disableYearSelection: React.PropTypes.bool, /** * Disables the DatePicker. */ disabled: React.PropTypes.bool, /** * Used to change the first day of week. It drastically varies from * Saturday to Monday (could even be Friday) between different locales. * The allowed range is 0 (Sunday) to 6 (Saturday). */ firstDayOfWeek: React.PropTypes.number, /** * This function is called to format the date to display in the input box. * By default, date objects are formatted to MM/DD/YYYY. */ formatDate: React.PropTypes.func, /** * Locale used for formatting date. If you are not using the default value, you * have to provide a DateTimeFormat that supports it. You can use Intl.DateTimeFormat * if it's supported by your environment. * https://github.com/andyearnshaw/Intl.js is a good polyfill. */ locale: React.PropTypes.string, /** * The ending of a range of valid dates. The range includes the endDate. * The default value is current date + 100 years. */ maxDate: React.PropTypes.object, /** * The beginning of a range of valid dates. The range includes the startDate. * The default value is current date - 100 years. */ minDate: React.PropTypes.object, /** * Tells the component to display the picker in portrait or landscape mode. */ mode: React.PropTypes.oneOf(['portrait', 'landscape']), /** * Callback function that is fired when the date value changes. Since there * is no particular event associated with the change the first argument * will always be null and the second argument will be the new Date instance. */ onChange: React.PropTypes.func, /** * Fired when the datepicker dialog is dismissed. */ onDismiss: React.PropTypes.func, /** * Callback function that is fired when the datepicker field gains focus. */ onFocus: React.PropTypes.func, /** * Fired when the datepicker dialog is shown. */ onShow: React.PropTypes.func, /** * Called when touch tap event occurs on text-field. */ onTouchTap: React.PropTypes.func, /** * Called during render time of a given day. If this method returns * false the day is disabled otherwise it is displayed normally. */ shouldDisableDate: React.PropTypes.func, /** * Enables the year selection in the date picker. */ showYearSelector: deprecated(React.PropTypes.bool, 'Instead, use disableYearSelection.'), /** * Override the inline-styles of the root element. */ style: React.PropTypes.object, /** * Override the inline-styles of DatePicker's TextField element. */ textFieldStyle: React.PropTypes.object, /** * Sets the date for the Date Picker programmatically. */ value: React.PropTypes.any, /** * Creates a ValueLink with the value of date picker. */ valueLink: React.PropTypes.object, /** * Wordings used inside the button of the dialog. */ wordings: React.PropTypes.object, }, contextTypes: { muiTheme: React.PropTypes.object, }, //for passing default theme context to children childContextTypes: { muiTheme: React.PropTypes.object, }, mixins: [ StylePropable, WindowListenable, ], getDefaultProps() { return { formatDate: DateTime.format, autoOk: false, disableYearSelection: false, style: {}, firstDayOfWeek: 0, disabled: false, }; }, getInitialState() { return { date: this._isControlled() ? this._getControlledDate() : this.props.defaultDate, dialogDate: new Date(), muiTheme: this.context.muiTheme || getMuiTheme(), }; }, getChildContext() { return { muiTheme: this.state.muiTheme, }; }, componentWillReceiveProps(nextProps, nextContext) { if (nextContext.muiTheme) { this.setState({muiTheme: nextContext.muiTheme}); } if (this._isControlled()) { let newDate = this._getControlledDate(nextProps); if (!DateTime.isEqualDate(this.state.date, newDate)) { this.setState({ date: newDate, }); } } }, windowListeners: { keyup: '_handleWindowKeyUp', }, getDate() { return this.state.date; }, setDate(date) { warning(false, `setDate() method is deprecated. Use the defaultDate property instead. Or use the DatePicker as a controlled component with the value property.`); this.setState({ date: date, }); }, /** * Open the date-picker dialog programmatically from a parent. */ openDialog() { this.setState({ dialogDate: this.getDate(), }, this.refs.dialogWindow.show); }, /** * Alias for `openDialog()` for an api consistent with TextField. */ focus() { this.openDialog(); }, _handleDialogAccept(date) { if (!this._isControlled()) { this.setState({ date: date, }); } if (this.props.onChange) this.props.onChange(null, date); if (this.props.valueLink) this.props.valueLink.requestChange(date); }, _handleInputFocus(e) { e.target.blur(); if (this.props.onFocus) this.props.onFocus(e); }, _handleInputTouchTap: function _handleInputTouchTap(event) { if (this.props.onTouchTap) this.props.onTouchTap(event); if (!this.props.disabled) setTimeout(() => { this.openDialog(); }, 0); }, _handleWindowKeyUp() { //TO DO: open the dialog if input has focus }, _isControlled() { return this.props.hasOwnProperty('value') || this.props.hasOwnProperty('valueLink'); }, _getControlledDate(props = this.props) { if (DateTime.isDateObject(props.value)) { return props.value; } else if (props.valueLink && DateTime.isDateObject(props.valueLink.value)) { return props.valueLink.value; } }, render() { let { container, DateTimeFormat, locale, wordings, autoOk, defaultDate, formatDate, maxDate, minDate, mode, onDismiss, onFocus, onShow, onTouchTap, disableYearSelection, style, textFieldStyle, valueLink, firstDayOfWeek, ...other, } = this.props; return ( <div style={this.prepareStyles(style)}> <TextField {...other} style={textFieldStyle} ref="input" value={this.state.date ? formatDate(this.state.date) : undefined} onFocus={this._handleInputFocus} onTouchTap={this._handleInputTouchTap} /> <DatePickerDialog container={container} ref="dialogWindow" DateTimeFormat={DateTimeFormat} locale={locale} wordings={wordings} mode={mode} initialDate={this.state.dialogDate} onAccept={this._handleDialogAccept} onShow={onShow} onDismiss={onDismiss} minDate={minDate} maxDate={maxDate} autoOk={autoOk} disableYearSelection={disableYearSelection} shouldDisableDate={this.props.shouldDisableDate} firstDayOfWeek={firstDayOfWeek} /> </div> ); }, }); export default DatePicker;