From 90cb87796a91ec19887a7d443d5fa1860acf63dc Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 13 Feb 2018 15:43:30 +0200 Subject: [PATCH 01/22] Move all moment specific usages to utils --- .eslintrc | 3 +- docs/src/Demo/Demo.jsx | 4 +- lib/src/DatePicker/Calendar.jsx | 36 ++-- lib/src/DatePicker/CalendarHeader.jsx | 4 +- lib/src/DatePicker/DatePicker.jsx | 13 +- lib/src/DatePicker/DatePickerWrapper.jsx | 4 +- lib/src/DatePicker/YearSelection.jsx | 18 +- lib/src/DateTimePicker/DateTimePicker.jsx | 6 +- .../DateTimePicker/DateTimePickerHeader.jsx | 16 +- .../DateTimePicker/DateTimePickerWrapper.jsx | 4 +- lib/src/TimePicker/HourView.jsx | 13 +- lib/src/TimePicker/MinutesView.jsx | 9 +- lib/src/TimePicker/TimePicker.jsx | 8 +- lib/src/TimePicker/TimePickerWrapper.jsx | 4 +- lib/src/_shared/DateTextField.jsx | 34 ++-- lib/src/_shared/PickerBase.jsx | 14 +- lib/src/utils/utils.js | 167 ++++++++++++------ 17 files changed, 206 insertions(+), 151 deletions(-) diff --git a/.eslintrc b/.eslintrc index 514a8137e..e48fa5d9d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -7,7 +7,8 @@ "react/no-find-dom-node": 0, "no-param-reassign": 0, "import/no-named-as-default": 0, - "import/no-extraneous-dependencies": 0 + "import/no-extraneous-dependencies": 0, + "class-methods-use-this": 0 }, "globals": { "document": true diff --git a/docs/src/Demo/Demo.jsx b/docs/src/Demo/Demo.jsx index 30099f277..9d9d879bb 100644 --- a/docs/src/Demo/Demo.jsx +++ b/docs/src/Demo/Demo.jsx @@ -111,7 +111,7 @@ class Demo extends Component { - @@ -123,7 +123,7 @@ class Demo extends Component { sourceFile="PersianPickers.jsx" > - + */} ); diff --git a/lib/src/DatePicker/Calendar.jsx b/lib/src/DatePicker/Calendar.jsx index 722f9ffa2..be42e2e7a 100644 --- a/lib/src/DatePicker/Calendar.jsx +++ b/lib/src/DatePicker/Calendar.jsx @@ -2,8 +2,6 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import withStyles from 'material-ui/styles/withStyles'; -import Moment from 'moment'; -import { extendMoment } from 'moment-range'; import EventListener from 'react-event-listener'; import keycode from 'keycode'; import CalendarHeader from './CalendarHeader'; @@ -13,8 +11,6 @@ import DayWrapper from './DayWrapper'; import Day from './Day'; -const moment = extendMoment(Moment); - /* eslint-disable no-unused-expressions */ export class Calendar extends Component { static propTypes = { @@ -30,7 +26,7 @@ export class Calendar extends Component { renderDay: PropTypes.func, /** @ignore */ theme: PropTypes.object.isRequired, - utils: PropTypes.object, + utils: PropTypes.func, shouldDisableDate: PropTypes.func, }; @@ -71,20 +67,23 @@ export class Calendar extends Component { }; validateMinMaxDate = (day) => { - const { minDate, maxDate } = this.props; - const startOfDay = date => moment(date).startOf('day'); + const { minDate, maxDate, utils } = this.props; + const startOfDay = date => utils.startOfDay(utils.date(date)); return ( - (minDate && day.isBefore(startOfDay(minDate))) || - (maxDate && day.isAfter(startOfDay(maxDate))) + (minDate && utils.isBefore(day, startOfDay(minDate))) || + (maxDate && utils.isAfter(day, startOfDay(maxDate))) ); }; shouldDisableDate = (day) => { - const { disablePast, disableFuture, shouldDisableDate } = this.props; + const { + disablePast, disableFuture, shouldDisableDate, utils, + } = this.props; + return ( - (disableFuture && day.isAfter(moment(), 'day')) || - (disablePast && day.isBefore(moment(), 'day')) || + (disableFuture && utils.isAfterDay(day, utils.date())) || + (disablePast && utils.isBeforeDay(day, utils.date())) || this.validateMinMaxDate(day) || shouldDisableDate(day) ); @@ -145,22 +144,21 @@ export class Calendar extends Component { const { date, renderDay, utils } = this.props; const selectedDate = date.clone().startOf('day'); - const currentMonthNumber = utils.getMonthNumber(this.state.currentMonth); - const now = moment(); + const currentMonthNumber = utils.getMonth(this.state.currentMonth); + const now = utils.date(); return week.map((day) => { const disabled = this.shouldDisableDate(day); - const dayInCurrentMonth = - utils.getMonthNumber(day) === currentMonthNumber; + const dayInCurrentMonth = utils.getMonth(day) === currentMonthNumber; let dayComponent = ( ); diff --git a/lib/src/DatePicker/CalendarHeader.jsx b/lib/src/DatePicker/CalendarHeader.jsx index aca240e44..fe033acc8 100644 --- a/lib/src/DatePicker/CalendarHeader.jsx +++ b/lib/src/DatePicker/CalendarHeader.jsx @@ -30,7 +30,7 @@ export const CalendarHeader = (props) => { - {utils.getCalendarHeaderText(currentMonth)} + {utils.format(currentMonth, 'MMMM YYYY')} @@ -61,7 +61,7 @@ CalendarHeader.propTypes = { theme: PropTypes.object.isRequired, leftArrowIcon: PropTypes.node, rightArrowIcon: PropTypes.node, - utils: PropTypes.object, + utils: PropTypes.func, }; CalendarHeader.defaultProps = { diff --git a/lib/src/DatePicker/DatePicker.jsx b/lib/src/DatePicker/DatePicker.jsx index d2c389aaf..c42c70d55 100644 --- a/lib/src/DatePicker/DatePicker.jsx +++ b/lib/src/DatePicker/DatePicker.jsx @@ -1,6 +1,5 @@ import React, { PureComponent, Fragment } from 'react'; import PropTypes from 'prop-types'; -import moment from 'moment'; import Calendar from './Calendar'; import YearSelection from './YearSelection'; @@ -23,7 +22,7 @@ export class DatePicker extends PureComponent { leftArrowIcon: PropTypes.node, rightArrowIcon: PropTypes.node, renderDay: PropTypes.func, - utils: PropTypes.object, + utils: PropTypes.func, shouldDisableDate: PropTypes.func, } @@ -47,15 +46,15 @@ export class DatePicker extends PureComponent { } get date() { - return this.props.date.startOf('day'); + return this.props.utils.startOfDay(this.props.date); } get minDate() { - return moment(this.props.minDate); + return this.props.utils.date(this.props.minDate); } get maxDate() { - return moment(this.props.maxDate); + return this.props.utils.date(this.props.maxDate); } handleYearSelect = (date) => { @@ -92,14 +91,14 @@ export class DatePicker extends PureComponent { variant="subheading" onClick={this.openYearSelection} selected={showYearSelection} - label={utils.getYearText(this.date)} + label={utils.format(this.date, 'YYYY')} /> diff --git a/lib/src/DatePicker/DatePickerWrapper.jsx b/lib/src/DatePicker/DatePickerWrapper.jsx index 44af8980c..bca559ed0 100644 --- a/lib/src/DatePicker/DatePickerWrapper.jsx +++ b/lib/src/DatePicker/DatePickerWrapper.jsx @@ -5,7 +5,7 @@ import ModalWrapper from '../wrappers/ModalWrapper'; import DatePicker from './DatePicker'; import DomainPropTypes from '../constants/prop-types'; import PickerBase from '../_shared/PickerBase'; -import * as defaultUtils from '../utils/utils'; +import defaultUtils from '../utils/utils'; export default class DatePickerWrapper extends PickerBase { static propTypes = { @@ -42,7 +42,7 @@ export default class DatePickerWrapper extends PickerBase { /* Custom renderer for day renderDay(date, selectedDate, dayInCurrentMonth) */ renderDay: PropTypes.func, /* Date displaying utils */ - utils: PropTypes.object, + utils: PropTypes.func, /* Disable specific date hook */ shouldDisableDate: PropTypes.func, } diff --git a/lib/src/DatePicker/YearSelection.jsx b/lib/src/DatePicker/YearSelection.jsx index c42f3c0ee..83af13eaf 100644 --- a/lib/src/DatePicker/YearSelection.jsx +++ b/lib/src/DatePicker/YearSelection.jsx @@ -1,15 +1,11 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { findDOMNode } from 'react-dom'; -import Moment from 'moment'; -import { extendMoment } from 'moment-range'; import withStyles from 'material-ui/styles/withStyles'; import DomainPropTypes from '../constants/prop-types'; -import * as defaultUtils from '../utils/utils'; +import defaultUtils from '../utils/utils'; import Year from './Year'; -const moment = extendMoment(Moment); - export class YearSelection extends PureComponent { static propTypes = { date: PropTypes.shape({}).isRequired, @@ -20,7 +16,7 @@ export class YearSelection extends PureComponent { disablePast: PropTypes.bool.isRequired, disableFuture: PropTypes.bool.isRequired, animateYearScrolling: PropTypes.bool, - utils: PropTypes.object, + utils: PropTypes.func, } static defaultProps = { @@ -65,7 +61,7 @@ export class YearSelection extends PureComponent { return (
{ - Array.from(moment.range(minDate, maxDate).by('year')) + utils.getYearRange(minDate, maxDate) .map((year) => { const yearNumber = utils.getYear(year); const selected = yearNumber === currentYear; @@ -74,18 +70,18 @@ export class YearSelection extends PureComponent { - {utils.getYearText(year)} + {utils.format(year, 'YYYY')} ); }) diff --git a/lib/src/DateTimePicker/DateTimePicker.jsx b/lib/src/DateTimePicker/DateTimePicker.jsx index dfefef36d..bc31fad6b 100644 --- a/lib/src/DateTimePicker/DateTimePicker.jsx +++ b/lib/src/DateTimePicker/DateTimePicker.jsx @@ -12,7 +12,7 @@ import { convertToMeridiem } from '../utils/time-utils'; import DomainPropTypes from '../constants/prop-types'; import * as viewType from '../constants/date-picker-view'; -import * as defaultUtils from '../utils/utils'; +import defaultUtils from '../utils/utils'; export class DateTimePicker extends Component { static propTypes = { @@ -30,7 +30,7 @@ export class DateTimePicker extends Component { dateRangeIcon: PropTypes.node, timeIcon: PropTypes.node, renderDay: PropTypes.func, - utils: PropTypes.object, + utils: PropTypes.func, ampm: PropTypes.bool, shouldDisableDate: PropTypes.func, animateYearScrolling: PropTypes.bool, @@ -57,7 +57,7 @@ export class DateTimePicker extends Component { state = { openView: this.props.openTo, - meridiemMode: this.props.date.hours() >= 12 ? 'pm' : 'am', + meridiemMode: this.props.utils.getHours(this.props.date) >= 12 ? 'pm' : 'am', } onChange = (time, isFinish = true, nextView) => { diff --git a/lib/src/DateTimePicker/DateTimePickerHeader.jsx b/lib/src/DateTimePicker/DateTimePickerHeader.jsx index 14fad49ca..4e323a325 100644 --- a/lib/src/DateTimePicker/DateTimePickerHeader.jsx +++ b/lib/src/DateTimePicker/DateTimePickerHeader.jsx @@ -3,8 +3,8 @@ import PropTypes from 'prop-types'; import withStyles from 'material-ui/styles/withStyles'; import PickerToolbar from '../_shared/PickerToolbar'; import ToolbarButton from '../_shared/ToolbarButton'; +import defaultUtils from '../utils/utils'; import * as viewType from '../constants/date-picker-view'; -import * as defaultUtils from '../utils/utils'; export const DateTimePickerHeader = (props) => { const { @@ -15,7 +15,7 @@ export const DateTimePickerHeader = (props) => { const changeOpenView = view => () => onOpenViewChange(view); const rtl = theme.direction === 'rtl'; - const hourMinuteClassname = rtl + const hourMinuteClassName = rtl ? classes.hourMinuteLabelReverse : classes.hourMinuteLabel; @@ -26,24 +26,24 @@ export const DateTimePickerHeader = (props) => { variant="subheading" onClick={changeOpenView(viewType.YEAR)} selected={openView === viewType.YEAR} - label={utils.getYearText(date)} + label={utils.format(date, 'YYYY')} />
-
+
{ variant="display2" onClick={changeOpenView(viewType.MINUTES)} selected={openView === viewType.MINUTES} - label={utils.getMinuteText(date)} + label={utils.format(date, 'mm')} />
@@ -93,7 +93,7 @@ DateTimePickerHeader.propTypes = { openView: PropTypes.string.isRequired, onOpenViewChange: PropTypes.func.isRequired, setMeridiemMode: PropTypes.func.isRequired, - utils: PropTypes.object, + utils: PropTypes.func, ampm: PropTypes.bool, }; diff --git a/lib/src/DateTimePicker/DateTimePickerWrapper.jsx b/lib/src/DateTimePicker/DateTimePickerWrapper.jsx index 4e3deb9eb..369bfbaf3 100644 --- a/lib/src/DateTimePicker/DateTimePickerWrapper.jsx +++ b/lib/src/DateTimePicker/DateTimePickerWrapper.jsx @@ -7,7 +7,7 @@ import DomainPropTypes from '../constants/prop-types'; import ModalWrapper from '../wrappers/ModalWrapper'; import DateTimePicker from './DateTimePicker'; import PickerBase from '../_shared/PickerBase'; -import * as defaultUtils from '../utils/utils'; +import defaultUtils from '../utils/utils'; export class DateTimePickerWrapper extends PickerBase { static propTypes = { @@ -30,7 +30,7 @@ export class DateTimePickerWrapper extends PickerBase { timeIcon: PropTypes.node, renderDay: PropTypes.func, labelFunc: PropTypes.func, - utils: PropTypes.object, + utils: PropTypes.func, ampm: PropTypes.bool, shouldDisableDate: PropTypes.func, animateYearScrolling: PropTypes.bool, diff --git a/lib/src/TimePicker/HourView.jsx b/lib/src/TimePicker/HourView.jsx index 59cbd6ad2..42017fed9 100644 --- a/lib/src/TimePicker/HourView.jsx +++ b/lib/src/TimePicker/HourView.jsx @@ -3,14 +3,14 @@ import PropTypes from 'prop-types'; import Clock from './Clock'; import { HOURS } from '../constants/clock-types'; import ClockNumber from './ClockNumber'; -import * as defaultUtils from '../utils/utils'; +import defaultUtils from '../utils/utils'; export default class HourView extends PureComponent { static propTypes = { date: PropTypes.object.isRequired, onChange: PropTypes.func.isRequired, - utils: PropTypes.object, + utils: PropTypes.func, ampm: PropTypes.bool, } @@ -22,7 +22,7 @@ export default class HourView extends PureComponent { getHourNumbers = () => { const { ampm, utils, date } = this.props; - const currentHours = date.get('hours'); + const currentHours = utils.getHours(date); const hourNumbers = []; const startHour = ampm ? 1 : 0; @@ -62,14 +62,15 @@ export default class HourView extends PureComponent { } handleChange = (hours, isFinish) => { - const updatedTime = this.props.date.clone().hour(hours); + const { date, utils } = this.props; + const updatedTime = utils.setHours(date, hours); this.props.onChange(updatedTime, isFinish); } render() { - const { date, ampm } = this.props; - const value = date.get('hours'); + const { date, ampm, utils } = this.props; + const value = utils.getHours(date); return ( { - const updatedDate = this.props.date.clone().minutes(minutes); + const { date, utils } = this.props; + const updatedDate = utils.setMinutes(date, minutes); this.props.onChange(updatedDate, isFinish); } @@ -25,7 +26,7 @@ export default class MinutesView extends Component { const { date, utils } = this.props; const f = utils.formatNumber; - const value = date.get('minutes'); + const value = utils.getMinutes(date); return (
diff --git a/lib/src/TimePicker/TimePickerWrapper.jsx b/lib/src/TimePicker/TimePickerWrapper.jsx index 6e91555d1..e2e93588f 100644 --- a/lib/src/TimePicker/TimePickerWrapper.jsx +++ b/lib/src/TimePicker/TimePickerWrapper.jsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import ModalWrapper from '../wrappers/ModalWrapper'; import TimePicker from './TimePicker'; import PickerBase from '../_shared/PickerBase'; -import * as defaultUtils from '../utils/utils'; +import defaultUtils from '../utils/utils'; export default class TimePickerWrapper extends PickerBase { static propTypes = { @@ -19,7 +19,7 @@ export default class TimePickerWrapper extends PickerBase { autoOk: PropTypes.bool, returnMoment: PropTypes.bool, invalidLabel: PropTypes.string, - utils: PropTypes.object, + utils: PropTypes.func, ampm: PropTypes.bool, } diff --git a/lib/src/_shared/DateTextField.jsx b/lib/src/_shared/DateTextField.jsx index 2823907d4..e23dd28e2 100644 --- a/lib/src/_shared/DateTextField.jsx +++ b/lib/src/_shared/DateTextField.jsx @@ -1,7 +1,6 @@ /* eslint-disable react/sort-comp */ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import moment from 'moment'; import Icon from 'material-ui/Icon'; import InputAdornment from 'material-ui/Input/InputAdornment'; import TextField from 'material-ui/TextField'; @@ -10,6 +9,7 @@ import withStyles from 'material-ui/styles/withStyles'; import DomainPropTypes from '../constants/prop-types'; import MaskedInput from './MaskedInput'; +import defaultUtils from '../utils/utils'; class DateTextField extends PureComponent { static propTypes = { @@ -41,6 +41,7 @@ class DateTextField extends PureComponent { invalidDateMessage: PropTypes.string, clearable: PropTypes.bool, TextFieldComponent: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), + utils: PropTypes.func, } static defaultProps = { @@ -64,15 +65,16 @@ class DateTextField extends PureComponent { minDateMessage: 'Date should not be before minimal date', maxDateMessage: 'Date should not be after maximal date', TextFieldComponent: TextField, + utils: defaultUtils, } getDisplayDate = (props) => { const { - value, format, invalidLabel, emptyLabel, labelFunc, + utils, value, format, invalidLabel, emptyLabel, labelFunc, } = props; const isEmpty = value === null; - const date = moment(value); + const date = utils.date(value); if (labelFunc) { return labelFunc(isEmpty ? null : date, invalidLabel); @@ -82,13 +84,14 @@ class DateTextField extends PureComponent { return emptyLabel; } - return date.isValid() - ? date.format(format) + return utils.isValid(date) + ? utils.format(date, format) : invalidLabel; } getError = (value) => { const { + utils, maxDate, minDate, disablePast, @@ -98,24 +101,24 @@ class DateTextField extends PureComponent { invalidDateMessage, } = this.props; - if (!value.isValid()) { + if (!utils.isValid(value)) { // if null - do not show error - if (value.parsingFlags().nullInput) { + if (utils.isNull(value)) { return ''; } return invalidDateMessage; } if ( - (maxDate && value.isAfter(maxDate)) || - (disableFuture && value.isAfter(moment().endOf('day'))) + (maxDate && utils.isAfter(value, maxDate)) || + (disableFuture && utils.isAfter(value, utils.endOfDay(utils.date()))) ) { return maxDateMessage; } if ( - (minDate && value.isBefore(minDate)) || - (disablePast && value.isBefore(moment().startOf('day'))) + (minDate && utils.isBefore(value, minDate)) || + (disablePast && utils.isBefore(value, utils.startOfDay(utils.date()))) ) { return minDateMessage; } @@ -126,7 +129,7 @@ class DateTextField extends PureComponent { updateState = (props = this.props) => ({ value: props.value, displayValue: this.getDisplayDate(props), - error: this.getError(moment(props.value)), + error: this.getError(props.utils.date(props.value)), }) state = this.updateState() @@ -150,6 +153,7 @@ class DateTextField extends PureComponent { format, clearable, onClear, + utils, } = this.props; if (clearable && e.target.value === '') { @@ -162,8 +166,8 @@ class DateTextField extends PureComponent { return; } - const oldValue = moment(this.state.value); - const newValue = moment(e.target.value, format, true); + const oldValue = utils.date(this.state.value); + const newValue = utils.date(e.target.value, format, true); const error = this.getError(newValue); this.setState({ @@ -171,7 +175,7 @@ class DateTextField extends PureComponent { value: error ? newValue : oldValue, error, }, () => { - if (!error && newValue.format('LLLL') !== oldValue.format('LLLL')) { + if (!error && utils.format(newValue, 'LLLL') !== utils.format(oldValue, 'LLLL')) { this.props.onChange(newValue, true); } }); diff --git a/lib/src/_shared/PickerBase.jsx b/lib/src/_shared/PickerBase.jsx index 3bfdc9b37..aa7c75e21 100644 --- a/lib/src/_shared/PickerBase.jsx +++ b/lib/src/_shared/PickerBase.jsx @@ -1,7 +1,7 @@ import { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import moment from 'moment'; import DomainPropTypes from '../constants/prop-types'; +import defaultUtils from '../utils/utils'; /* eslint-disable react/sort-comp */ export default class PickerBase extends PureComponent { @@ -13,6 +13,7 @@ export default class PickerBase extends PureComponent { format: PropTypes.string, labelFunc: PropTypes.func, ampm: PropTypes.bool, + utils: PropTypes.func, } static defaultProps = { @@ -22,12 +23,15 @@ export default class PickerBase extends PureComponent { labelFunc: undefined, format: undefined, ampm: true, + utils: defaultUtils, } - getValidDateOrCurrent = (props = this.props) => { - const date = moment(props.value); + getValidDateOrCurrent = () => { + const { utils, value } = this.props; + console.log(this.props.utils); + const date = utils.date(value); - return date.isValid() ? date : moment(); + return utils.isValid(date) ? date : utils.date(); } state = { @@ -59,7 +63,7 @@ export default class PickerBase extends PureComponent { handleAccept = () => { const dateToReturn = this.props.returnMoment ? this.state.date - : this.state.date.toDate(); + : this.props.utils.toNativeDate(this.state.date); this.props.onChange(dateToReturn); } diff --git a/lib/src/utils/utils.js b/lib/src/utils/utils.js index b29549cf6..5c354571d 100644 --- a/lib/src/utils/utils.js +++ b/lib/src/utils/utils.js @@ -3,82 +3,133 @@ import { extendMoment } from 'moment-range'; const moment = extendMoment(Moment); -export function formatNumber(num) { - return num; -} +export default class Utils { + static date(value) { + return moment(value); + } -export function getCalendarHeaderText(date) { - return date.format('MMMM YYYY'); -} + static isValid(date) { + return date.isValid(); + } -export function getDatePickerHeaderText(date) { - return date.format('ddd, MMM D'); -} + static isNull(date) { + return date.parsingFlags().nullInput; + } -export function getDateTimePickerHeaderText(date) { - return date.format('MMM D'); -} + static isAfter(date, value) { + return date.isAfter(value); + } -export function getDayText(date) { - return date.format('D'); -} + static isBefore(date, value) { + return date.isBefore(value); + } -export function getHourText(date, ampm) { - return date.format(ampm ? 'hh' : 'HH'); -} + static isAfterDay(date, value) { + return date.isAfter(value, 'day'); + } -export function getMinuteText(date) { - return date.format('mm'); -} + static isBeforeDay(date, value) { + return date.isBefore(value, 'day'); + } -export function getMeridiemText(ampm) { - return ampm === 'am' ? 'AM' : 'PM'; -} + static isBeforeYear(date, value) { + return date.isBefore(value, 'year'); + } -export function getYearText(date) { - return date.format('YYYY'); -} + static isAfterYear(date, value) { + return date.isAfter(value, 'year'); + } -export function getMonthNumber(date) { - return date.get('month'); -} + static startOfDay(date) { + return date.startOf('day'); + } -export function getStartOfMonth(date) { - return date.clone().startOf('month'); -} + static endOfDay(date) { + return date.endOf('day'); + } -export function getNextMonth(date) { - return date.clone().add(1, 'month'); -} + static format(date, formatString) { + return date.format(formatString); + } -export function getPreviousMonth(date) { - return date.clone().subtract(1, 'month'); -} + static formatNumber(num) { + return num; + } -export function getYear(date) { - return date.get('year'); -} + static getHours(date) { + return date.get('hours'); + } -export function setYear(date, year) { - return date.clone().set('year', year); -} + static setHours(date, value) { + return date.clone().hours(value); + } -export function getWeekdays() { - return [0, 1, 2, 3, 4, 5, 6].map(dayOfWeek => moment().weekday(dayOfWeek).format('dd')[0]); -} + static getMinutes(date) { + return date.get('minutes'); + } + + static setMinutes(date, value) { + return date.clone().minutes(value); + } + + static getMonth(date) { + return date.get('month'); + } + + + static isSameDay(date, comparing) { + return date.isSame(comparing, 'day'); + } + + static getMeridiemText(ampm) { + return ampm === 'am' ? 'AM' : 'PM'; + } + + static getStartOfMonth(date) { + return date.clone().startOf('month'); + } + + static getNextMonth(date) { + return date.clone().add(1, 'month'); + } + + static getPreviousMonth(date) { + return date.clone().subtract(1, 'month'); + } + + static getYear(date) { + return date.get('year'); + } + + static setYear(date, year) { + return date.clone().set('year', year); + } + + static getWeekdays() { + return [0, 1, 2, 3, 4, 5, 6].map(dayOfWeek => moment().weekday(dayOfWeek).format('dd')[0]); + } + + static getWeekArray(date) { + const start = date.clone().startOf('month').startOf('week'); + const end = date.clone().endOf('month').endOf('week'); + + const weeks = Array.from(moment.range(start, end).by('week')); -export function getWeekArray(date) { - const start = date.clone().startOf('month').startOf('week'); - const end = date.clone().endOf('month').endOf('week'); + const nestedWeeks = []; - const weeks = Array.from(moment.range(start, end).by('week')); + weeks.forEach((week) => { + const endOfWeek = week.clone().endOf('week'); + nestedWeeks.push(Array.from(moment.range(week, endOfWeek).by('day'))); + }); - const nestedWeeks = []; + return nestedWeeks; + } - weeks.forEach((week) => { - const endOfWeek = week.clone().endOf('week'); - nestedWeeks.push(Array.from(moment.range(week, endOfWeek).by('day'))); - }); + static getYearRange(start, end) { + return Array.from(moment.range(start, end).by('year')); + } - return nestedWeeks; + static toNativeDate(date) { + return date.toDate(); + } } From fc9402dd2d39268ecbc6354162fac7cd02b95be0 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 20 Feb 2018 14:33:09 +0200 Subject: [PATCH 02/22] Move missing moment usages to utils --- lib/src/DatePicker/Calendar.jsx | 29 +++++++++++++---------------- lib/src/TimePicker/TimePicker.jsx | 2 +- lib/src/utils/time-utils.js | 10 +++++----- lib/src/utils/utils.js | 9 ++++++++- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/lib/src/DatePicker/Calendar.jsx b/lib/src/DatePicker/Calendar.jsx index be42e2e7a..56e6a1034 100644 --- a/lib/src/DatePicker/Calendar.jsx +++ b/lib/src/DatePicker/Calendar.jsx @@ -53,13 +53,11 @@ export class Calendar extends Component { } onDateSelect = (day) => { - const { date } = this.props; - const updatedDate = day - .clone() - .hours(date.hours()) - .minutes(date.minutes()); + const { date, utils } = this.props; + const withHours = utils.setHours(day, utils.setMinutes(date)); + const withMinutes = utils.setMinutes(withHours, utils.getMinutes(date)); - this.props.onChange(updatedDate); + this.props.onChange(withMinutes); }; handleChangeMonth = (newMonth) => { @@ -96,24 +94,24 @@ export class Calendar extends Component { } handleKeyDown = (event) => { - const { theme, date } = this.props; + const { theme, date, utils } = this.props; switch (keycode(event)) { case 'up': - this.moveToDay(date.clone().subtract(7, 'days')); + this.moveToDay(utils.addDays(date, -7)); break; case 'down': - this.moveToDay(date.clone().add(7, 'days')); + this.moveToDay(utils.addDays(date, 7)); break; case 'left': theme.direction === 'ltr' - ? this.moveToDay(date.clone().subtract(1, 'day')) - : this.moveToDay(date.clone().add(1, 'day')); + ? this.moveToDay(utils.addDays(date, -1)) + : this.moveToDay(utils.addDays(date, 1)); break; case 'right': theme.direction === 'ltr' - ? this.moveToDay(date.clone().add(1, 'day')) - : this.moveToDay(date.clone().subtract(1, 'day')); + ? this.moveToDay(utils.addDays(date, 1)) + : this.moveToDay(utils.addDays(date, -1)); break; default: // if keycode is not handled, stop execution @@ -137,13 +135,12 @@ export class Calendar extends Component { {this.renderDays(week)}
)); - }; - + } renderDays = (week) => { const { date, renderDay, utils } = this.props; - const selectedDate = date.clone().startOf('day'); + const selectedDate = utils.startOfDay(date); const currentMonthNumber = utils.getMonth(this.state.currentMonth); const now = utils.date(); diff --git a/lib/src/TimePicker/TimePicker.jsx b/lib/src/TimePicker/TimePicker.jsx index 2b5eb2ff1..ee0d688fd 100644 --- a/lib/src/TimePicker/TimePicker.jsx +++ b/lib/src/TimePicker/TimePicker.jsx @@ -27,7 +27,7 @@ export class TimePicker extends Component { state = { isHourViewShown: true, - meridiemMode: this.props.date.hours() >= 12 ? 'pm' : 'am', + meridiemMode: this.props.utils.getHours(this.props.date) >= 12 ? 'pm' : 'am', } setMeridiemMode = mode => () => { diff --git a/lib/src/utils/time-utils.js b/lib/src/utils/time-utils.js index 4dedf4552..affd5f17b 100644 --- a/lib/src/utils/time-utils.js +++ b/lib/src/utils/time-utils.js @@ -54,15 +54,15 @@ export const getMinutes = (offsetX, offsetY, step = 6) => { return value; }; -export const convertToMeridiem = (time, meridiem, ampm) => { +export const convertToMeridiem = (time, meridiem, ampm, utils) => { if (ampm) { - const currentMeridiem = time.hours() >= 12 ? 'pm' : 'am'; + const currentMeridiem = utils.getHours(time) >= 12 ? 'pm' : 'am'; if (currentMeridiem !== meridiem) { const hours = meridiem === 'am' - ? time.hours() - 12 - : time.hours() + 12; + ? utils.getHours(time) - 12 + : utils.getHours(time) + 12; - return time.clone().hours(hours); + return utils.setHours(time, hours); } } diff --git a/lib/src/utils/utils.js b/lib/src/utils/utils.js index 5c354571d..17ca75a4f 100644 --- a/lib/src/utils/utils.js +++ b/lib/src/utils/utils.js @@ -60,6 +60,14 @@ export default class Utils { return date.get('hours'); } + static addDays(date, count) { + if (count < 0) { + date.clone().subtract(Math.abs(count)); + } else { + date.clone().add(count); + } + } + static setHours(date, value) { return date.clone().hours(value); } @@ -76,7 +84,6 @@ export default class Utils { return date.get('month'); } - static isSameDay(date, comparing) { return date.isSame(comparing, 'day'); } From 9f2d8fbbb682956a9db07a5f95947f1290064b67 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 20 Feb 2018 15:15:44 +0200 Subject: [PATCH 03/22] Add date-fns utils --- docs/src/Demo/Demo.jsx | 4 +- docs/src/Demo/Examples/BasicUsage.jsx | 3 +- docs/src/Demo/Examples/DateTimePickers.jsx | 1 - lib/package-lock.json | 916 ++++++++++++++++++++- lib/package.json | 1 + lib/src/DatePicker/Calendar.jsx | 3 +- lib/src/DateTimePicker/DateTimePicker.jsx | 4 +- lib/src/TimePicker/Clock.jsx | 2 +- lib/src/TimePicker/TimePicker.jsx | 4 +- lib/src/{utils => _helpers}/time-utils.js | 0 lib/src/_shared/PickerBase.jsx | 1 - lib/src/utils/moment-utils.js | 142 ++++ lib/src/utils/utils.js | 141 ++-- 13 files changed, 1135 insertions(+), 87 deletions(-) rename lib/src/{utils => _helpers}/time-utils.js (100%) create mode 100644 lib/src/utils/moment-utils.js diff --git a/docs/src/Demo/Demo.jsx b/docs/src/Demo/Demo.jsx index 9d9d879bb..a942f2a56 100644 --- a/docs/src/Demo/Demo.jsx +++ b/docs/src/Demo/Demo.jsx @@ -103,7 +103,7 @@ class Demo extends Component { > - + {/* - {/* diff --git a/docs/src/Demo/Examples/BasicUsage.jsx b/docs/src/Demo/Examples/BasicUsage.jsx index 382382aa0..5da9afe94 100644 --- a/docs/src/Demo/Examples/BasicUsage.jsx +++ b/docs/src/Demo/Examples/BasicUsage.jsx @@ -1,11 +1,10 @@ import React, { Fragment, Component } from 'react'; -import moment from 'moment'; import { Typography } from 'material-ui'; import { TimePicker, DatePicker } from 'material-ui-pickers'; export default class BasicUsage extends Component { state = { - selectedDate: moment(), + selectedDate: new Date(), } handleDateChange = (date) => { diff --git a/docs/src/Demo/Examples/DateTimePickers.jsx b/docs/src/Demo/Examples/DateTimePickers.jsx index 5ad9db726..03b6b6e0b 100644 --- a/docs/src/Demo/Examples/DateTimePickers.jsx +++ b/docs/src/Demo/Examples/DateTimePickers.jsx @@ -1,7 +1,6 @@ import React, { Fragment, Component } from 'react'; import { DateTimePicker } from 'material-ui-pickers'; import { IconButton, Typography, Icon, InputAdornment } from 'material-ui'; -import moment from 'moment'; export default class BasicUsage extends Component { state = { diff --git a/lib/package-lock.json b/lib/package-lock.json index f771955b6..1c071994e 100644 --- a/lib/package-lock.json +++ b/lib/package-lock.json @@ -1630,6 +1630,7 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", + "fsevents": "1.1.3", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -1983,8 +1984,7 @@ "date-fns": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", - "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==", - "dev": true + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" }, "debug": { "version": "2.6.9", @@ -3005,6 +3005,910 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -5517,6 +6421,13 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "dev": true, + "optional": true + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6999,6 +7910,7 @@ "anymatch": "1.3.2", "exec-sh": "0.2.1", "fb-watchman": "2.0.0", + "fsevents": "1.1.3", "minimatch": "3.0.4", "minimist": "1.2.0", "walker": "1.0.7", diff --git a/lib/package.json b/lib/package.json index 4858f0e6f..ff7bea32d 100644 --- a/lib/package.json +++ b/lib/package.json @@ -40,6 +40,7 @@ "react-dom": "^16.2.0" }, "dependencies": { + "date-fns": "^1.29.0", "moment-range": "^3.0.3", "react-text-mask": "^5.0.2" }, diff --git a/lib/src/DatePicker/Calendar.jsx b/lib/src/DatePicker/Calendar.jsx index 56e6a1034..7d59f3763 100644 --- a/lib/src/DatePicker/Calendar.jsx +++ b/lib/src/DatePicker/Calendar.jsx @@ -54,7 +54,8 @@ export class Calendar extends Component { onDateSelect = (day) => { const { date, utils } = this.props; - const withHours = utils.setHours(day, utils.setMinutes(date)); + + const withHours = utils.setHours(day, utils.getHours(date)); const withMinutes = utils.setMinutes(withHours, utils.getMinutes(date)); this.props.onChange(withMinutes); diff --git a/lib/src/DateTimePicker/DateTimePicker.jsx b/lib/src/DateTimePicker/DateTimePicker.jsx index bc31fad6b..7ea19ca36 100644 --- a/lib/src/DateTimePicker/DateTimePicker.jsx +++ b/lib/src/DateTimePicker/DateTimePicker.jsx @@ -8,7 +8,7 @@ import HourView from '../TimePicker/HourView'; import MinutesView from '../TimePicker/MinutesView'; import DateTimePickerTabs from './DateTimePickerTabs'; import DatetimePickerHeader from './DateTimePickerHeader'; -import { convertToMeridiem } from '../utils/time-utils'; +import { convertToMeridiem } from '../_helpers/time-utils'; import DomainPropTypes from '../constants/prop-types'; import * as viewType from '../constants/date-picker-view'; @@ -80,7 +80,7 @@ export class DateTimePicker extends Component { } handleChange = (time, isFinish = false) => { - const withMeridiem = convertToMeridiem(time, this.state.meridiemMode, this.props.ampm); + const withMeridiem = convertToMeridiem(time, this.state.meridiemMode, this.props.ampm, this.props.utils); this.props.onChange(withMeridiem, isFinish); } diff --git a/lib/src/TimePicker/Clock.jsx b/lib/src/TimePicker/Clock.jsx index 0d7d4066b..945139557 100644 --- a/lib/src/TimePicker/Clock.jsx +++ b/lib/src/TimePicker/Clock.jsx @@ -4,7 +4,7 @@ import withStyles from 'material-ui/styles/withStyles'; import ClockPointer from './ClockPointer'; import * as clockType from '../constants/clock-types'; -import { getMinutes, getHours } from '../utils/time-utils'; +import { getMinutes, getHours } from '../_helpers/time-utils'; export class Clock extends Component { static propTypes = { diff --git a/lib/src/TimePicker/TimePicker.jsx b/lib/src/TimePicker/TimePicker.jsx index ee0d688fd..327c7ddf7 100644 --- a/lib/src/TimePicker/TimePicker.jsx +++ b/lib/src/TimePicker/TimePicker.jsx @@ -5,7 +5,7 @@ import PickerToolbar from '../_shared/PickerToolbar'; import ToolbarButton from '../_shared/ToolbarButton'; import HourView from './HourView'; import MinutesView from './MinutesView'; -import { convertToMeridiem } from '../utils/time-utils'; +import { convertToMeridiem } from '../_helpers/time-utils'; import defaultUtils from '../utils/utils'; export class TimePicker extends Component { @@ -38,7 +38,7 @@ export class TimePicker extends Component { } handleChange(time, isFinish, openMinutes) { - const withMeridiem = convertToMeridiem(time, this.state.meridiemMode, this.props.ampm); + const withMeridiem = convertToMeridiem(time, this.state.meridiemMode, this.props.ampm, this.props.utils); if (isFinish) { if (!openMinutes) { diff --git a/lib/src/utils/time-utils.js b/lib/src/_helpers/time-utils.js similarity index 100% rename from lib/src/utils/time-utils.js rename to lib/src/_helpers/time-utils.js diff --git a/lib/src/_shared/PickerBase.jsx b/lib/src/_shared/PickerBase.jsx index aa7c75e21..249484188 100644 --- a/lib/src/_shared/PickerBase.jsx +++ b/lib/src/_shared/PickerBase.jsx @@ -28,7 +28,6 @@ export default class PickerBase extends PureComponent { getValidDateOrCurrent = () => { const { utils, value } = this.props; - console.log(this.props.utils); const date = utils.date(value); return utils.isValid(date) ? date : utils.date(); diff --git a/lib/src/utils/moment-utils.js b/lib/src/utils/moment-utils.js new file mode 100644 index 000000000..17ca75a4f --- /dev/null +++ b/lib/src/utils/moment-utils.js @@ -0,0 +1,142 @@ +import Moment from 'moment'; +import { extendMoment } from 'moment-range'; + +const moment = extendMoment(Moment); + +export default class Utils { + static date(value) { + return moment(value); + } + + static isValid(date) { + return date.isValid(); + } + + static isNull(date) { + return date.parsingFlags().nullInput; + } + + static isAfter(date, value) { + return date.isAfter(value); + } + + static isBefore(date, value) { + return date.isBefore(value); + } + + static isAfterDay(date, value) { + return date.isAfter(value, 'day'); + } + + static isBeforeDay(date, value) { + return date.isBefore(value, 'day'); + } + + static isBeforeYear(date, value) { + return date.isBefore(value, 'year'); + } + + static isAfterYear(date, value) { + return date.isAfter(value, 'year'); + } + + static startOfDay(date) { + return date.startOf('day'); + } + + static endOfDay(date) { + return date.endOf('day'); + } + + static format(date, formatString) { + return date.format(formatString); + } + + static formatNumber(num) { + return num; + } + + static getHours(date) { + return date.get('hours'); + } + + static addDays(date, count) { + if (count < 0) { + date.clone().subtract(Math.abs(count)); + } else { + date.clone().add(count); + } + } + + static setHours(date, value) { + return date.clone().hours(value); + } + + static getMinutes(date) { + return date.get('minutes'); + } + + static setMinutes(date, value) { + return date.clone().minutes(value); + } + + static getMonth(date) { + return date.get('month'); + } + + static isSameDay(date, comparing) { + return date.isSame(comparing, 'day'); + } + + static getMeridiemText(ampm) { + return ampm === 'am' ? 'AM' : 'PM'; + } + + static getStartOfMonth(date) { + return date.clone().startOf('month'); + } + + static getNextMonth(date) { + return date.clone().add(1, 'month'); + } + + static getPreviousMonth(date) { + return date.clone().subtract(1, 'month'); + } + + static getYear(date) { + return date.get('year'); + } + + static setYear(date, year) { + return date.clone().set('year', year); + } + + static getWeekdays() { + return [0, 1, 2, 3, 4, 5, 6].map(dayOfWeek => moment().weekday(dayOfWeek).format('dd')[0]); + } + + static getWeekArray(date) { + const start = date.clone().startOf('month').startOf('week'); + const end = date.clone().endOf('month').endOf('week'); + + const weeks = Array.from(moment.range(start, end).by('week')); + + const nestedWeeks = []; + + weeks.forEach((week) => { + const endOfWeek = week.clone().endOf('week'); + nestedWeeks.push(Array.from(moment.range(week, endOfWeek).by('day'))); + }); + + return nestedWeeks; + } + + static getYearRange(start, end) { + return Array.from(moment.range(start, end).by('year')); + } + + static toNativeDate(date) { + return date.toDate(); + } +} diff --git a/lib/src/utils/utils.js b/lib/src/utils/utils.js index 17ca75a4f..b165db37d 100644 --- a/lib/src/utils/utils.js +++ b/lib/src/utils/utils.js @@ -1,142 +1,137 @@ -import Moment from 'moment'; -import { extendMoment } from 'moment-range'; - -const moment = extendMoment(Moment); +import addDays from 'date-fns/add_days'; +import addMonths from 'date-fns/add_months'; +import addYears from 'date-fns/add_years'; +import endOfDay from 'date-fns/end_of_day'; +import endOfMonth from 'date-fns/end_of_month'; +import endOfWeek from 'date-fns/end_of_week'; +import endOfYear from 'date-fns/end_of_year'; +import format from 'date-fns/format'; +import isAfter from 'date-fns/is_after'; +import isBefore from 'date-fns/is_before'; +import isSameDay from 'date-fns/is_same_day'; +import isValid from 'date-fns/is_valid'; +import setDay from 'date-fns/set_day'; +import setHours from 'date-fns/set_hours'; +import setMinutes from 'date-fns/set_minutes'; +import setYear from 'date-fns/set_year'; +import startOfDay from 'date-fns/start_of_day'; +import startOfMonth from 'date-fns/start_of_month'; +import startOfWeek from 'date-fns/start_of_week'; +import startOfYear from 'date-fns/start_of_year'; +import getHours from 'date-fns/get_hours'; +import getYear from 'date-fns/get_year'; export default class Utils { static date(value) { - return moment(value); + return value; } - static isValid(date) { - return date.isValid(); - } + static isValid = isValid static isNull(date) { - return date.parsingFlags().nullInput; + return date == null; } - static isAfter(date, value) { - return date.isAfter(value); - } + static isAfter = isAfter - static isBefore(date, value) { - return date.isBefore(value); - } + static isBefore = isBefore static isAfterDay(date, value) { - return date.isAfter(value, 'day'); + return isAfter(endOfDay(date), value); } static isBeforeDay(date, value) { - return date.isBefore(value, 'day'); + return isBefore(startOfDay(date), value); } static isBeforeYear(date, value) { - return date.isBefore(value, 'year'); + return isBefore(startOfYear(date), value); } static isAfterYear(date, value) { - return date.isAfter(value, 'year'); + return isAfter(endOfYear(date), value); } - static startOfDay(date) { - return date.startOf('day'); - } + static startOfDay = startOfDay - static endOfDay(date) { - return date.endOf('day'); - } + static endOfDay = endOfDay - static format(date, formatString) { - return date.format(formatString); - } + static format = format static formatNumber(num) { return num; } - static getHours(date) { - return date.get('hours'); - } - - static addDays(date, count) { - if (count < 0) { - date.clone().subtract(Math.abs(count)); - } else { - date.clone().add(count); - } - } + static getHours = getHours - static setHours(date, value) { - return date.clone().hours(value); - } + static setHours = setHours static getMinutes(date) { - return date.get('minutes'); + return date.getMinutes(); } - static setMinutes(date, value) { - return date.clone().minutes(value); - } + static setMinutes = setMinutes static getMonth(date) { - return date.get('month'); + return date.getMonth(); } - static isSameDay(date, comparing) { - return date.isSame(comparing, 'day'); - } + + static isSameDay = isSameDay; static getMeridiemText(ampm) { return ampm === 'am' ? 'AM' : 'PM'; } - static getStartOfMonth(date) { - return date.clone().startOf('month'); - } + static getStartOfMonth = startOfMonth static getNextMonth(date) { - return date.clone().add(1, 'month'); + return addMonths(date, 1); } static getPreviousMonth(date) { - return date.clone().subtract(1, 'month'); + return addMonths(date, -1); } - static getYear(date) { - return date.get('year'); - } + static getYear = getYear - static setYear(date, year) { - return date.clone().set('year', year); - } + static setYear = setYear; static getWeekdays() { - return [0, 1, 2, 3, 4, 5, 6].map(dayOfWeek => moment().weekday(dayOfWeek).format('dd')[0]); + return [0, 1, 2, 3, 4, 5, 6].map(dayOfWeek => format(setDay(new Date(), dayOfWeek), 'dd')); } static getWeekArray(date) { - const start = date.clone().startOf('month').startOf('week'); - const end = date.clone().endOf('month').endOf('week'); - - const weeks = Array.from(moment.range(start, end).by('week')); + const start = startOfWeek(startOfMonth(date)); + const end = endOfWeek(endOfMonth(date)); const nestedWeeks = []; - - weeks.forEach((week) => { - const endOfWeek = week.clone().endOf('week'); - nestedWeeks.push(Array.from(moment.range(week, endOfWeek).by('day'))); - }); + let count = 0; + let current = start; + while (isBefore(current, end)) { + const weekNumber = Math.floor(count / 7); + nestedWeeks[weekNumber] = nestedWeeks[weekNumber] || []; + nestedWeeks[weekNumber].push(current); + current = addDays(current, 1); + count += 1; + } return nestedWeeks; } static getYearRange(start, end) { - return Array.from(moment.range(start, end).by('year')); + const startDate = new Date(start); + const endDate = new Date(end); + const years = []; + let current = startDate; + while (isBefore(current, endDate)) { + years.push(current); + current = addYears(current, 1); + } + return years; } static toNativeDate(date) { - return date.toDate(); + return date; } } From e20ec441b49a1b64c28bd7c1807ffd76e9eca08e Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 20 Feb 2018 16:12:42 +0200 Subject: [PATCH 04/22] Add date-fns utils, imlement hoc for setting and getting utils from context --- docs/src/App.js | 24 ++++++++++++------- lib/src/DatePicker/Calendar.jsx | 8 +++---- lib/src/DatePicker/CalendarHeader.jsx | 7 +++--- lib/src/DatePicker/DatePicker.jsx | 7 +++--- lib/src/DatePicker/DatePickerWrapper.jsx | 10 ++++---- lib/src/DatePicker/YearSelection.jsx | 7 +++--- lib/src/DateTimePicker/DateTimePicker.jsx | 14 +++++++---- .../DateTimePicker/DateTimePickerHeader.jsx | 7 +++--- .../DateTimePicker/DateTimePickerWrapper.jsx | 7 +++--- lib/src/TimePicker/HourView.jsx | 11 +++++---- lib/src/TimePicker/MinutesView.jsx | 10 ++++---- lib/src/TimePicker/TimePicker.jsx | 14 +++++++---- lib/src/TimePicker/TimePickerWrapper.jsx | 10 ++++---- lib/src/_shared/DateTextField.jsx | 10 ++++---- lib/src/_shared/PickerBase.jsx | 4 +--- lib/src/_shared/WithUtils.jsx | 23 ++++++++++++++++++ lib/src/index.js | 6 +++++ lib/src/utils/MuiPickersUtilsProvider.jsx | 23 ++++++++++++++++++ lib/src/utils/{utils.js => date-fns-utils.js} | 0 19 files changed, 134 insertions(+), 68 deletions(-) create mode 100644 lib/src/_shared/WithUtils.jsx create mode 100644 lib/src/utils/MuiPickersUtilsProvider.jsx rename lib/src/utils/{utils.js => date-fns-utils.js} (100%) diff --git a/docs/src/App.js b/docs/src/App.js index 76c307c4b..255e29104 100644 --- a/docs/src/App.js +++ b/docs/src/App.js @@ -1,8 +1,7 @@ import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { MuiThemeProvider, createMuiTheme } from 'material-ui'; - -import Demo from './Demo/Demo'; -import { setPrismTheme } from './utils/prism'; +import { MuiPickerUtilsProvider, dateFnsUtils } from 'material-ui-pickers'; import { create } from 'jss'; import preset from 'jss-preset-default'; @@ -10,10 +9,17 @@ import rtl from 'jss-rtl'; import JssProvider from 'react-jss/lib/JssProvider'; import createGenerateClassName from 'material-ui/styles/createGenerateClassName'; +import Demo from './Demo/Demo'; +import { setPrismTheme } from './utils/prism'; + const jss = create({ plugins: [...preset().plugins, rtl()] }); jss.options.createGenerateClassName = createGenerateClassName; export default class App extends Component { + static propTypes = { + toggleFrench: PropTypes.func.isRequired, + } + state = { type: 'light', direction: 'ltr', @@ -50,11 +56,13 @@ export default class App extends Component {
- + + +
diff --git a/lib/src/DatePicker/Calendar.jsx b/lib/src/DatePicker/Calendar.jsx index 7d59f3763..2db227017 100644 --- a/lib/src/DatePicker/Calendar.jsx +++ b/lib/src/DatePicker/Calendar.jsx @@ -6,10 +6,9 @@ import EventListener from 'react-event-listener'; import keycode from 'keycode'; import CalendarHeader from './CalendarHeader'; import DomainPropTypes from '../constants/prop-types'; -import * as defaultUtils from '../utils/utils'; import DayWrapper from './DayWrapper'; import Day from './Day'; - +import withUtils from '../_shared/WithUtils'; /* eslint-disable no-unused-expressions */ export class Calendar extends Component { @@ -26,8 +25,8 @@ export class Calendar extends Component { renderDay: PropTypes.func, /** @ignore */ theme: PropTypes.object.isRequired, - utils: PropTypes.func, shouldDisableDate: PropTypes.func, + utils: PropTypes.func.isRequired, }; static defaultProps = { @@ -38,7 +37,6 @@ export class Calendar extends Component { leftArrowIcon: undefined, rightArrowIcon: undefined, renderDay: undefined, - utils: defaultUtils, shouldDisableDate: () => false, }; @@ -219,4 +217,4 @@ const styles = theme => ({ export default withStyles(styles, { name: 'MuiPickersCalendar', withTheme: true, -})(Calendar); +})(withUtils()(Calendar)); diff --git a/lib/src/DatePicker/CalendarHeader.jsx b/lib/src/DatePicker/CalendarHeader.jsx index fe033acc8..e367b4cf1 100644 --- a/lib/src/DatePicker/CalendarHeader.jsx +++ b/lib/src/DatePicker/CalendarHeader.jsx @@ -4,7 +4,7 @@ import withStyles from 'material-ui/styles/withStyles'; import Typography from 'material-ui/Typography'; import IconButton from 'material-ui/IconButton'; import Icon from 'material-ui/Icon'; -import * as defaultUtils from '../utils/utils'; +import withUtils from '../_shared/WithUtils'; export const CalendarHeader = (props) => { const { @@ -61,13 +61,12 @@ CalendarHeader.propTypes = { theme: PropTypes.object.isRequired, leftArrowIcon: PropTypes.node, rightArrowIcon: PropTypes.node, - utils: PropTypes.func, + utils: PropTypes.func.isRequired, }; CalendarHeader.defaultProps = { leftArrowIcon: 'keyboard_arrow_left', rightArrowIcon: 'keyboard_arrow_right', - utils: defaultUtils, }; const styles = theme => ({ @@ -93,4 +92,4 @@ const styles = theme => ({ export default withStyles( styles, { withTheme: true, name: 'MuiPickersCalendarHeader' }, -)(CalendarHeader); +)(withUtils()(CalendarHeader)); diff --git a/lib/src/DatePicker/DatePicker.jsx b/lib/src/DatePicker/DatePicker.jsx index c42c70d55..3913f31fc 100644 --- a/lib/src/DatePicker/DatePicker.jsx +++ b/lib/src/DatePicker/DatePicker.jsx @@ -5,8 +5,8 @@ import Calendar from './Calendar'; import YearSelection from './YearSelection'; import PickerToolbar from '../_shared/PickerToolbar'; import ToolbarButton from '../_shared/ToolbarButton'; -import * as defaultUtils from '../utils/utils'; import DomainPropTypes from '../constants/prop-types'; +import withUtils from '../_shared/WithUtils'; export class DatePicker extends PureComponent { static propTypes = { @@ -22,7 +22,7 @@ export class DatePicker extends PureComponent { leftArrowIcon: PropTypes.node, rightArrowIcon: PropTypes.node, renderDay: PropTypes.func, - utils: PropTypes.func, + utils: PropTypes.func.isRequired, shouldDisableDate: PropTypes.func, } @@ -37,7 +37,6 @@ export class DatePicker extends PureComponent { leftArrowIcon: undefined, rightArrowIcon: undefined, renderDay: undefined, - utils: defaultUtils, shouldDisableDate: undefined, } @@ -137,5 +136,5 @@ export class DatePicker extends PureComponent { } } -export default DatePicker; +export default withUtils()(DatePicker); diff --git a/lib/src/DatePicker/DatePickerWrapper.jsx b/lib/src/DatePicker/DatePickerWrapper.jsx index bca559ed0..83588168f 100644 --- a/lib/src/DatePicker/DatePickerWrapper.jsx +++ b/lib/src/DatePicker/DatePickerWrapper.jsx @@ -5,9 +5,9 @@ import ModalWrapper from '../wrappers/ModalWrapper'; import DatePicker from './DatePicker'; import DomainPropTypes from '../constants/prop-types'; import PickerBase from '../_shared/PickerBase'; -import defaultUtils from '../utils/utils'; +import withUtils from '../_shared/WithUtils'; -export default class DatePickerWrapper extends PickerBase { +class DatePickerWrapper extends PickerBase { static propTypes = { /* Datepicker value */ value: DomainPropTypes.date, @@ -42,7 +42,7 @@ export default class DatePickerWrapper extends PickerBase { /* Custom renderer for day renderDay(date, selectedDate, dayInCurrentMonth) */ renderDay: PropTypes.func, /* Date displaying utils */ - utils: PropTypes.func, + utils: PropTypes.func.isRequired, /* Disable specific date hook */ shouldDisableDate: PropTypes.func, } @@ -63,7 +63,6 @@ export default class DatePickerWrapper extends PickerBase { rightArrowIcon: undefined, renderDay: undefined, labelFunc: undefined, - utils: defaultUtils, shouldDisableDate: undefined, } @@ -131,3 +130,6 @@ export default class DatePickerWrapper extends PickerBase { ); } } + +export default withUtils()(DatePickerWrapper); + diff --git a/lib/src/DatePicker/YearSelection.jsx b/lib/src/DatePicker/YearSelection.jsx index 83af13eaf..ff4f8a518 100644 --- a/lib/src/DatePicker/YearSelection.jsx +++ b/lib/src/DatePicker/YearSelection.jsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { findDOMNode } from 'react-dom'; import withStyles from 'material-ui/styles/withStyles'; import DomainPropTypes from '../constants/prop-types'; -import defaultUtils from '../utils/utils'; +import withUtils from '../_shared/WithUtils'; import Year from './Year'; export class YearSelection extends PureComponent { @@ -16,12 +16,11 @@ export class YearSelection extends PureComponent { disablePast: PropTypes.bool.isRequired, disableFuture: PropTypes.bool.isRequired, animateYearScrolling: PropTypes.bool, - utils: PropTypes.func, + utils: PropTypes.func.isRequired, } static defaultProps = { animateYearScrolling: false, - utils: defaultUtils, } componentDidMount = () => { @@ -99,4 +98,4 @@ const styles = { }, }; -export default withStyles(styles, { name: 'MuiPickersYearSelection' })(YearSelection); +export default withStyles(styles, { name: 'MuiPickersYearSelection' })(withUtils()(YearSelection)); diff --git a/lib/src/DateTimePicker/DateTimePicker.jsx b/lib/src/DateTimePicker/DateTimePicker.jsx index 7ea19ca36..9a0bb6f3f 100644 --- a/lib/src/DateTimePicker/DateTimePicker.jsx +++ b/lib/src/DateTimePicker/DateTimePicker.jsx @@ -12,7 +12,7 @@ import { convertToMeridiem } from '../_helpers/time-utils'; import DomainPropTypes from '../constants/prop-types'; import * as viewType from '../constants/date-picker-view'; -import defaultUtils from '../utils/utils'; +import withUtils from '../_shared/WithUtils'; export class DateTimePicker extends Component { static propTypes = { @@ -30,7 +30,7 @@ export class DateTimePicker extends Component { dateRangeIcon: PropTypes.node, timeIcon: PropTypes.node, renderDay: PropTypes.func, - utils: PropTypes.func, + utils: PropTypes.func.isRequired, ampm: PropTypes.bool, shouldDisableDate: PropTypes.func, animateYearScrolling: PropTypes.bool, @@ -49,7 +49,6 @@ export class DateTimePicker extends Component { dateRangeIcon: undefined, timeIcon: undefined, renderDay: undefined, - utils: defaultUtils, ampm: true, shouldDisableDate: undefined, animateYearScrolling: false, @@ -80,7 +79,12 @@ export class DateTimePicker extends Component { } handleChange = (time, isFinish = false) => { - const withMeridiem = convertToMeridiem(time, this.state.meridiemMode, this.props.ampm, this.props.utils); + const withMeridiem = convertToMeridiem( + time, + this.state.meridiemMode, + this.props.ampm, + this.props.utils, + ); this.props.onChange(withMeridiem, isFinish); } @@ -189,4 +193,4 @@ export class DateTimePicker extends Component { } } -export default DateTimePicker; +export default withUtils()(DateTimePicker); diff --git a/lib/src/DateTimePicker/DateTimePickerHeader.jsx b/lib/src/DateTimePicker/DateTimePickerHeader.jsx index 4e323a325..aea7b021e 100644 --- a/lib/src/DateTimePicker/DateTimePickerHeader.jsx +++ b/lib/src/DateTimePicker/DateTimePickerHeader.jsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import withStyles from 'material-ui/styles/withStyles'; import PickerToolbar from '../_shared/PickerToolbar'; import ToolbarButton from '../_shared/ToolbarButton'; -import defaultUtils from '../utils/utils'; +import withUtils from '../_shared/WithUtils'; import * as viewType from '../constants/date-picker-view'; export const DateTimePickerHeader = (props) => { @@ -93,12 +93,11 @@ DateTimePickerHeader.propTypes = { openView: PropTypes.string.isRequired, onOpenViewChange: PropTypes.func.isRequired, setMeridiemMode: PropTypes.func.isRequired, - utils: PropTypes.func, + utils: PropTypes.func.isRequired, ampm: PropTypes.bool, }; DateTimePickerHeader.defaultProps = { - utils: defaultUtils, ampm: true, }; @@ -143,4 +142,4 @@ const styles = () => ({ }, }); -export default withStyles(styles, { withTheme: true })(DateTimePickerHeader); +export default withStyles(styles, { withTheme: true })(withUtils()(DateTimePickerHeader)); diff --git a/lib/src/DateTimePicker/DateTimePickerWrapper.jsx b/lib/src/DateTimePicker/DateTimePickerWrapper.jsx index 369bfbaf3..770575416 100644 --- a/lib/src/DateTimePicker/DateTimePickerWrapper.jsx +++ b/lib/src/DateTimePicker/DateTimePickerWrapper.jsx @@ -7,7 +7,7 @@ import DomainPropTypes from '../constants/prop-types'; import ModalWrapper from '../wrappers/ModalWrapper'; import DateTimePicker from './DateTimePicker'; import PickerBase from '../_shared/PickerBase'; -import defaultUtils from '../utils/utils'; +import withUtils from '../_shared/WithUtils'; export class DateTimePickerWrapper extends PickerBase { static propTypes = { @@ -30,7 +30,7 @@ export class DateTimePickerWrapper extends PickerBase { timeIcon: PropTypes.node, renderDay: PropTypes.func, labelFunc: PropTypes.func, - utils: PropTypes.func, + utils: PropTypes.func.isRequired, ampm: PropTypes.bool, shouldDisableDate: PropTypes.func, animateYearScrolling: PropTypes.bool, @@ -54,7 +54,6 @@ export class DateTimePickerWrapper extends PickerBase { timeIcon: undefined, renderDay: undefined, labelFunc: undefined, - utils: defaultUtils, ampm: true, shouldDisableDate: undefined, animateYearScrolling: false, @@ -141,5 +140,5 @@ const styles = { }, }; -export default withStyles(styles, { name: 'MuiPickerDTPickerModal' })(DateTimePickerWrapper); +export default withStyles(styles, { name: 'MuiPickerDTPickerModal' })(withUtils()(DateTimePickerWrapper)); diff --git a/lib/src/TimePicker/HourView.jsx b/lib/src/TimePicker/HourView.jsx index 42017fed9..a4796a77e 100644 --- a/lib/src/TimePicker/HourView.jsx +++ b/lib/src/TimePicker/HourView.jsx @@ -3,19 +3,17 @@ import PropTypes from 'prop-types'; import Clock from './Clock'; import { HOURS } from '../constants/clock-types'; import ClockNumber from './ClockNumber'; -import defaultUtils from '../utils/utils'; +import withUtils from '../_shared/WithUtils'; - -export default class HourView extends PureComponent { +class HourView extends PureComponent { static propTypes = { date: PropTypes.object.isRequired, onChange: PropTypes.func.isRequired, - utils: PropTypes.func, + utils: PropTypes.func.isRequired, ampm: PropTypes.bool, } static defaultProps = { - utils: defaultUtils, ampm: true, } @@ -84,3 +82,6 @@ export default class HourView extends PureComponent { ); } } + +export default withUtils()(HourView); + diff --git a/lib/src/TimePicker/MinutesView.jsx b/lib/src/TimePicker/MinutesView.jsx index b76edca20..87b4b89cf 100644 --- a/lib/src/TimePicker/MinutesView.jsx +++ b/lib/src/TimePicker/MinutesView.jsx @@ -3,17 +3,16 @@ import PropTypes from 'prop-types'; import Clock from './Clock'; import { MINUTES } from '../constants/clock-types'; import ClockNumber from './ClockNumber'; -import defaultUtils from '../utils/utils'; +import withUtils from '../_shared/WithUtils'; -export default class MinutesView extends Component { +class MinutesView extends Component { static propTypes = { date: PropTypes.object.isRequired, onChange: PropTypes.func.isRequired, - utils: PropTypes.func, + utils: PropTypes.func.isRequired, } static defaultProps = { - utils: defaultUtils, } handleChange = (minutes, isFinish) => { @@ -50,3 +49,6 @@ export default class MinutesView extends Component { ); } } + +export default withUtils()(MinutesView); + diff --git a/lib/src/TimePicker/TimePicker.jsx b/lib/src/TimePicker/TimePicker.jsx index 327c7ddf7..06442480d 100644 --- a/lib/src/TimePicker/TimePicker.jsx +++ b/lib/src/TimePicker/TimePicker.jsx @@ -6,7 +6,7 @@ import ToolbarButton from '../_shared/ToolbarButton'; import HourView from './HourView'; import MinutesView from './MinutesView'; import { convertToMeridiem } from '../_helpers/time-utils'; -import defaultUtils from '../utils/utils'; +import withUtils from '../_shared/WithUtils'; export class TimePicker extends Component { static propTypes = { @@ -15,13 +15,12 @@ export class TimePicker extends Component { classes: PropTypes.object.isRequired, theme: PropTypes.object.isRequired, children: PropTypes.node, - utils: PropTypes.func, + utils: PropTypes.func.isRequired, ampm: PropTypes.bool, } static defaultProps = { children: null, - utils: defaultUtils, ampm: true, } @@ -38,7 +37,12 @@ export class TimePicker extends Component { } handleChange(time, isFinish, openMinutes) { - const withMeridiem = convertToMeridiem(time, this.state.meridiemMode, this.props.ampm, this.props.utils); + const withMeridiem = convertToMeridiem( + time, + this.state.meridiemMode, + this.props.ampm, + this.props.utils, + ); if (isFinish) { if (!openMinutes) { @@ -186,4 +190,4 @@ const styles = () => ({ export default withStyles( styles, { withTheme: true, name: 'MuiPickersTimePicker' }, -)(TimePicker); +)(withUtils()(TimePicker)); diff --git a/lib/src/TimePicker/TimePickerWrapper.jsx b/lib/src/TimePicker/TimePickerWrapper.jsx index e2e93588f..ba6346f94 100644 --- a/lib/src/TimePicker/TimePickerWrapper.jsx +++ b/lib/src/TimePicker/TimePickerWrapper.jsx @@ -4,9 +4,9 @@ import PropTypes from 'prop-types'; import ModalWrapper from '../wrappers/ModalWrapper'; import TimePicker from './TimePicker'; import PickerBase from '../_shared/PickerBase'; -import defaultUtils from '../utils/utils'; +import withUtils from '../_shared/WithUtils'; -export default class TimePickerWrapper extends PickerBase { +class TimePickerWrapper extends PickerBase { static propTypes = { value: PropTypes.oneOfType([ PropTypes.object, @@ -19,7 +19,7 @@ export default class TimePickerWrapper extends PickerBase { autoOk: PropTypes.bool, returnMoment: PropTypes.bool, invalidLabel: PropTypes.string, - utils: PropTypes.func, + utils: PropTypes.func.isRequired, ampm: PropTypes.bool, } @@ -29,7 +29,6 @@ export default class TimePickerWrapper extends PickerBase { autoOk: false, returnMoment: true, invalidLabel: undefined, - utils: defaultUtils, ampm: true, } @@ -65,3 +64,6 @@ export default class TimePickerWrapper extends PickerBase { ); } } + +export default withUtils()(TimePickerWrapper); + diff --git a/lib/src/_shared/DateTextField.jsx b/lib/src/_shared/DateTextField.jsx index e23dd28e2..1bba8a492 100644 --- a/lib/src/_shared/DateTextField.jsx +++ b/lib/src/_shared/DateTextField.jsx @@ -9,7 +9,7 @@ import withStyles from 'material-ui/styles/withStyles'; import DomainPropTypes from '../constants/prop-types'; import MaskedInput from './MaskedInput'; -import defaultUtils from '../utils/utils'; +import withUtils from '../_shared/WithUtils'; class DateTextField extends PureComponent { static propTypes = { @@ -41,7 +41,7 @@ class DateTextField extends PureComponent { invalidDateMessage: PropTypes.string, clearable: PropTypes.bool, TextFieldComponent: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), - utils: PropTypes.func, + utils: PropTypes.func.isRequired, } static defaultProps = { @@ -65,7 +65,6 @@ class DateTextField extends PureComponent { minDateMessage: 'Date should not be before minimal date', maxDateMessage: 'Date should not be after maximal date', TextFieldComponent: TextField, - utils: defaultUtils, } getDisplayDate = (props) => { @@ -211,6 +210,7 @@ class DateTextField extends PureComponent { render() { const { + utils, format, classes, disabled, @@ -235,8 +235,8 @@ class DateTextField extends PureComponent { TextFieldComponent, ...other } = this.props; - const { displayValue, error } = this.state; + const { displayValue, error } = this.state; const localInputProps = { inputComponent: MaskedInput, inputProps: { @@ -277,4 +277,4 @@ const styles = { }, }; -export default withStyles(styles)(DateTextField); +export default withStyles(styles)(withUtils()(DateTextField)); diff --git a/lib/src/_shared/PickerBase.jsx b/lib/src/_shared/PickerBase.jsx index 249484188..305e7e446 100644 --- a/lib/src/_shared/PickerBase.jsx +++ b/lib/src/_shared/PickerBase.jsx @@ -1,7 +1,6 @@ import { PureComponent } from 'react'; import PropTypes from 'prop-types'; import DomainPropTypes from '../constants/prop-types'; -import defaultUtils from '../utils/utils'; /* eslint-disable react/sort-comp */ export default class PickerBase extends PureComponent { @@ -13,7 +12,7 @@ export default class PickerBase extends PureComponent { format: PropTypes.string, labelFunc: PropTypes.func, ampm: PropTypes.bool, - utils: PropTypes.func, + utils: PropTypes.func.isRequired, } static defaultProps = { @@ -23,7 +22,6 @@ export default class PickerBase extends PureComponent { labelFunc: undefined, format: undefined, ampm: true, - utils: defaultUtils, } getValidDateOrCurrent = () => { diff --git a/lib/src/_shared/WithUtils.jsx b/lib/src/_shared/WithUtils.jsx new file mode 100644 index 000000000..19aa069f8 --- /dev/null +++ b/lib/src/_shared/WithUtils.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const withUtils = () => (Component) => { + const WithUtils = (props, context) => { + if (!context.muiPickersDateUtils) { + // eslint-disable-next-line no-console + console.error('Utils should be provided'); + } + + return ; + }; + + WithUtils.contextTypes = { + muiPickersDateUtils: PropTypes.func, + }; + + WithUtils.displayName = `withUtils${Component.displayName || Component.name}`; + + return WithUtils; +}; + +export default withUtils; diff --git a/lib/src/index.js b/lib/src/index.js index 173f5b6cc..b0f44c714 100644 --- a/lib/src/index.js +++ b/lib/src/index.js @@ -3,3 +3,9 @@ export { default as DatePicker } from './DatePicker/DatePickerWrapper'; export { default as TimePicker } from './TimePicker/TimePickerWrapper'; export { default as DateTimePicker } from './DateTimePicker/DateTimePickerWrapper'; + +export { default as MuiPickerUtilsProvider } from './utils/MuiPickersUtilsProvider'; + +export { default as dateFnsUtils } from './utils/date-fns-utils'; + +export { default as momentUtils } from './utils/moment-utils'; diff --git a/lib/src/utils/MuiPickersUtilsProvider.jsx b/lib/src/utils/MuiPickersUtilsProvider.jsx new file mode 100644 index 000000000..1ae3fb50b --- /dev/null +++ b/lib/src/utils/MuiPickersUtilsProvider.jsx @@ -0,0 +1,23 @@ +import { PureComponent } from 'react'; +import PropTypes from 'prop-types'; + +export default class MuiPickersUtilsProvider extends PureComponent { + static propTypes = { + utils: PropTypes.func.isRequired, + children: PropTypes.element.isRequired, + } + + static childContextTypes = { + muiPickersDateUtils: PropTypes.func, + } + + getChildContext() { + return { + muiPickersDateUtils: this.props.utils, + }; + } + + render() { + return this.props.children; + } +} diff --git a/lib/src/utils/utils.js b/lib/src/utils/date-fns-utils.js similarity index 100% rename from lib/src/utils/utils.js rename to lib/src/utils/date-fns-utils.js From 4245319baf0a99e0a2386570eb09a5a3263d9755 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 20 Feb 2018 18:37:18 +0200 Subject: [PATCH 05/22] Improve utils, fix crashings --- docs/src/App.js | 2 +- lib/src/DatePicker/Calendar.jsx | 5 ++--- lib/src/_shared/PickerBase.jsx | 2 +- lib/src/utils/date-fns-utils.js | 14 +++++++++----- lib/src/utils/moment-utils.js | 14 ++++++++------ 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/docs/src/App.js b/docs/src/App.js index 255e29104..9546113df 100644 --- a/docs/src/App.js +++ b/docs/src/App.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { MuiThemeProvider, createMuiTheme } from 'material-ui'; -import { MuiPickerUtilsProvider, dateFnsUtils } from 'material-ui-pickers'; +import { MuiPickerUtilsProvider, dateFnsUtils, momentUtils } from 'material-ui-pickers'; import { create } from 'jss'; import preset from 'jss-preset-default'; diff --git a/lib/src/DatePicker/Calendar.jsx b/lib/src/DatePicker/Calendar.jsx index 2db227017..e835fa5c7 100644 --- a/lib/src/DatePicker/Calendar.jsx +++ b/lib/src/DatePicker/Calendar.jsx @@ -65,11 +65,10 @@ export class Calendar extends Component { validateMinMaxDate = (day) => { const { minDate, maxDate, utils } = this.props; - const startOfDay = date => utils.startOfDay(utils.date(date)); return ( - (minDate && utils.isBefore(day, startOfDay(minDate))) || - (maxDate && utils.isAfter(day, startOfDay(maxDate))) + (minDate && utils.isBeforeDay(day, utils.date(minDate))) || + (maxDate && utils.isAfterDay(day, utils.date(maxDate))) ); }; diff --git a/lib/src/_shared/PickerBase.jsx b/lib/src/_shared/PickerBase.jsx index 305e7e446..a6ef041c4 100644 --- a/lib/src/_shared/PickerBase.jsx +++ b/lib/src/_shared/PickerBase.jsx @@ -36,7 +36,7 @@ export default class PickerBase extends PureComponent { } componentWillReceiveProps(nextProps) { - if (this.props.value !== nextProps.value) { + if (!this.props.utils.isEqual(this.state.date, nextProps.value)) { this.setState({ date: this.getValidDateOrCurrent(nextProps) }); } } diff --git a/lib/src/utils/date-fns-utils.js b/lib/src/utils/date-fns-utils.js index b165db37d..a146290f7 100644 --- a/lib/src/utils/date-fns-utils.js +++ b/lib/src/utils/date-fns-utils.js @@ -20,14 +20,19 @@ import startOfWeek from 'date-fns/start_of_week'; import startOfYear from 'date-fns/start_of_year'; import getHours from 'date-fns/get_hours'; import getYear from 'date-fns/get_year'; +import isEqual from 'date-fns/is_equal'; -export default class Utils { +export default class DateFnsUtils { static date(value) { - return value; + return new Date(value); } + static addDays = addDays + static isValid = isValid + static isEqual = isEqual + static isNull(date) { return date == null; } @@ -41,11 +46,11 @@ export default class Utils { } static isBeforeDay(date, value) { - return isBefore(startOfDay(date), value); + return isBefore(date, startOfDay(value)); } static isBeforeYear(date, value) { - return isBefore(startOfYear(date), value); + return isBefore(date, startOfYear(value)); } static isAfterYear(date, value) { @@ -76,7 +81,6 @@ export default class Utils { return date.getMonth(); } - static isSameDay = isSameDay; static getMeridiemText(ampm) { diff --git a/lib/src/utils/moment-utils.js b/lib/src/utils/moment-utils.js index 17ca75a4f..a84d5a2c3 100644 --- a/lib/src/utils/moment-utils.js +++ b/lib/src/utils/moment-utils.js @@ -3,7 +3,7 @@ import { extendMoment } from 'moment-range'; const moment = extendMoment(Moment); -export default class Utils { +export default class MomentUtils { static date(value) { return moment(value); } @@ -61,11 +61,9 @@ export default class Utils { } static addDays(date, count) { - if (count < 0) { - date.clone().subtract(Math.abs(count)); - } else { - date.clone().add(count); - } + return count < 0 + ? date.clone().subtract(Math.abs(count), 'days') + : date.clone().add(count, 'days'); } static setHours(date, value) { @@ -116,6 +114,10 @@ export default class Utils { return [0, 1, 2, 3, 4, 5, 6].map(dayOfWeek => moment().weekday(dayOfWeek).format('dd')[0]); } + static isEqual(value, comparing) { + return moment(value).isSame(comparing); + } + static getWeekArray(date) { const start = date.clone().startOf('month').startOf('week'); const end = date.clone().endOf('month').endOf('week'); From 47850efb522db91d26f5fafb0d1510c6577441cb Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 20 Feb 2018 18:59:01 +0200 Subject: [PATCH 06/22] Add typings for utils and new components --- lib/src/utils/MuiPickersUtilsProvider.d.ts | 12 +++++++ lib/src/utils/date-fns-utils.d.ts | 4 +++ lib/src/utils/moment-utils.d.ts | 4 +++ lib/src/utils/utils.d.ts | 37 ---------------------- lib/typings/date.ts | 3 ++ lib/typings/utils.ts | 34 ++++++++++++++++++++ 6 files changed, 57 insertions(+), 37 deletions(-) create mode 100644 lib/src/utils/MuiPickersUtilsProvider.d.ts create mode 100644 lib/src/utils/date-fns-utils.d.ts create mode 100644 lib/src/utils/moment-utils.d.ts delete mode 100644 lib/src/utils/utils.d.ts create mode 100644 lib/typings/date.ts create mode 100644 lib/typings/utils.ts diff --git a/lib/src/utils/MuiPickersUtilsProvider.d.ts b/lib/src/utils/MuiPickersUtilsProvider.d.ts new file mode 100644 index 000000000..9f7d2b2af --- /dev/null +++ b/lib/src/utils/MuiPickersUtilsProvider.d.ts @@ -0,0 +1,12 @@ +import { ComponentClass, ReactNode } from 'react'; +import { DateTimePickerView } from '../constants/date-picker-view'; +import { Utils } from '../../typings/utils'; + +export interface MuiPickersUtilsProviderProps { + utils: Utils; + children: ReactNode; +} + +declare const MuiPickersUtilsProvider: ComponentClass; + +export default MuiPickersUtilsProvider; diff --git a/lib/src/utils/date-fns-utils.d.ts b/lib/src/utils/date-fns-utils.d.ts new file mode 100644 index 000000000..d99f7eead --- /dev/null +++ b/lib/src/utils/date-fns-utils.d.ts @@ -0,0 +1,4 @@ +import { Utils } from '../../typings/utils' + +declare const DateFnsUtils: Utils; +export default DateFnsUtils \ No newline at end of file diff --git a/lib/src/utils/moment-utils.d.ts b/lib/src/utils/moment-utils.d.ts new file mode 100644 index 000000000..2140e1e97 --- /dev/null +++ b/lib/src/utils/moment-utils.d.ts @@ -0,0 +1,4 @@ +import { Utils } from '../../typings/utils' + +declare const MomentUtils: Utils; +export default MomentUtils \ No newline at end of file diff --git a/lib/src/utils/utils.d.ts b/lib/src/utils/utils.d.ts deleted file mode 100644 index 9d008ffce..000000000 --- a/lib/src/utils/utils.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -export declare function formatNumber(num: string): string; -export declare function getCalendarHeaderText(date: any): string; -export declare function getDatePickerHeaderText(date: any): string; -export declare function getDateTimePickerHeaderText(date: any): string; -export declare function getDayText(date: any): string; -export declare function getHourText(date: any): string; -export declare function getMinuteText(date: any): string; -export declare function getMeridiemText(ampm: 'am' | 'pm'): string; -export declare function getYearText(date: any): string; -export declare function getMonthNumber(date: any): number; -export declare function getStartOfMonth(date: any): any; -export declare function getNextMonth(date: any): any; -export declare function getPreviousMonth(date: any): any; -export declare function getYear(date: any): any; -export declare function setYear(date: any, year: number): any; -export declare function getWeekdays(): string[]; -export declare function getWeekArray(date: any): any[][]; - -export interface Utils { - formatNumber: typeof formatNumber; - getCalendarHeaderText: typeof getCalendarHeaderText; - getDatePickerHeaderText: typeof getDatePickerHeaderText; - getDateTimePickerHeaderText: typeof getDateTimePickerHeaderText; - getDayText: typeof getDayText; - getHourText: typeof getHourText; - getMinuteText: typeof getMinuteText; - getMeridiemText: typeof getMeridiemText; - getYearText: typeof getYearText; - getMonthNumber: typeof getMonthNumber; - getStartOfMonth: typeof getStartOfMonth; - getNextMonth: typeof getNextMonth; - getPreviousMonth: typeof getPreviousMonth; - getYear: typeof getYear; - setYear: typeof setYear; - getWeekdays: typeof getWeekdays; - getWeekArray: typeof getWeekArray; -} diff --git a/lib/typings/date.ts b/lib/typings/date.ts new file mode 100644 index 000000000..92b46a635 --- /dev/null +++ b/lib/typings/date.ts @@ -0,0 +1,3 @@ +import { Moment } from 'moment'; + +export type MaterialUiPickersDate = Moment | Date \ No newline at end of file diff --git a/lib/typings/utils.ts b/lib/typings/utils.ts new file mode 100644 index 000000000..4dcc6d788 --- /dev/null +++ b/lib/typings/utils.ts @@ -0,0 +1,34 @@ +import { MaterialUiPickersDate } from './date' +import { isEqual, isAfter, endOfDay, setHours } from 'date-fns'; + +export interface Utils { + date(value: any): MaterialUiPickersDate; + addDays(value: MaterialUiPickersDate, count: Number): MaterialUiPickersDate; + isValid(value: MaterialUiPickersDate): boolean; + isEqual(value: MaterialUiPickersDate, comparing: MaterialUiPickersDate): boolean; + isNull(value: MaterialUiPickersDate): boolean; + isAfter(value: MaterialUiPickersDate, comparing: MaterialUiPickersDate): boolean; + isAfterDay(value: MaterialUiPickersDate, comparing: MaterialUiPickersDate): boolean; + isBeforeDay(value: MaterialUiPickersDate, comparing: MaterialUiPickersDate): boolean; + isBeforeYear(value: MaterialUiPickersDate, comparing: MaterialUiPickersDate): boolean; + isAfterYear(value: MaterialUiPickersDate, comparing: MaterialUiPickersDate): boolean; + startOfDay(value: MaterialUiPickersDate): MaterialUiPickersDate; + endOfDay(value: MaterialUiPickersDate): MaterialUiPickersDate; + format(value: MaterialUiPickersDate): string; + formatNumber(number: number): MaterialUiPickersDate + getHours(value: MaterialUiPickersDate): number; + setHours(value: MaterialUiPickersDate, count: number): MaterialUiPickersDate; + getMinutes(value: MaterialUiPickersDate): number; + setMinutes(value: MaterialUiPickersDate, count: number): MaterialUiPickersDate + getMonth(value: MaterialUiPickersDate): number; + isSameDay(value: MaterialUiPickersDate, comparing: MaterialUiPickersDate): boolean + getMeridiemText(ampm: boolean): string; + getStartOfMonth(value: MaterialUiPickersDate): MaterialUiPickersDate; + getNextMonth(value: MaterialUiPickersDate): MaterialUiPickersDate; + getPreviousMonth(value: MaterialUiPickersDate): MaterialUiPickersDate; + getYear(value: MaterialUiPickersDate): number; + setYear(value: MaterialUiPickersDate): MaterialUiPickersDate; + getWeekDays(): string[]; + getWeekArray(): MaterialUiPickersDate[]; + getYearRange(): MaterialUiPickersDate[]; +} \ No newline at end of file From bb3051c4f24ea0104ead032d63aa9e6b91e04b95 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 20 Feb 2018 21:35:35 +0200 Subject: [PATCH 07/22] Add test setup for moment and date-fns separately, fix failing unit-tests --- lib/__tests__/DatePicker/Calendar.test.js | 4 +- .../DatePicker/CalendarHeader.test.js | 4 +- lib/__tests__/DatePicker/DatePicker.test.js | 4 +- .../DatePicker/DatePickerWrapper.test.js | 38 ++++++++++--------- .../DatePicker/DatePickerWrapper.usage.tsx | 6 ++- .../DatePicker/YearSelection.test.js | 4 +- .../DateTimePicker/DateTimePicker.test.js | 4 +- .../DateTimePickerHeader.test.js | 4 +- .../DateTimePicker/DateTimePickerTabs.test.js | 4 +- .../DateTimePicker/DateTimePickerView.test.js | 4 +- .../DateTimePickerWrapper.test.js | 4 +- .../DateTimePickerWrapper.usage.tsx | 12 +++--- lib/__tests__/TimePicker/Clock.test.js | 4 +- lib/__tests__/TimePicker/ClockNumber.test.js | 4 +- lib/__tests__/TimePicker/ClockPointer.test.js | 4 +- lib/__tests__/TimePicker/HourView.test.js | 6 +-- lib/__tests__/TimePicker/MinutesView.test.js | 8 ++-- lib/__tests__/TimePicker/TimePicker.test.js | 4 +- .../TimePicker/TimePickerWrapper.test.js | 6 +-- .../TimePicker/TimePickerWrapper.usage.tsx | 6 ++- lib/__tests__/_shared/DateTextField.test.js | 17 +++------ lib/__tests__/_shared/ModalDialog.test.js | 4 +- lib/__tests__/_shared/PickerToolbar.test.js | 4 +- lib/__tests__/_shared/ToolbarButton.test.js | 4 +- lib/__tests__/test-utils.d.ts | 3 ++ lib/__tests__/test-utils.js | 14 +++++++ lib/__tests__/utils/time-utils.test.js | 7 ++-- lib/__tests__/wrappers/ModalWrapper.test.js | 4 +- lib/package.json | 5 ++- lib/src/DatePicker/Calendar.d.ts | 2 +- lib/src/DatePicker/CalendarHeader.d.ts | 2 +- lib/src/DatePicker/DatePicker.d.ts | 2 +- lib/src/DatePicker/DatePickerWrapper.d.ts | 2 +- lib/src/DatePicker/YearSelection.d.ts | 2 +- lib/src/DateTimePicker/DateTimePicker.d.ts | 2 +- .../DateTimePicker/DateTimePickerHeader.d.ts | 2 +- .../DateTimePicker/DateTimePickerWrapper.d.ts | 2 +- lib/src/TimePicker/HourView.d.ts | 2 +- lib/src/TimePicker/HourView.jsx | 2 +- lib/src/TimePicker/MinutesView.d.ts | 2 +- lib/src/TimePicker/MinutesView.jsx | 2 +- lib/src/TimePicker/TimePicker.d.ts | 2 +- lib/src/TimePicker/TimePickerWrapper.d.ts | 2 +- lib/src/TimePicker/TimePickerWrapper.jsx | 2 +- lib/src/_shared/ModalDialog.d.ts | 2 +- lib/src/index.d.ts | 3 +- 46 files changed, 128 insertions(+), 103 deletions(-) create mode 100644 lib/__tests__/test-utils.d.ts create mode 100644 lib/__tests__/test-utils.js diff --git a/lib/__tests__/DatePicker/Calendar.test.js b/lib/__tests__/DatePicker/Calendar.test.js index afe954f4d..72163e7dd 100644 --- a/lib/__tests__/DatePicker/Calendar.test.js +++ b/lib/__tests__/DatePicker/Calendar.test.js @@ -1,6 +1,6 @@ import React from 'react'; import moment from 'moment'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { Calendar } from '../../src/DatePicker/Calendar'; describe('Calendar', () => { @@ -11,7 +11,7 @@ describe('Calendar', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/DatePicker/CalendarHeader.test.js b/lib/__tests__/DatePicker/CalendarHeader.test.js index e0b788929..fcda52ce9 100644 --- a/lib/__tests__/DatePicker/CalendarHeader.test.js +++ b/lib/__tests__/DatePicker/CalendarHeader.test.js @@ -1,6 +1,6 @@ import React from 'react'; import moment from 'moment'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { CalendarHeader } from '../../src/DatePicker/CalendarHeader'; describe('CalendarHeader', () => { @@ -11,7 +11,7 @@ describe('CalendarHeader', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/DatePicker/DatePicker.test.js b/lib/__tests__/DatePicker/DatePicker.test.js index 35f89d48e..3946ecb44 100644 --- a/lib/__tests__/DatePicker/DatePicker.test.js +++ b/lib/__tests__/DatePicker/DatePicker.test.js @@ -1,6 +1,6 @@ import React from 'react'; import moment from 'moment'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { DatePicker } from '../../src/DatePicker/DatePicker'; describe('DatePicker', () => { @@ -11,7 +11,7 @@ describe('DatePicker', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/DatePicker/DatePickerWrapper.test.js b/lib/__tests__/DatePicker/DatePickerWrapper.test.js index 0531d1869..e76c06952 100644 --- a/lib/__tests__/DatePicker/DatePickerWrapper.test.js +++ b/lib/__tests__/DatePicker/DatePickerWrapper.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { mount } from 'enzyme'; import moment from 'moment'; +import { shallow } from '../test-utils'; import DatePickerWrapper from '../../src/DatePicker/DatePickerWrapper'; const spy = jest.fn(); @@ -16,30 +16,32 @@ describe('DatePickerWrapper', () => { let component; beforeEach(() => { - component = mount(); + component = shallow(); }); it('Should renders', () => { - // console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); - it('Should support keyboard input', () => { - const input = component.find('input'); - input.simulate('change', { target: { value: '2019' } }); + // 20.02.2018 -> TODO Move keyboard input tests to the text field - expect(spy).toHaveBeenCalled(); - expect(component.state().date.format()).toEqual(moment('2019', 'YYYY').format()); - }); + // it('Should support keyboard input', () => { + // const input = component.find('input'); + // input.simulate('change', { target: { value: '2019' } }); - it('Should not pass disabled dates', () => { - component.setProps({ - disableFuture: true, - }); - const input = component.find('input'); - input.simulate('change', { target: { value: '4000' } }); + // expect(spy).toHaveBeenCalled(); + // expect(component.state().date.format()).toEqual(moment('2019', 'YYYY').format()); + // }); - expect(spy).toHaveBeenCalled(); - expect(component.state().date.format()).toEqual(moment(new Date().getFullYear(), 'YYYY').format()); - }); + // it('Should not pass disabled dates', () => { + // component.setProps({ + // disableFuture: true, + // }); + // const input = component.find('input'); + // input.simulate('change', { target: { value: '4000' } }); + + // expect(spy).toHaveBeenCalled(); + // expect(component.state().date.format()).toEqual(moment(new Date().getFullYear(), 'YYYY').format()); + // }); }); diff --git a/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx b/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx index 4c36b0c37..13645ffd0 100644 --- a/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx +++ b/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx @@ -6,6 +6,8 @@ import { IconButton } from 'material-ui' import * as classNames from 'classnames'; import { Moment } from 'moment' import { DayComponent } from '../../src/DatePicker/Calendar' +import { utilsToUse } from '../test-utils'; +import MuiUtilsProvider from '../../src/utils/MuiPickersUtilsProvider' // initially from the docs site export default class BasicUsage extends Component<{}, {selectedDate: Date}> { @@ -21,7 +23,7 @@ export default class BasicUsage extends Component<{}, {selectedDate: Date}> { const { selectedDate } = this.state; return ( - + { onChange={this.handleChange} animateYearScrolling={false} /> - + ); } } diff --git a/lib/__tests__/DatePicker/YearSelection.test.js b/lib/__tests__/DatePicker/YearSelection.test.js index bfd5b9deb..4aebf6995 100644 --- a/lib/__tests__/DatePicker/YearSelection.test.js +++ b/lib/__tests__/DatePicker/YearSelection.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { shallow } from 'enzyme'; import moment from 'moment'; +import { shallow } from '../test-utils'; import { YearSelection } from '../../src/DatePicker/YearSelection'; describe('YearSelection', () => { @@ -11,7 +11,7 @@ describe('YearSelection', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/DateTimePicker/DateTimePicker.test.js b/lib/__tests__/DateTimePicker/DateTimePicker.test.js index e0bc3e593..ad5c6254c 100644 --- a/lib/__tests__/DateTimePicker/DateTimePicker.test.js +++ b/lib/__tests__/DateTimePicker/DateTimePicker.test.js @@ -1,6 +1,6 @@ import React from 'react'; import moment from 'moment'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { DateTimePicker } from '../../src/DateTimePicker/DateTimePicker'; describe('DateTimePicker', () => { @@ -14,7 +14,7 @@ describe('DateTimePicker', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/DateTimePicker/DateTimePickerHeader.test.js b/lib/__tests__/DateTimePicker/DateTimePickerHeader.test.js index db85631e1..3cba99ed6 100644 --- a/lib/__tests__/DateTimePicker/DateTimePickerHeader.test.js +++ b/lib/__tests__/DateTimePicker/DateTimePickerHeader.test.js @@ -1,6 +1,6 @@ import React from 'react'; import moment from 'moment'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { DateTimePickerHeader } from '../../src/DateTimePicker/DateTimePickerHeader'; describe('DateTimePickerHeader', () => { @@ -16,7 +16,7 @@ describe('DateTimePickerHeader', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/DateTimePicker/DateTimePickerTabs.test.js b/lib/__tests__/DateTimePicker/DateTimePickerTabs.test.js index 23c5c29d6..2930c4dce 100644 --- a/lib/__tests__/DateTimePicker/DateTimePickerTabs.test.js +++ b/lib/__tests__/DateTimePicker/DateTimePickerTabs.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { DateTimePickerTabs } from '../../src/DateTimePicker/DateTimePickerTabs'; describe('DateTimePickerTabs', () => { @@ -13,7 +13,7 @@ describe('DateTimePickerTabs', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/DateTimePicker/DateTimePickerView.test.js b/lib/__tests__/DateTimePicker/DateTimePickerView.test.js index 10fa9b985..a5a4b1f5d 100644 --- a/lib/__tests__/DateTimePicker/DateTimePickerView.test.js +++ b/lib/__tests__/DateTimePicker/DateTimePickerView.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { DateTimePickerView } from '../../src/DateTimePicker/DateTimePickerView'; describe('DateTimePickerView', () => { @@ -10,7 +10,7 @@ describe('DateTimePickerView', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/DateTimePicker/DateTimePickerWrapper.test.js b/lib/__tests__/DateTimePicker/DateTimePickerWrapper.test.js index ea9dee89f..e36fd8796 100644 --- a/lib/__tests__/DateTimePicker/DateTimePickerWrapper.test.js +++ b/lib/__tests__/DateTimePicker/DateTimePickerWrapper.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { DateTimePickerWrapper } from '../../src/DateTimePicker/DateTimePickerWrapper'; describe('DateTimePickerWrapper', () => { @@ -10,7 +10,7 @@ describe('DateTimePickerWrapper', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx b/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx index 82b9d66bb..d41132c6f 100644 --- a/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx +++ b/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx @@ -6,7 +6,9 @@ import DateTimePickerWrapper from '../../src/DateTimePicker/DateTimePickerWrapp import * as classNames from 'classnames' import { Moment } from 'moment' import * as PropTypes from 'prop-types' -import {DayComponent} from '../../src/DatePicker/Calendar' +import { DayComponent } from '../../src/DatePicker/Calendar' +import { utilsToUse } from '../test-utils'; +import MuiUtilsProvider from '../../src/utils/MuiPickersUtilsProvider' // FIXME: src vs exported component names a source of confusion // FIXME https://github.com/dmtrKovalenko/material-ui-pickers/issues/169 @@ -25,7 +27,7 @@ export default class BasicUsage extends Component<{}, {selectedDate: Date}> { const { selectedDate } = this.state; return ( - + { ), }} /> - + ); } } @@ -90,7 +92,7 @@ class CustomElements extends Component<{classes: any}, {selectedDate: Date}> { const { selectedDate } = this.state; return ( - + { renderDay={this.renderCustomDayForDateTime} returnMoment /> - + ); } } \ No newline at end of file diff --git a/lib/__tests__/TimePicker/Clock.test.js b/lib/__tests__/TimePicker/Clock.test.js index 058a2bcc0..ce756a3fe 100644 --- a/lib/__tests__/TimePicker/Clock.test.js +++ b/lib/__tests__/TimePicker/Clock.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { Clock } from '../../src/TimePicker/Clock'; describe('Clock', () => { @@ -10,7 +10,7 @@ describe('Clock', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/TimePicker/ClockNumber.test.js b/lib/__tests__/TimePicker/ClockNumber.test.js index e694aa84c..6f94bf52e 100644 --- a/lib/__tests__/TimePicker/ClockNumber.test.js +++ b/lib/__tests__/TimePicker/ClockNumber.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { ClockNumber } from '../../src/TimePicker/ClockNumber'; describe('ClockNumber', () => { @@ -10,7 +10,7 @@ describe('ClockNumber', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/TimePicker/ClockPointer.test.js b/lib/__tests__/TimePicker/ClockPointer.test.js index 0e920afec..c4ed96541 100644 --- a/lib/__tests__/TimePicker/ClockPointer.test.js +++ b/lib/__tests__/TimePicker/ClockPointer.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { ClockPointer } from '../../src/TimePicker/ClockPointer'; describe('ClockPointer', () => { @@ -10,7 +10,7 @@ describe('ClockPointer', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/TimePicker/HourView.test.js b/lib/__tests__/TimePicker/HourView.test.js index 8bce4fcad..387c53e50 100644 --- a/lib/__tests__/TimePicker/HourView.test.js +++ b/lib/__tests__/TimePicker/HourView.test.js @@ -1,8 +1,8 @@ import React from 'react'; import moment from 'moment'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; -import HourView from '../../src/TimePicker/HourView'; +import { HourView } from '../../src/TimePicker/HourView'; const date = moment(); describe('HourView', () => { @@ -13,7 +13,7 @@ describe('HourView', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/TimePicker/MinutesView.test.js b/lib/__tests__/TimePicker/MinutesView.test.js index 8b168ae12..d62d60ba6 100644 --- a/lib/__tests__/TimePicker/MinutesView.test.js +++ b/lib/__tests__/TimePicker/MinutesView.test.js @@ -1,10 +1,10 @@ import React from 'react'; import moment from 'moment'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; -import MinutesView from '../../src/TimePicker/MinutesView'; +import { MinutesView } from '../../src/TimePicker/MinutesView'; -const date = moment(); +const date = process.env.UTILS === 'moment' ? moment() : new Date(); describe('MinutesView', () => { let component; @@ -14,7 +14,7 @@ describe('MinutesView', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/TimePicker/TimePicker.test.js b/lib/__tests__/TimePicker/TimePicker.test.js index ee9331d98..1a92ad970 100644 --- a/lib/__tests__/TimePicker/TimePicker.test.js +++ b/lib/__tests__/TimePicker/TimePicker.test.js @@ -1,6 +1,6 @@ import React from 'react'; import moment from 'moment'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import { TimePicker } from '../../src/TimePicker/TimePicker'; describe('TimePicker', () => { @@ -15,7 +15,7 @@ describe('TimePicker', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/TimePicker/TimePickerWrapper.test.js b/lib/__tests__/TimePicker/TimePickerWrapper.test.js index c1058f39d..cd406b65e 100644 --- a/lib/__tests__/TimePicker/TimePickerWrapper.test.js +++ b/lib/__tests__/TimePicker/TimePickerWrapper.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { shallow } from 'enzyme'; -import TimePickerWrapper from '../../src/TimePicker/TimePickerWrapper'; +import { shallow } from '../test-utils'; +import { TimePickerWrapper } from '../../src/TimePicker/TimePickerWrapper'; describe('TimePickerWrapper', () => { let component; @@ -10,7 +10,7 @@ describe('TimePickerWrapper', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/TimePicker/TimePickerWrapper.usage.tsx b/lib/__tests__/TimePicker/TimePickerWrapper.usage.tsx index 475c3763d..5de5940f5 100644 --- a/lib/__tests__/TimePicker/TimePickerWrapper.usage.tsx +++ b/lib/__tests__/TimePicker/TimePickerWrapper.usage.tsx @@ -2,6 +2,8 @@ import * as React from 'react' import { Fragment, Component } from 'react'; import TimePickerWrapper from '../../src/TimePicker/TimePickerWrapper'; import { Moment } from 'moment' +import { utilsToUse } from '../test-utils'; +import MuiUtilsProvider from '../../src/utils/MuiPickersUtilsProvider' // initially from the docs site export default class BasicUsage extends Component<{}, {selectedDate: Date}> { @@ -17,7 +19,7 @@ export default class BasicUsage extends Component<{}, {selectedDate: Date}> { const { selectedDate } = this.state; return ( - + { value={selectedDate} onChange={this.handleChange} /> - + ); } } \ No newline at end of file diff --git a/lib/__tests__/_shared/DateTextField.test.js b/lib/__tests__/_shared/DateTextField.test.js index fc545c50c..8851f0fe8 100644 --- a/lib/__tests__/_shared/DateTextField.test.js +++ b/lib/__tests__/_shared/DateTextField.test.js @@ -1,27 +1,22 @@ import React from 'react'; -import { createShallow, createMount } from 'material-ui/test-utils'; +import { createMount } from 'material-ui/test-utils'; +import { shallow } from '../test-utils'; import DateTextField from '../../src/_shared/DateTextField'; describe('DateTextField', () => { let component; beforeEach(() => { - const shallow = createShallow({ dive: true }); component = shallow(); }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); describe('DateTextField with custom TextField', () => { - let shallow; - beforeEach(() => { - shallow = createShallow({ dive: true }); - }); - it('Should handle a component function', () => { function CustomTextField(props) { return ( @@ -32,21 +27,21 @@ describe('DateTextField with custom TextField', () => { const component = shallow(); // Check InputProps to make sure DateTextField is passing props to the custom component - expect(component.prop('InputProps')).toBeTruthy(); + expect(component.props('InputProps')).toBeTruthy(); expect(component.find('li')).toBeTruthy(); }); it('Should handle a component string', () => { const component = shallow(); - expect(component.prop('InputProps')).toBeTruthy(); + expect(component.props('InputProps')).toBeTruthy(); expect(component.find('li')).toBeTruthy(); }); it('Should not handle a node', () => { const mount = createMount(); expect(() => { - mount(} />); + mount(} />); }).toThrow(); }); }); diff --git a/lib/__tests__/_shared/ModalDialog.test.js b/lib/__tests__/_shared/ModalDialog.test.js index a5e3e7447..563ca39f4 100644 --- a/lib/__tests__/_shared/ModalDialog.test.js +++ b/lib/__tests__/_shared/ModalDialog.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import ModalDialog from '../../src/_shared/ModalDialog'; describe('ModalDialog', () => { @@ -10,7 +10,7 @@ describe('ModalDialog', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/_shared/PickerToolbar.test.js b/lib/__tests__/_shared/PickerToolbar.test.js index d88505b98..4d6edbb16 100644 --- a/lib/__tests__/_shared/PickerToolbar.test.js +++ b/lib/__tests__/_shared/PickerToolbar.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import PickerToolbar from '../../src/_shared/PickerToolbar'; describe('PickerToolbar', () => { @@ -10,7 +10,7 @@ describe('PickerToolbar', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/_shared/ToolbarButton.test.js b/lib/__tests__/_shared/ToolbarButton.test.js index e50fa0cd8..a85c11f11 100644 --- a/lib/__tests__/_shared/ToolbarButton.test.js +++ b/lib/__tests__/_shared/ToolbarButton.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import ToolbarButton from '../../src/_shared/ToolbarButton'; describe('ToolbarButton', () => { @@ -10,7 +10,7 @@ describe('ToolbarButton', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/__tests__/test-utils.d.ts b/lib/__tests__/test-utils.d.ts new file mode 100644 index 000000000..169b449d6 --- /dev/null +++ b/lib/__tests__/test-utils.d.ts @@ -0,0 +1,3 @@ +import { Utils } from '../typings/utils' + +export const utilsToUse: Utils; \ No newline at end of file diff --git a/lib/__tests__/test-utils.js b/lib/__tests__/test-utils.js new file mode 100644 index 000000000..3c2ffab0b --- /dev/null +++ b/lib/__tests__/test-utils.js @@ -0,0 +1,14 @@ +import React from 'react'; +import * as enzyme from 'enzyme'; +import dateFnsUtils from '../src/utils/date-fns-utils'; +import momentUtils from '../src/utils/moment-utils'; + +export const utilsToUse = process.env.UTILS === 'moment' + ? momentUtils + : dateFnsUtils; + +const getComponentWithUtils = Component => React.cloneElement(Component, { utils: utilsToUse }); + +export const shallow = Component => enzyme.shallow(getComponentWithUtils(Component)); + +export const mount = Component => enzyme.mount(getComponentWithUtils(Component)); diff --git a/lib/__tests__/utils/time-utils.test.js b/lib/__tests__/utils/time-utils.test.js index 881457979..505d9b237 100644 --- a/lib/__tests__/utils/time-utils.test.js +++ b/lib/__tests__/utils/time-utils.test.js @@ -1,5 +1,6 @@ import moment from 'moment'; -import { getHours, getMinutes, convertToMeridiem } from '../../src/utils/time-utils'; +import { utilsToUse } from '../test-utils'; +import { getHours, getMinutes, convertToMeridiem } from '../../src/_helpers/time-utils'; describe('Time utils', () => { it('Should properly calculate hours', () => { @@ -11,8 +12,8 @@ describe('Time utils', () => { }); it('Should convert time to meridiem', () => { - const time = convertToMeridiem(moment('2017-01-01T16:00'), 'am', true); - expect(time.hours()).toBe(4); + const time = convertToMeridiem(moment('2017-01-01T16:00'), 'am', true, utilsToUse); + expect(utilsToUse.getHours(time)).toBe(4); }); }); diff --git a/lib/__tests__/wrappers/ModalWrapper.test.js b/lib/__tests__/wrappers/ModalWrapper.test.js index a94327a06..d6864706c 100644 --- a/lib/__tests__/wrappers/ModalWrapper.test.js +++ b/lib/__tests__/wrappers/ModalWrapper.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from '../test-utils'; import ModalWrapper from '../../src/wrappers/ModalWrapper'; describe('ModalWrapper', () => { @@ -10,7 +10,7 @@ describe('ModalWrapper', () => { }); it('Should renders', () => { - console.log(component.debug()); // TODO REMOVE ME + // console.log(component.debug()); expect(component).toBeTruthy(); }); }); diff --git a/lib/package.json b/lib/package.json index ff7bea32d..7676d3acb 100644 --- a/lib/package.json +++ b/lib/package.json @@ -45,7 +45,10 @@ "react-text-mask": "^5.0.2" }, "scripts": { - "test": "jest && npm run typescript", + "test": "npm run test:moment && npm run test:date-fns", + "all-tests": "jest && npm run typescript", + "test:moment": "UTILS=moment && npm run all-tests", + "test:date-fns": "UTILS=date-fns && npm run all-tests", "typescript": "tsc -p tsconfig.json", "start": "cross-env NODE_ENV=development rollup --config --watch", "prebuild": "rimraf build", diff --git a/lib/src/DatePicker/Calendar.d.ts b/lib/src/DatePicker/Calendar.d.ts index 7e0167ad6..c472202d4 100644 --- a/lib/src/DatePicker/Calendar.d.ts +++ b/lib/src/DatePicker/Calendar.d.ts @@ -1,7 +1,7 @@ import { ComponentClass, ReactElement, ReactNode } from 'react'; import { IconButtonProps } from 'material-ui/IconButton'; import { DateType } from '../constants/prop-types'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { Moment } from 'moment'; export type DayComponent = ReactElement; diff --git a/lib/src/DatePicker/CalendarHeader.d.ts b/lib/src/DatePicker/CalendarHeader.d.ts index 0e6fe1eb1..cb62a8ecb 100644 --- a/lib/src/DatePicker/CalendarHeader.d.ts +++ b/lib/src/DatePicker/CalendarHeader.d.ts @@ -1,5 +1,5 @@ import { ComponentClass, ReactNode } from 'react'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { Moment } from 'moment'; export interface CalendarHeaderProps { diff --git a/lib/src/DatePicker/DatePicker.d.ts b/lib/src/DatePicker/DatePicker.d.ts index 5dcfd2d0e..40c821ccc 100644 --- a/lib/src/DatePicker/DatePicker.d.ts +++ b/lib/src/DatePicker/DatePicker.d.ts @@ -1,6 +1,6 @@ import { ComponentClass, ReactNode } from 'react'; import { DateType } from '../constants/prop-types'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { RenderDay } from './Calendar'; import { Moment } from 'moment'; diff --git a/lib/src/DatePicker/DatePickerWrapper.d.ts b/lib/src/DatePicker/DatePickerWrapper.d.ts index 9fb6c8cdd..b9ddc840f 100644 --- a/lib/src/DatePicker/DatePickerWrapper.d.ts +++ b/lib/src/DatePicker/DatePickerWrapper.d.ts @@ -1,6 +1,6 @@ import { ComponentClass, ReactNode } from 'react'; import { DateType } from '../constants/prop-types'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { RenderDay } from './Calendar'; import { ModalWrapperProps } from '../wrappers/ModalWrapper'; import { Moment } from 'moment'; diff --git a/lib/src/DatePicker/YearSelection.d.ts b/lib/src/DatePicker/YearSelection.d.ts index 34ff84b40..c96b98a87 100644 --- a/lib/src/DatePicker/YearSelection.d.ts +++ b/lib/src/DatePicker/YearSelection.d.ts @@ -1,6 +1,6 @@ import { ComponentClass, ReactNode } from 'react'; import { DateType } from '../constants/prop-types'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { Moment } from 'moment'; export interface YearSelectionProps { diff --git a/lib/src/DateTimePicker/DateTimePicker.d.ts b/lib/src/DateTimePicker/DateTimePicker.d.ts index 034e879bc..54ec2ba2d 100644 --- a/lib/src/DateTimePicker/DateTimePicker.d.ts +++ b/lib/src/DateTimePicker/DateTimePicker.d.ts @@ -1,7 +1,7 @@ import { ComponentClass, ReactNode } from 'react'; import { DateTimePickerView } from '../constants/date-picker-view'; import { DateType } from '../constants/prop-types'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { RenderDay } from '../DatePicker/Calendar'; import { Moment } from 'moment'; diff --git a/lib/src/DateTimePicker/DateTimePickerHeader.d.ts b/lib/src/DateTimePicker/DateTimePickerHeader.d.ts index d12c876dc..8864e9256 100644 --- a/lib/src/DateTimePicker/DateTimePickerHeader.d.ts +++ b/lib/src/DateTimePicker/DateTimePickerHeader.d.ts @@ -1,6 +1,6 @@ import { ComponentClass } from 'react'; import { DateTimePickerView } from '../constants/date-picker-view'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { Moment } from 'moment'; type MeridiemMode = 'am' | 'pm'; diff --git a/lib/src/DateTimePicker/DateTimePickerWrapper.d.ts b/lib/src/DateTimePicker/DateTimePickerWrapper.d.ts index 36d669df1..37794cc6f 100644 --- a/lib/src/DateTimePicker/DateTimePickerWrapper.d.ts +++ b/lib/src/DateTimePicker/DateTimePickerWrapper.d.ts @@ -1,7 +1,7 @@ import { ComponentClass, ReactNode } from 'react'; import { DateTimePickerView } from '../constants/date-picker-view'; import { DateType } from '../constants/prop-types'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { RenderDay } from '../DatePicker/Calendar'; import { ModalWrapperProps } from '../wrappers/ModalWrapper'; import { Moment } from 'moment'; diff --git a/lib/src/TimePicker/HourView.d.ts b/lib/src/TimePicker/HourView.d.ts index f3f570652..06b2a7e0f 100644 --- a/lib/src/TimePicker/HourView.d.ts +++ b/lib/src/TimePicker/HourView.d.ts @@ -1,5 +1,5 @@ import { ComponentClass } from 'react'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { Moment } from 'moment'; export interface HourViewProps { diff --git a/lib/src/TimePicker/HourView.jsx b/lib/src/TimePicker/HourView.jsx index a4796a77e..2d7a59d41 100644 --- a/lib/src/TimePicker/HourView.jsx +++ b/lib/src/TimePicker/HourView.jsx @@ -5,7 +5,7 @@ import { HOURS } from '../constants/clock-types'; import ClockNumber from './ClockNumber'; import withUtils from '../_shared/WithUtils'; -class HourView extends PureComponent { +export class HourView extends PureComponent { static propTypes = { date: PropTypes.object.isRequired, onChange: PropTypes.func.isRequired, diff --git a/lib/src/TimePicker/MinutesView.d.ts b/lib/src/TimePicker/MinutesView.d.ts index 1c483ab60..76e705056 100644 --- a/lib/src/TimePicker/MinutesView.d.ts +++ b/lib/src/TimePicker/MinutesView.d.ts @@ -1,5 +1,5 @@ import { ComponentClass } from 'react'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { Moment } from 'moment'; export interface MinutesViewProps { diff --git a/lib/src/TimePicker/MinutesView.jsx b/lib/src/TimePicker/MinutesView.jsx index 87b4b89cf..2b280fefd 100644 --- a/lib/src/TimePicker/MinutesView.jsx +++ b/lib/src/TimePicker/MinutesView.jsx @@ -5,7 +5,7 @@ import { MINUTES } from '../constants/clock-types'; import ClockNumber from './ClockNumber'; import withUtils from '../_shared/WithUtils'; -class MinutesView extends Component { +export class MinutesView extends Component { static propTypes = { date: PropTypes.object.isRequired, onChange: PropTypes.func.isRequired, diff --git a/lib/src/TimePicker/TimePicker.d.ts b/lib/src/TimePicker/TimePicker.d.ts index a4b8ccddf..727aa518f 100644 --- a/lib/src/TimePicker/TimePicker.d.ts +++ b/lib/src/TimePicker/TimePicker.d.ts @@ -1,5 +1,5 @@ import { ComponentClass } from 'react'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { Moment } from 'moment'; export interface TimePickerProps { diff --git a/lib/src/TimePicker/TimePickerWrapper.d.ts b/lib/src/TimePicker/TimePickerWrapper.d.ts index 1e93b6edd..a2b9071d4 100644 --- a/lib/src/TimePicker/TimePickerWrapper.d.ts +++ b/lib/src/TimePicker/TimePickerWrapper.d.ts @@ -1,5 +1,5 @@ import { ComponentClass } from 'react'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { ModalWrapperProps } from '../wrappers/ModalWrapper'; import { PickerBaseProps } from '../_shared/PickerBase' import { Omit } from 'material-ui' diff --git a/lib/src/TimePicker/TimePickerWrapper.jsx b/lib/src/TimePicker/TimePickerWrapper.jsx index ba6346f94..919332855 100644 --- a/lib/src/TimePicker/TimePickerWrapper.jsx +++ b/lib/src/TimePicker/TimePickerWrapper.jsx @@ -6,7 +6,7 @@ import TimePicker from './TimePicker'; import PickerBase from '../_shared/PickerBase'; import withUtils from '../_shared/WithUtils'; -class TimePickerWrapper extends PickerBase { +export class TimePickerWrapper extends PickerBase { static propTypes = { value: PropTypes.oneOfType([ PropTypes.object, diff --git a/lib/src/_shared/ModalDialog.d.ts b/lib/src/_shared/ModalDialog.d.ts index 2fb32508b..c457e958d 100644 --- a/lib/src/_shared/ModalDialog.d.ts +++ b/lib/src/_shared/ModalDialog.d.ts @@ -1,6 +1,6 @@ import { ComponentClass, ReactNode } from 'react'; import { DateType } from '../constants/prop-types'; -import { Utils } from '../utils/utils'; +import { Utils } from '../../typings/utils'; import { DialogProps } from 'material-ui/Dialog'; import { ButtonProps } from 'material-ui/Button'; diff --git a/lib/src/index.d.ts b/lib/src/index.d.ts index 50298e750..7d1edc8f1 100644 --- a/lib/src/index.d.ts +++ b/lib/src/index.d.ts @@ -1,4 +1,5 @@ -export { Utils } from './utils/utils'; +export { default as dateFnsUtils } from './utils/date-fns-utils' +export { default as momentUtils } from './utils/moment-utils' export { default as DatePicker } from './DatePicker/DatePickerWrapper'; export { default as TimePicker } from './TimePicker/TimePickerWrapper'; From 46a1938b101af9ea5a1a88f30389a0b47255a051 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 20 Feb 2018 21:49:50 +0200 Subject: [PATCH 08/22] Fix not imported full componenets in some tests --- .../DatePicker/DatePickerWrapper.test.js | 2 +- lib/__tests__/_shared/DateTextField.test.js | 18 ++++++++++++------ lib/src/DatePicker/DatePickerWrapper.jsx | 2 +- lib/src/DatePicker/Year.jsx | 2 +- lib/src/_shared/DateTextField.jsx | 3 ++- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/__tests__/DatePicker/DatePickerWrapper.test.js b/lib/__tests__/DatePicker/DatePickerWrapper.test.js index e76c06952..3780713a4 100644 --- a/lib/__tests__/DatePicker/DatePickerWrapper.test.js +++ b/lib/__tests__/DatePicker/DatePickerWrapper.test.js @@ -1,7 +1,7 @@ import React from 'react'; import moment from 'moment'; import { shallow } from '../test-utils'; -import DatePickerWrapper from '../../src/DatePicker/DatePickerWrapper'; +import { DatePickerWrapper } from '../../src/DatePicker/DatePickerWrapper'; const spy = jest.fn(); diff --git a/lib/__tests__/_shared/DateTextField.test.js b/lib/__tests__/_shared/DateTextField.test.js index 8851f0fe8..1ebc45dc9 100644 --- a/lib/__tests__/_shared/DateTextField.test.js +++ b/lib/__tests__/_shared/DateTextField.test.js @@ -1,13 +1,13 @@ import React from 'react'; import { createMount } from 'material-ui/test-utils'; -import { shallow } from '../test-utils'; -import DateTextField from '../../src/_shared/DateTextField'; +import { shallow, utilsToUse } from '../test-utils'; +import { DateTextField } from '../../src/_shared/DateTextField'; describe('DateTextField', () => { let component; beforeEach(() => { - component = shallow(); + component = shallow(); }); it('Should renders', () => { @@ -24,7 +24,13 @@ describe('DateTextField with custom TextField', () => { ); } - const component = shallow(); + const component = shallow( + + ); // Check InputProps to make sure DateTextField is passing props to the custom component expect(component.props('InputProps')).toBeTruthy(); @@ -32,7 +38,7 @@ describe('DateTextField with custom TextField', () => { }); it('Should handle a component string', () => { - const component = shallow(); + const component = shallow(); expect(component.props('InputProps')).toBeTruthy(); expect(component.find('li')).toBeTruthy(); @@ -41,7 +47,7 @@ describe('DateTextField with custom TextField', () => { it('Should not handle a node', () => { const mount = createMount(); expect(() => { - mount(} />); + mount(} />); }).toThrow(); }); }); diff --git a/lib/src/DatePicker/DatePickerWrapper.jsx b/lib/src/DatePicker/DatePickerWrapper.jsx index 83588168f..2e245c959 100644 --- a/lib/src/DatePicker/DatePickerWrapper.jsx +++ b/lib/src/DatePicker/DatePickerWrapper.jsx @@ -7,7 +7,7 @@ import DomainPropTypes from '../constants/prop-types'; import PickerBase from '../_shared/PickerBase'; import withUtils from '../_shared/WithUtils'; -class DatePickerWrapper extends PickerBase { +export class DatePickerWrapper extends PickerBase { static propTypes = { /* Datepicker value */ value: DomainPropTypes.date, diff --git a/lib/src/DatePicker/Year.jsx b/lib/src/DatePicker/Year.jsx index 4e0ccf271..a74246bec 100644 --- a/lib/src/DatePicker/Year.jsx +++ b/lib/src/DatePicker/Year.jsx @@ -4,7 +4,7 @@ import classnames from 'classnames'; import withStyles from 'material-ui/styles/withStyles'; import Typography from 'material-ui/Typography'; -class Year extends PureComponent { +export class Year extends PureComponent { static propTypes = { children: PropTypes.node.isRequired, classes: PropTypes.object.isRequired, diff --git a/lib/src/_shared/DateTextField.jsx b/lib/src/_shared/DateTextField.jsx index 1bba8a492..ca718a8d7 100644 --- a/lib/src/_shared/DateTextField.jsx +++ b/lib/src/_shared/DateTextField.jsx @@ -11,7 +11,7 @@ import DomainPropTypes from '../constants/prop-types'; import MaskedInput from './MaskedInput'; import withUtils from '../_shared/WithUtils'; -class DateTextField extends PureComponent { +export class DateTextField extends PureComponent { static propTypes = { classes: PropTypes.shape({}).isRequired, value: PropTypes.oneOfType([ @@ -235,6 +235,7 @@ class DateTextField extends PureComponent { TextFieldComponent, ...other } = this.props; + console.log(classes) const { displayValue, error } = this.state; const localInputProps = { From 2e2db64c534f6d1324bede3c20892c6db7bf545e Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 20 Feb 2018 21:54:27 +0200 Subject: [PATCH 09/22] Remove console.log --- lib/src/_shared/DateTextField.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/_shared/DateTextField.jsx b/lib/src/_shared/DateTextField.jsx index ca718a8d7..b706a3b9e 100644 --- a/lib/src/_shared/DateTextField.jsx +++ b/lib/src/_shared/DateTextField.jsx @@ -235,7 +235,6 @@ export class DateTextField extends PureComponent { TextFieldComponent, ...other } = this.props; - console.log(classes) const { displayValue, error } = this.state; const localInputProps = { From 97ee95e130b66f9f3fa6e0a03aa91b2b5be5363b Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 21 Feb 2018 12:11:42 +0200 Subject: [PATCH 10/22] Change build system to direct import from components name (without src) --- docs/src/App.js | 2 +- lib/.babelrc | 4 +- lib/copy.js | 4 +- lib/package-lock.json | 19 +++++-- lib/package.json | 4 +- .../{DatePickerWrapper.d.ts => index.d.ts} | 0 .../{DatePickerWrapper.jsx => index.jsx} | 0 ...{DateTimePickerWrapper.d.ts => index.d.ts} | 0 .../{DateTimePickerWrapper.jsx => index.jsx} | 0 .../{TimePickerWrapper.d.ts => index.d.ts} | 0 .../{TimePickerWrapper.jsx => index.jsx} | 0 lib/src/_shared/DateTextField.jsx | 9 ++-- lib/src/_shared/PickerBase.d.ts | 1 + lib/src/index.js | 6 +-- lib/src/utils/date-fns-utils.js | 51 ++++++++++--------- lib/src/utils/moment-utils.js | 6 ++- 16 files changed, 61 insertions(+), 45 deletions(-) rename lib/src/DatePicker/{DatePickerWrapper.d.ts => index.d.ts} (100%) rename lib/src/DatePicker/{DatePickerWrapper.jsx => index.jsx} (100%) rename lib/src/DateTimePicker/{DateTimePickerWrapper.d.ts => index.d.ts} (100%) rename lib/src/DateTimePicker/{DateTimePickerWrapper.jsx => index.jsx} (100%) rename lib/src/TimePicker/{TimePickerWrapper.d.ts => index.d.ts} (100%) rename lib/src/TimePicker/{TimePickerWrapper.jsx => index.jsx} (100%) diff --git a/docs/src/App.js b/docs/src/App.js index 9546113df..e57b84c8f 100644 --- a/docs/src/App.js +++ b/docs/src/App.js @@ -56,7 +56,7 @@ export default class App extends Component {
- + copyTypings(path.resolve(__dirname, 'src'), path.resolve(__dirname, 'build/src'))) + .then(() => copyTypings(path.resolve(__dirname, 'src'), path.resolve(__dirname, 'build'))) .then(() => copyReadme()); diff --git a/lib/package-lock.json b/lib/package-lock.json index 1c071994e..753aef7ed 100644 --- a/lib/package-lock.json +++ b/lib/package-lock.json @@ -1982,9 +1982,9 @@ } }, "date-fns": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", - "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" + "version": "2.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.0.0-alpha.7.tgz", + "integrity": "sha1-JFrRb5V2Tqur+ywKQf1dAzwg5Xo=" }, "debug": { "version": "2.6.9", @@ -2028,6 +2028,12 @@ "is-obj": "1.0.1" } }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -5938,6 +5944,12 @@ "restore-cursor": "1.0.1" } }, + "date-fns": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==", + "dev": true + }, "figures": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", @@ -7312,6 +7324,7 @@ "integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=", "dev": true, "requires": { + "deep-extend": "0.4.2", "ini": "1.3.5", "minimist": "1.2.0", "strip-json-comments": "2.0.1" diff --git a/lib/package.json b/lib/package.json index 7676d3acb..4dab8fd31 100644 --- a/lib/package.json +++ b/lib/package.json @@ -5,7 +5,7 @@ "description": "React components, that implements material design pickers for material-ui v1", "main": "build/dist/material-ui-pickers.cjs.js", "module": "build/dist/material-ui-pickers.es.js", - "types": "./src/index.d.ts", + "types": "src/index.d.ts", "keywords": [ "material-ui", "pickers", @@ -40,7 +40,7 @@ "react-dom": "^16.2.0" }, "dependencies": { - "date-fns": "^1.29.0", + "date-fns": "^2.0.0-alpha.7", "moment-range": "^3.0.3", "react-text-mask": "^5.0.2" }, diff --git a/lib/src/DatePicker/DatePickerWrapper.d.ts b/lib/src/DatePicker/index.d.ts similarity index 100% rename from lib/src/DatePicker/DatePickerWrapper.d.ts rename to lib/src/DatePicker/index.d.ts diff --git a/lib/src/DatePicker/DatePickerWrapper.jsx b/lib/src/DatePicker/index.jsx similarity index 100% rename from lib/src/DatePicker/DatePickerWrapper.jsx rename to lib/src/DatePicker/index.jsx diff --git a/lib/src/DateTimePicker/DateTimePickerWrapper.d.ts b/lib/src/DateTimePicker/index.d.ts similarity index 100% rename from lib/src/DateTimePicker/DateTimePickerWrapper.d.ts rename to lib/src/DateTimePicker/index.d.ts diff --git a/lib/src/DateTimePicker/DateTimePickerWrapper.jsx b/lib/src/DateTimePicker/index.jsx similarity index 100% rename from lib/src/DateTimePicker/DateTimePickerWrapper.jsx rename to lib/src/DateTimePicker/index.jsx diff --git a/lib/src/TimePicker/TimePickerWrapper.d.ts b/lib/src/TimePicker/index.d.ts similarity index 100% rename from lib/src/TimePicker/TimePickerWrapper.d.ts rename to lib/src/TimePicker/index.d.ts diff --git a/lib/src/TimePicker/TimePickerWrapper.jsx b/lib/src/TimePicker/index.jsx similarity index 100% rename from lib/src/TimePicker/TimePickerWrapper.jsx rename to lib/src/TimePicker/index.jsx diff --git a/lib/src/_shared/DateTextField.jsx b/lib/src/_shared/DateTextField.jsx index b706a3b9e..59eb0543e 100644 --- a/lib/src/_shared/DateTextField.jsx +++ b/lib/src/_shared/DateTextField.jsx @@ -99,7 +99,6 @@ export class DateTextField extends PureComponent { minDateMessage, invalidDateMessage, } = this.props; - if (!utils.isValid(value)) { // if null - do not show error if (utils.isNull(value)) { @@ -149,10 +148,10 @@ export class DateTextField extends PureComponent { handleChange = (e) => { const { - format, clearable, onClear, utils, + format, } = this.props; if (clearable && e.target.value === '') { @@ -166,7 +165,8 @@ export class DateTextField extends PureComponent { } const oldValue = utils.date(this.state.value); - const newValue = utils.date(e.target.value, format, true); + const newValue = utils.parse(e.target.value, format); + const error = this.getError(newValue); this.setState({ @@ -175,7 +175,7 @@ export class DateTextField extends PureComponent { error, }, () => { if (!error && utils.format(newValue, 'LLLL') !== utils.format(oldValue, 'LLLL')) { - this.props.onChange(newValue, true); + this.props.onChange(newValue); } }); } @@ -190,7 +190,6 @@ export class DateTextField extends PureComponent { } e.target.blur(); - this.openPicker(e); } diff --git a/lib/src/_shared/PickerBase.d.ts b/lib/src/_shared/PickerBase.d.ts index b112ccec4..83cce0615 100644 --- a/lib/src/_shared/PickerBase.d.ts +++ b/lib/src/_shared/PickerBase.d.ts @@ -1,4 +1,5 @@ import {Moment} from 'moment' +import { DateTextFieldProps } from './ModalDialog'; export interface PickerBaseProps { onChange: (date: Date | Moment) => void; diff --git a/lib/src/index.js b/lib/src/index.js index b0f44c714..dbea138ff 100644 --- a/lib/src/index.js +++ b/lib/src/index.js @@ -1,8 +1,8 @@ -export { default as DatePicker } from './DatePicker/DatePickerWrapper'; +export { default as DatePicker } from './DatePicker'; -export { default as TimePicker } from './TimePicker/TimePickerWrapper'; +export { default as TimePicker } from './TimePicker'; -export { default as DateTimePicker } from './DateTimePicker/DateTimePickerWrapper'; +export { default as DateTimePicker } from './DateTimePicker'; export { default as MuiPickerUtilsProvider } from './utils/MuiPickersUtilsProvider'; diff --git a/lib/src/utils/date-fns-utils.js b/lib/src/utils/date-fns-utils.js index a146290f7..53b136f0e 100644 --- a/lib/src/utils/date-fns-utils.js +++ b/lib/src/utils/date-fns-utils.js @@ -1,31 +1,32 @@ -import addDays from 'date-fns/add_days'; -import addMonths from 'date-fns/add_months'; -import addYears from 'date-fns/add_years'; -import endOfDay from 'date-fns/end_of_day'; -import endOfMonth from 'date-fns/end_of_month'; -import endOfWeek from 'date-fns/end_of_week'; -import endOfYear from 'date-fns/end_of_year'; +import parse from 'date-fns/parse'; +import addDays from 'date-fns/addDays'; +import addMonths from 'date-fns/addMonths'; +import addYears from 'date-fns/addYears'; +import endOfDay from 'date-fns/endOfDay'; +import endOfMonth from 'date-fns/endOfMonth'; +import endOfWeek from 'date-fns/endOfWeek'; +import endOfYear from 'date-fns/endOfYear'; import format from 'date-fns/format'; -import isAfter from 'date-fns/is_after'; -import isBefore from 'date-fns/is_before'; -import isSameDay from 'date-fns/is_same_day'; -import isValid from 'date-fns/is_valid'; -import setDay from 'date-fns/set_day'; -import setHours from 'date-fns/set_hours'; -import setMinutes from 'date-fns/set_minutes'; -import setYear from 'date-fns/set_year'; -import startOfDay from 'date-fns/start_of_day'; -import startOfMonth from 'date-fns/start_of_month'; -import startOfWeek from 'date-fns/start_of_week'; -import startOfYear from 'date-fns/start_of_year'; -import getHours from 'date-fns/get_hours'; -import getYear from 'date-fns/get_year'; -import isEqual from 'date-fns/is_equal'; +import isAfter from 'date-fns/isAfter'; +import isBefore from 'date-fns/isBefore'; +import isSameDay from 'date-fns/isSameDay'; +import isValid from 'date-fns/isValid'; +import setDay from 'date-fns/setDay'; +import setHours from 'date-fns/setHours'; +import setMinutes from 'date-fns/setMinutes'; +import setYear from 'date-fns/setYear'; +import startOfDay from 'date-fns/startOfDay'; +import startOfMonth from 'date-fns/startOfMonth'; +import startOfWeek from 'date-fns/startOfWeek'; +import startOfYear from 'date-fns/startOfYear'; +import getHours from 'date-fns/getHours'; +import getYear from 'date-fns/getYear'; +import isEqual from 'date-fns/isEqual'; export default class DateFnsUtils { - static date(value) { - return new Date(value); - } + static date = value => new Date(value) + + static parse = (value, formatString) => parse(value, formatString, new Date()) static addDays = addDays diff --git a/lib/src/utils/moment-utils.js b/lib/src/utils/moment-utils.js index a84d5a2c3..11d5869bb 100644 --- a/lib/src/utils/moment-utils.js +++ b/lib/src/utils/moment-utils.js @@ -4,8 +4,10 @@ import { extendMoment } from 'moment-range'; const moment = extendMoment(Moment); export default class MomentUtils { - static date(value) { - return moment(value); + static parse = moment + + static date(value, formatString) { + return moment(value, formatString); } static isValid(date) { From fad69c58d72ec88126b8f501a5d9a1014fb833c1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 21 Feb 2018 12:15:20 +0200 Subject: [PATCH 11/22] Fix unit tests --- lib/__tests__/DatePicker/DatePickerWrapper.test.js | 2 +- lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx | 2 +- lib/__tests__/DateTimePicker/DateTimePickerWrapper.test.js | 2 +- .../DateTimePicker/DateTimePickerWrapper.usage.tsx | 6 +----- lib/__tests__/TimePicker/TimePickerWrapper.test.js | 2 +- lib/__tests__/TimePicker/TimePickerWrapper.usage.tsx | 2 +- lib/src/index.d.ts | 6 +++--- 7 files changed, 9 insertions(+), 13 deletions(-) diff --git a/lib/__tests__/DatePicker/DatePickerWrapper.test.js b/lib/__tests__/DatePicker/DatePickerWrapper.test.js index 3780713a4..2ae2b1a6b 100644 --- a/lib/__tests__/DatePicker/DatePickerWrapper.test.js +++ b/lib/__tests__/DatePicker/DatePickerWrapper.test.js @@ -1,7 +1,7 @@ import React from 'react'; import moment from 'moment'; import { shallow } from '../test-utils'; -import { DatePickerWrapper } from '../../src/DatePicker/DatePickerWrapper'; +import { DatePickerWrapper } from '../../src/DatePicker'; const spy = jest.fn(); diff --git a/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx b/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx index 13645ffd0..8dcf5ab68 100644 --- a/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx +++ b/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import * as PropTypes from 'prop-types'; import { Fragment, Component } from 'react'; -import DatePickerWrapper from '../../src/DatePicker/DatePickerWrapper'; +import DatePickerWrapper from '../../src/DatePicker'; import { IconButton } from 'material-ui' import * as classNames from 'classnames'; import { Moment } from 'moment' diff --git a/lib/__tests__/DateTimePicker/DateTimePickerWrapper.test.js b/lib/__tests__/DateTimePicker/DateTimePickerWrapper.test.js index e36fd8796..03a0498da 100644 --- a/lib/__tests__/DateTimePicker/DateTimePickerWrapper.test.js +++ b/lib/__tests__/DateTimePicker/DateTimePickerWrapper.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { shallow } from '../test-utils'; -import { DateTimePickerWrapper } from '../../src/DateTimePicker/DateTimePickerWrapper'; +import { DateTimePickerWrapper } from '../../src/DateTimePicker'; describe('DateTimePickerWrapper', () => { let component; diff --git a/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx b/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx index d41132c6f..1002e2358 100644 --- a/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx +++ b/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx @@ -2,7 +2,7 @@ import * as React from 'react' import { Fragment, Component } from 'react'; import { IconButton, Typography, Icon } from 'material-ui'; import InputAdornment from 'material-ui/Input/InputAdornment'; -import DateTimePickerWrapper from '../../src/DateTimePicker/DateTimePickerWrapper'; +import DateTimePickerWrapper from '../../src/DateTimePicker'; import * as classNames from 'classnames' import { Moment } from 'moment' import * as PropTypes from 'prop-types' @@ -10,10 +10,6 @@ import { DayComponent } from '../../src/DatePicker/Calendar' import { utilsToUse } from '../test-utils'; import MuiUtilsProvider from '../../src/utils/MuiPickersUtilsProvider' -// FIXME: src vs exported component names a source of confusion -// FIXME https://github.com/dmtrKovalenko/material-ui-pickers/issues/169 - -// initially from the docs site export default class BasicUsage extends Component<{}, {selectedDate: Date}> { state = { selectedDate: new Date(), diff --git a/lib/__tests__/TimePicker/TimePickerWrapper.test.js b/lib/__tests__/TimePicker/TimePickerWrapper.test.js index cd406b65e..d096ce216 100644 --- a/lib/__tests__/TimePicker/TimePickerWrapper.test.js +++ b/lib/__tests__/TimePicker/TimePickerWrapper.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { shallow } from '../test-utils'; -import { TimePickerWrapper } from '../../src/TimePicker/TimePickerWrapper'; +import { TimePickerWrapper } from '../../src/TimePicker'; describe('TimePickerWrapper', () => { let component; diff --git a/lib/__tests__/TimePicker/TimePickerWrapper.usage.tsx b/lib/__tests__/TimePicker/TimePickerWrapper.usage.tsx index 5de5940f5..2c4e9bcc7 100644 --- a/lib/__tests__/TimePicker/TimePickerWrapper.usage.tsx +++ b/lib/__tests__/TimePicker/TimePickerWrapper.usage.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { Fragment, Component } from 'react'; -import TimePickerWrapper from '../../src/TimePicker/TimePickerWrapper'; +import TimePickerWrapper from '../../src/TimePicker'; import { Moment } from 'moment' import { utilsToUse } from '../test-utils'; import MuiUtilsProvider from '../../src/utils/MuiPickersUtilsProvider' diff --git a/lib/src/index.d.ts b/lib/src/index.d.ts index 7d1edc8f1..b8d24c1b2 100644 --- a/lib/src/index.d.ts +++ b/lib/src/index.d.ts @@ -1,6 +1,6 @@ export { default as dateFnsUtils } from './utils/date-fns-utils' export { default as momentUtils } from './utils/moment-utils' -export { default as DatePicker } from './DatePicker/DatePickerWrapper'; -export { default as TimePicker } from './TimePicker/TimePickerWrapper'; -export { default as DateTimePicker } from './DateTimePicker/DateTimePickerWrapper'; +export { default as DatePicker } from './DatePicker'; +export { default as TimePicker } from './TimePicker'; +export { default as DateTimePicker } from './DateTimePicker'; From e8e5ec1e64d4e68a76c7cb5403a3be24f0e7809f Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 21 Feb 2018 14:49:42 +0200 Subject: [PATCH 12/22] Change all moment types to Date or Moment in type defenitions --- lib/src/DatePicker/Calendar.d.ts | 12 ++++++------ lib/src/DatePicker/CalendarHeader.d.ts | 4 ++-- lib/src/DatePicker/DatePicker.d.ts | 8 ++++---- lib/src/DatePicker/YearSelection.d.ts | 6 +++--- lib/src/DatePicker/index.d.ts | 4 ++-- lib/src/DateTimePicker/DateTimePicker.d.ts | 8 ++++---- lib/src/DateTimePicker/DateTimePickerHeader.d.ts | 4 ++-- lib/src/DateTimePicker/index.d.ts | 4 ++-- lib/src/TimePicker/HourView.d.ts | 6 +++--- lib/src/TimePicker/MinutesView.d.ts | 6 +++--- lib/src/TimePicker/TimePicker.d.ts | 6 +++--- 11 files changed, 34 insertions(+), 34 deletions(-) diff --git a/lib/src/DatePicker/Calendar.d.ts b/lib/src/DatePicker/Calendar.d.ts index c472202d4..1b5cc12e1 100644 --- a/lib/src/DatePicker/Calendar.d.ts +++ b/lib/src/DatePicker/Calendar.d.ts @@ -2,31 +2,31 @@ import { ComponentClass, ReactElement, ReactNode } from 'react'; import { IconButtonProps } from 'material-ui/IconButton'; import { DateType } from '../constants/prop-types'; import { Utils } from '../../typings/utils'; -import { Moment } from 'moment'; +import { MaterialUiPickersDate } from '../../typings/date' export type DayComponent = ReactElement; export type RenderDay = ( - day: Moment, - selectedDate: Moment, + day: MaterialUiPickersDate, + selectedDate: MaterialUiPickersDate, dayInCurrentMonth: boolean, dayComponent: DayComponent, ) => ReactNode; export interface CalendarProps { - date: Moment; + date: MaterialUiPickersDate; minDate?: DateType; maxDate?: DateType; - onChange: (date: Moment) => void; + onChange: (date: MaterialUiPickersDate) => void; disablePast?: boolean; disableFuture?: boolean; leftArrowIcon?: ReactNode; rightArrowIcon?: ReactNode; renderDay?: RenderDay; utils?: Utils; - shouldDisableDate?: (day: Moment) => boolean; + shouldDisableDate?: (day: MaterialUiPickersDate) => boolean; } declare const Calendar: ComponentClass; diff --git a/lib/src/DatePicker/CalendarHeader.d.ts b/lib/src/DatePicker/CalendarHeader.d.ts index cb62a8ecb..038b2396b 100644 --- a/lib/src/DatePicker/CalendarHeader.d.ts +++ b/lib/src/DatePicker/CalendarHeader.d.ts @@ -1,10 +1,10 @@ import { ComponentClass, ReactNode } from 'react'; import { Utils } from '../../typings/utils'; -import { Moment } from 'moment'; +import { MaterialUiPickersDate } from '../../typings/date' export interface CalendarHeaderProps { currentMonth: object; - onMonthChange: (date: Moment) => void; + onMonthChange: (date: MaterialUiPickersDate) => void; leftArrowIcon?: ReactNode; rightArrowIcon?: ReactNode; utils?: Utils; diff --git a/lib/src/DatePicker/DatePicker.d.ts b/lib/src/DatePicker/DatePicker.d.ts index 40c821ccc..1f1dcab80 100644 --- a/lib/src/DatePicker/DatePicker.d.ts +++ b/lib/src/DatePicker/DatePicker.d.ts @@ -2,13 +2,13 @@ import { ComponentClass, ReactNode } from 'react'; import { DateType } from '../constants/prop-types'; import { Utils } from '../../typings/utils'; import { RenderDay } from './Calendar'; -import { Moment } from 'moment'; +import { MaterialUiPickersDate } from '../../typings/date' export interface DatePickerProps { - date: Moment; + date: MaterialUiPickersDate; minDate?: DateType; maxDate?: DateType; - onChange: (date: Moment, isFinished?: boolean) => void; + onChange: (date: MaterialUiPickersDate, isFinished?: boolean) => void; disablePast?: boolean; disableFuture?: boolean; animateYearScrolling?: boolean; @@ -17,7 +17,7 @@ export interface DatePickerProps { rightArrowIcon?: ReactNode; renderDay?: RenderDay; utils?: Utils; - shouldDisableDate?: (day: Moment) => boolean; + shouldDisableDate?: (day: MaterialUiPickersDate) => boolean; } declare const DatePicker: ComponentClass; diff --git a/lib/src/DatePicker/YearSelection.d.ts b/lib/src/DatePicker/YearSelection.d.ts index c96b98a87..c9c76466c 100644 --- a/lib/src/DatePicker/YearSelection.d.ts +++ b/lib/src/DatePicker/YearSelection.d.ts @@ -1,13 +1,13 @@ import { ComponentClass, ReactNode } from 'react'; import { DateType } from '../constants/prop-types'; import { Utils } from '../../typings/utils'; -import { Moment } from 'moment'; +import { MaterialUiPickersDate } from '../../typings/date' export interface YearSelectionProps { - date: Moment; + date: MaterialUiPickersDate; minDate?: DateType; maxDate?: DateType; - onChange: (date: Moment) => void; + onChange: (date: MaterialUiPickersDate) => void; disablePast?: boolean; disableFuture?: boolean; animateYearScrolling?: boolean; diff --git a/lib/src/DatePicker/index.d.ts b/lib/src/DatePicker/index.d.ts index b9ddc840f..965e9a87e 100644 --- a/lib/src/DatePicker/index.d.ts +++ b/lib/src/DatePicker/index.d.ts @@ -3,7 +3,7 @@ import { DateType } from '../constants/prop-types'; import { Utils } from '../../typings/utils'; import { RenderDay } from './Calendar'; import { ModalWrapperProps } from '../wrappers/ModalWrapper'; -import { Moment } from 'moment'; +import { MaterialUiPickersDate } from '../../typings/date' import { PickerBaseProps } from '../_shared/PickerBase' import { Omit } from 'material-ui' @@ -19,7 +19,7 @@ export interface DatePickerWrapperProps extends PickerBaseProps, rightArrowIcon?: ReactNode; renderDay?: RenderDay; utils?: Utils; - shouldDisableDate?: (day: Moment) => boolean; + shouldDisableDate?: (day: MaterialUiPickersDate) => boolean; } declare const DatePickerWrapper: ComponentClass; diff --git a/lib/src/DateTimePicker/DateTimePicker.d.ts b/lib/src/DateTimePicker/DateTimePicker.d.ts index 54ec2ba2d..2c1aa406e 100644 --- a/lib/src/DateTimePicker/DateTimePicker.d.ts +++ b/lib/src/DateTimePicker/DateTimePicker.d.ts @@ -3,13 +3,13 @@ import { DateTimePickerView } from '../constants/date-picker-view'; import { DateType } from '../constants/prop-types'; import { Utils } from '../../typings/utils'; import { RenderDay } from '../DatePicker/Calendar'; -import { Moment } from 'moment'; +import { MaterialUiPickersDate } from '../../typings/date' export interface DateTimePickerProps { - date: Moment; + date: MaterialUiPickersDate; minDate?: DateType; maxDate?: DateType; - onChange: (date: Moment, isFinished: boolean, viewType?: DateTimePickerView) => void; + onChange: (date: MaterialUiPickersDate, isFinished: boolean, viewType?: DateTimePickerView) => void; disablePast?: boolean; disableFuture?: boolean; autoSubmit?: boolean; @@ -23,7 +23,7 @@ export interface DateTimePickerProps { timeIcon?: ReactNode; renderDay?: RenderDay; utils?: Utils; - shouldDisableDate?: (day: Moment) => boolean; + shouldDisableDate?: (day: MaterialUiPickersDate) => boolean; } declare const DateTimePicker: ComponentClass; diff --git a/lib/src/DateTimePicker/DateTimePickerHeader.d.ts b/lib/src/DateTimePicker/DateTimePickerHeader.d.ts index 8864e9256..3583a9406 100644 --- a/lib/src/DateTimePicker/DateTimePickerHeader.d.ts +++ b/lib/src/DateTimePicker/DateTimePickerHeader.d.ts @@ -1,12 +1,12 @@ import { ComponentClass } from 'react'; import { DateTimePickerView } from '../constants/date-picker-view'; import { Utils } from '../../typings/utils'; -import { Moment } from 'moment'; +import { MaterialUiPickersDate } from '../../typings/date' type MeridiemMode = 'am' | 'pm'; export interface DateTimePickerHeaderProps { - date: Moment; + date: MaterialUiPickersDate; meridiemMode: MeridiemMode; openView: DateTimePickerView; onOpenViewChange: (view: DateTimePickerView) => void; diff --git a/lib/src/DateTimePicker/index.d.ts b/lib/src/DateTimePicker/index.d.ts index 37794cc6f..53f201f62 100644 --- a/lib/src/DateTimePicker/index.d.ts +++ b/lib/src/DateTimePicker/index.d.ts @@ -4,7 +4,7 @@ import { DateType } from '../constants/prop-types'; import { Utils } from '../../typings/utils'; import { RenderDay } from '../DatePicker/Calendar'; import { ModalWrapperProps } from '../wrappers/ModalWrapper'; -import { Moment } from 'moment'; +import { MaterialUiPickersDate } from '../../typings/date' import { PickerBaseProps } from '../_shared/PickerBase' import { Omit } from 'material-ui' @@ -24,7 +24,7 @@ export interface DateTimePickerWrapperProps extends PickerBaseProps, timeIcon?: ReactNode; renderDay?: RenderDay; utils?: Utils; - shouldDisableDate?: (day: Moment) => boolean; + shouldDisableDate?: (day: MaterialUiPickersDate) => boolean; } declare const DateTimePickerWrapper: ComponentClass; diff --git a/lib/src/TimePicker/HourView.d.ts b/lib/src/TimePicker/HourView.d.ts index 06b2a7e0f..884197f18 100644 --- a/lib/src/TimePicker/HourView.d.ts +++ b/lib/src/TimePicker/HourView.d.ts @@ -1,10 +1,10 @@ import { ComponentClass } from 'react'; import { Utils } from '../../typings/utils'; -import { Moment } from 'moment'; +import { MaterialUiPickersDate } from '../../typings/date' export interface HourViewProps { - date: Moment; - onChange: (date: Moment, isFinished?: boolean) => void; + date: MaterialUiPickersDate; + onChange: (date: MaterialUiPickersDate, isFinished?: boolean) => void; ampm?: boolean; utils?: Utils; } diff --git a/lib/src/TimePicker/MinutesView.d.ts b/lib/src/TimePicker/MinutesView.d.ts index 76e705056..ed54eb2d5 100644 --- a/lib/src/TimePicker/MinutesView.d.ts +++ b/lib/src/TimePicker/MinutesView.d.ts @@ -1,10 +1,10 @@ import { ComponentClass } from 'react'; import { Utils } from '../../typings/utils'; -import { Moment } from 'moment'; +import { MaterialUiPickersDate } from '../../typings/date' export interface MinutesViewProps { - date: Moment; - onChange: (date: Moment, isFinished?: boolean) => void; + date: MaterialUiPickersDate; + onChange: (date: MaterialUiPickersDate, isFinished?: boolean) => void; utils?: Utils; } diff --git a/lib/src/TimePicker/TimePicker.d.ts b/lib/src/TimePicker/TimePicker.d.ts index 727aa518f..c25cf342d 100644 --- a/lib/src/TimePicker/TimePicker.d.ts +++ b/lib/src/TimePicker/TimePicker.d.ts @@ -1,10 +1,10 @@ import { ComponentClass } from 'react'; import { Utils } from '../../typings/utils'; -import { Moment } from 'moment'; +import { MaterialUiPickersDate } from '../../typings/date' export interface TimePickerProps { - date: Moment; - onChange: (date: Moment, isFinished?: boolean) => void; + date: MaterialUiPickersDate; + onChange: (date: MaterialUiPickersDate, isFinished?: boolean) => void; ampm?: boolean; utils?: Utils; } From 1b567fdc0c1f9665fe57cbdf93b71baf2878ff42 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 21 Feb 2018 15:23:45 +0200 Subject: [PATCH 13/22] Make date type unknown --- lib/typings/date.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/typings/date.ts b/lib/typings/date.ts index 92b46a635..d60b25bab 100644 --- a/lib/typings/date.ts +++ b/lib/typings/date.ts @@ -1,3 +1,4 @@ import { Moment } from 'moment'; -export type MaterialUiPickersDate = Moment | Date \ No newline at end of file +// 21.02.2018 - TODO type date, if there would be any way to dynamicly type Moment | Date +export type MaterialUiPickersDate = any \ No newline at end of file From dc165403eced9ca2fa2b850adaf6d1346f1e9050 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 22 Feb 2018 09:31:39 +0200 Subject: [PATCH 14/22] Merge conflicts --- lib/package.json | 6 ++++-- lib/rollup.config.js | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/package.json b/lib/package.json index 4dab8fd31..0837dfb08 100644 --- a/lib/package.json +++ b/lib/package.json @@ -34,13 +34,15 @@ "peerDependencies": { "classnames": "^2.2.5", "material-ui": "^1.0.0-beta.33", - "moment": "^2.19.2", "prop-types": "^15.6.0", "react": "^16.2.0", "react-dom": "^16.2.0" }, + "externalDependencies": { + "moment": "^2.19.2", + "date-fns": "^2.0.0-alpha.7" + }, "dependencies": { - "date-fns": "^2.0.0-alpha.7", "moment-range": "^3.0.3", "react-text-mask": "^5.0.2" }, diff --git a/lib/rollup.config.js b/lib/rollup.config.js index 237e04e7a..89ce5af41 100644 --- a/lib/rollup.config.js +++ b/lib/rollup.config.js @@ -6,6 +6,7 @@ import pkg from './package.json'; const externalDependencies = new RegExp(`^(${[ ...Object.keys(pkg.peerDependencies || {}), + ...Object.keys(pkg.externalDependencies || {}), ].join('|')})([/]|$)`); export default { From 9d6887cc4fb945ed20b489a013dedc634d7bea78 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 22 Feb 2018 09:50:36 +0200 Subject: [PATCH 15/22] Fix utils interface typings errors, fix typo in exported MuiPickerUtilsProvider name --- docs/src/App.js | 6 +++--- lib/package-lock.json | 3 ++- lib/package.json | 1 + lib/src/index.js | 2 +- lib/typings/utils.ts | 7 +++---- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/src/App.js b/docs/src/App.js index e57b84c8f..396f1052a 100644 --- a/docs/src/App.js +++ b/docs/src/App.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { MuiThemeProvider, createMuiTheme } from 'material-ui'; -import { MuiPickerUtilsProvider, dateFnsUtils, momentUtils } from 'material-ui-pickers'; +import { MuiPickersUtilsProvider, dateFnsUtils, momentUtils } from 'material-ui-pickers'; import { create } from 'jss'; import preset from 'jss-preset-default'; @@ -56,13 +56,13 @@ export default class App extends Component {
- + - +
diff --git a/lib/package-lock.json b/lib/package-lock.json index 753aef7ed..6c9b50909 100644 --- a/lib/package-lock.json +++ b/lib/package-lock.json @@ -1984,7 +1984,8 @@ "date-fns": { "version": "2.0.0-alpha.7", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.0.0-alpha.7.tgz", - "integrity": "sha1-JFrRb5V2Tqur+ywKQf1dAzwg5Xo=" + "integrity": "sha1-JFrRb5V2Tqur+ywKQf1dAzwg5Xo=", + "dev": true }, "debug": { "version": "2.6.9", diff --git a/lib/package.json b/lib/package.json index 0837dfb08..0252f658d 100644 --- a/lib/package.json +++ b/lib/package.json @@ -85,6 +85,7 @@ "babel-preset-latest": "^6.24.1", "classnames": "^2.2.5", "cross-env": "^5.1.0", + "date-fns": "^2.0.0-alpha.7", "enzyme": "^3.3.0", "enzyme-adapter-react-16": "^1.1.0", "eslint": "^4.17.0", diff --git a/lib/src/index.js b/lib/src/index.js index dbea138ff..28cf64ebe 100644 --- a/lib/src/index.js +++ b/lib/src/index.js @@ -4,7 +4,7 @@ export { default as TimePicker } from './TimePicker'; export { default as DateTimePicker } from './DateTimePicker'; -export { default as MuiPickerUtilsProvider } from './utils/MuiPickersUtilsProvider'; +export { default as MuiPickersUtilsProvider } from './utils/MuiPickersUtilsProvider'; export { default as dateFnsUtils } from './utils/date-fns-utils'; diff --git a/lib/typings/utils.ts b/lib/typings/utils.ts index 4dcc6d788..92ff9a48f 100644 --- a/lib/typings/utils.ts +++ b/lib/typings/utils.ts @@ -1,9 +1,8 @@ import { MaterialUiPickersDate } from './date' -import { isEqual, isAfter, endOfDay, setHours } from 'date-fns'; export interface Utils { date(value: any): MaterialUiPickersDate; - addDays(value: MaterialUiPickersDate, count: Number): MaterialUiPickersDate; + addDays(value: MaterialUiPickersDate, count: number): MaterialUiPickersDate; isValid(value: MaterialUiPickersDate): boolean; isEqual(value: MaterialUiPickersDate, comparing: MaterialUiPickersDate): boolean; isNull(value: MaterialUiPickersDate): boolean; @@ -14,8 +13,8 @@ export interface Utils { isAfterYear(value: MaterialUiPickersDate, comparing: MaterialUiPickersDate): boolean; startOfDay(value: MaterialUiPickersDate): MaterialUiPickersDate; endOfDay(value: MaterialUiPickersDate): MaterialUiPickersDate; - format(value: MaterialUiPickersDate): string; - formatNumber(number: number): MaterialUiPickersDate + format(value: MaterialUiPickersDate, formatString: string): string; + formatNumber(number: number): string; getHours(value: MaterialUiPickersDate): number; setHours(value: MaterialUiPickersDate, count: number): MaterialUiPickersDate; getMinutes(value: MaterialUiPickersDate): number; From 36fa3e8299a42535853b4bfce932204b95851b38 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 26 Feb 2018 14:21:55 +0200 Subject: [PATCH 16/22] Add displaying texts methods to utils --- docs/src/App.js | 2 +- lib/src/DatePicker/Calendar.jsx | 2 +- lib/src/DatePicker/CalendarHeader.jsx | 2 +- lib/src/DatePicker/DatePicker.jsx | 4 +-- lib/src/DatePicker/YearSelection.jsx | 4 +-- .../DateTimePicker/DateTimePickerHeader.jsx | 8 ++--- lib/src/TimePicker/HourView.jsx | 2 -- lib/src/TimePicker/TimePicker.jsx | 4 +-- lib/src/_shared/PickerBase.jsx | 10 +------ lib/src/utils/date-fns-utils.js | 29 +++++++++++++++++++ lib/src/utils/moment-utils.js | 29 +++++++++++++++++++ lib/typings/utils.ts | 11 ++++++- 12 files changed, 82 insertions(+), 25 deletions(-) diff --git a/docs/src/App.js b/docs/src/App.js index 396f1052a..8ba7dc03d 100644 --- a/docs/src/App.js +++ b/docs/src/App.js @@ -56,7 +56,7 @@ export default class App extends Component {
- + - {utils.format(day, 'D')} + {utils.getDayText(day)} ); diff --git a/lib/src/DatePicker/CalendarHeader.jsx b/lib/src/DatePicker/CalendarHeader.jsx index e367b4cf1..f17e372a0 100644 --- a/lib/src/DatePicker/CalendarHeader.jsx +++ b/lib/src/DatePicker/CalendarHeader.jsx @@ -30,7 +30,7 @@ export const CalendarHeader = (props) => { - {utils.format(currentMonth, 'MMMM YYYY')} + {utils.getCalendarHeaderText(currentMonth)} diff --git a/lib/src/DatePicker/DatePicker.jsx b/lib/src/DatePicker/DatePicker.jsx index 3913f31fc..2f0870236 100644 --- a/lib/src/DatePicker/DatePicker.jsx +++ b/lib/src/DatePicker/DatePicker.jsx @@ -90,14 +90,14 @@ export class DatePicker extends PureComponent { variant="subheading" onClick={this.openYearSelection} selected={showYearSelection} - label={utils.format(this.date, 'YYYY')} + label={utils.getYearText(this.date)} /> diff --git a/lib/src/DatePicker/YearSelection.jsx b/lib/src/DatePicker/YearSelection.jsx index ff4f8a518..bd5737a17 100644 --- a/lib/src/DatePicker/YearSelection.jsx +++ b/lib/src/DatePicker/YearSelection.jsx @@ -73,14 +73,14 @@ export class YearSelection extends PureComponent { (disableFuture && utils.isAfterYear(year, utils.date())) )} value={yearNumber} - key={utils.format(year, 'YYYY')} + key={utils.getYearText(year)} onSelect={this.onYearSelect} ref={selected ? this.getSelectedYearRef : undefined } > - {utils.format(year, 'YYYY')} + {utils.getYearText(year)} ); }) diff --git a/lib/src/DateTimePicker/DateTimePickerHeader.jsx b/lib/src/DateTimePicker/DateTimePickerHeader.jsx index aea7b021e..38f9ede9d 100644 --- a/lib/src/DateTimePicker/DateTimePickerHeader.jsx +++ b/lib/src/DateTimePicker/DateTimePickerHeader.jsx @@ -26,14 +26,14 @@ export const DateTimePickerHeader = (props) => { variant="subheading" onClick={changeOpenView(viewType.YEAR)} selected={openView === viewType.YEAR} - label={utils.format(date, 'YYYY')} + label={utils.getYearText(date)} />
@@ -43,7 +43,7 @@ export const DateTimePickerHeader = (props) => { variant="display2" onClick={changeOpenView(viewType.HOUR)} selected={openView === viewType.HOUR} - label={utils.format(date, ampm ? 'hh' : 'HH')} + label={utils.getHourText(date, ampm)} /> { variant="display2" onClick={changeOpenView(viewType.MINUTES)} selected={openView === viewType.MINUTES} - label={utils.format(date, 'mm')} + label={utils.getMinuteText(date)} />
diff --git a/lib/src/TimePicker/HourView.jsx b/lib/src/TimePicker/HourView.jsx index 2d7a59d41..c280f7138 100644 --- a/lib/src/TimePicker/HourView.jsx +++ b/lib/src/TimePicker/HourView.jsx @@ -17,7 +17,6 @@ export class HourView extends PureComponent { ampm: true, } - getHourNumbers = () => { const { ampm, utils, date } = this.props; const currentHours = utils.getHours(date); @@ -38,7 +37,6 @@ export class HourView extends PureComponent { return currentHours === hour; }; - for (let hour = startHour; hour <= endHour; hour += 1) { let label = hour.toString(); diff --git a/lib/src/TimePicker/TimePicker.jsx b/lib/src/TimePicker/TimePicker.jsx index 06442480d..eb44b51de 100644 --- a/lib/src/TimePicker/TimePicker.jsx +++ b/lib/src/TimePicker/TimePicker.jsx @@ -93,7 +93,7 @@ export class TimePicker extends Component { variant="display3" onClick={this.openHourView} selected={isHourViewShown} - label={utils.format(date, ampm ? 'hh' : 'HH')} + label={utils.getHourText(date, ampm)} /> diff --git a/lib/src/_shared/PickerBase.jsx b/lib/src/_shared/PickerBase.jsx index a6ef041c4..86bf4ae4d 100644 --- a/lib/src/_shared/PickerBase.jsx +++ b/lib/src/_shared/PickerBase.jsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import DomainPropTypes from '../constants/prop-types'; /* eslint-disable react/sort-comp */ +/* eslint-disable react/require-default-props */ export default class PickerBase extends PureComponent { static propTypes = { value: DomainPropTypes.date, @@ -15,15 +16,6 @@ export default class PickerBase extends PureComponent { utils: PropTypes.func.isRequired, } - static defaultProps = { - value: new Date(), - autoOk: false, - returnMoment: false, - labelFunc: undefined, - format: undefined, - ampm: true, - } - getValidDateOrCurrent = () => { const { utils, value } = this.props; const date = utils.date(value); diff --git a/lib/src/utils/date-fns-utils.js b/lib/src/utils/date-fns-utils.js index 53b136f0e..7a74b0d20 100644 --- a/lib/src/utils/date-fns-utils.js +++ b/lib/src/utils/date-fns-utils.js @@ -139,4 +139,33 @@ export default class DateFnsUtils { static toNativeDate(date) { return date; } + + // displaying methpds + static getCalendarHeaderText(date) { + return format(date, 'MMMM YYYY'); + } + + static getYearText(date) { + return format(date, 'YYYY'); + } + + static getDatePickerHeaderText(date) { + return format(date, 'ddd, MMM D'); + } + + static getDateTimePickerHeaderText(date) { + return format(date, 'MMM D'); + } + + static getDayText(date) { + return format(date, 'D'); + } + + static getHourText(date, ampm) { + return format(date, ampm ? 'hh' : 'HH'); + } + + static getMinuteText(date) { + return format(date, 'mm'); + } } diff --git a/lib/src/utils/moment-utils.js b/lib/src/utils/moment-utils.js index 11d5869bb..d4f66449f 100644 --- a/lib/src/utils/moment-utils.js +++ b/lib/src/utils/moment-utils.js @@ -143,4 +143,33 @@ export default class MomentUtils { static toNativeDate(date) { return date.toDate(); } + + // displaying methods + static getCalendarHeaderText(date) { + return date.format('MMMM YYYY'); + } + + static getYearText(date) { + return date.format('YYYY'); + } + + static getDatePickerHeaderText(date) { + return date.format('ddd, MMM D'); + } + + static getDateTimePickerHeaderText(date) { + return date.format('MMM D'); + } + + static getDayText(date) { + return date.format('D'); + } + + static getHourText(date, ampm) { + return date.format(ampm ? 'hh' : 'HH'); + } + + static getMinuteText(date) { + return date.format('mm'); + } } diff --git a/lib/typings/utils.ts b/lib/typings/utils.ts index 92ff9a48f..217ac33fc 100644 --- a/lib/typings/utils.ts +++ b/lib/typings/utils.ts @@ -21,7 +21,6 @@ export interface Utils { setMinutes(value: MaterialUiPickersDate, count: number): MaterialUiPickersDate getMonth(value: MaterialUiPickersDate): number; isSameDay(value: MaterialUiPickersDate, comparing: MaterialUiPickersDate): boolean - getMeridiemText(ampm: boolean): string; getStartOfMonth(value: MaterialUiPickersDate): MaterialUiPickersDate; getNextMonth(value: MaterialUiPickersDate): MaterialUiPickersDate; getPreviousMonth(value: MaterialUiPickersDate): MaterialUiPickersDate; @@ -30,4 +29,14 @@ export interface Utils { getWeekDays(): string[]; getWeekArray(): MaterialUiPickersDate[]; getYearRange(): MaterialUiPickersDate[]; + + // displaying methods + getMeridiemText(ampm: boolean): string; + getCalendarHeaderText(date: any): string; + getDatePickerHeaderText(date: any): string; + getDateTimePickerHeaderText(date: any): string; + getDayText(date: any): string; + getHourText(date: any, ampm: boolean): string; + getMinuteText(date: any): string; + getYearText(date: any): string; } \ No newline at end of file From 4b18c46f088de2de6178476435fb49769621f86c Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 26 Feb 2018 14:35:46 +0200 Subject: [PATCH 17/22] Reimplement range countings for moment manually, remove moment-range dep --- lib/package-lock.json | 44 ----------------------------------- lib/package.json | 1 - lib/src/utils/moment-utils.js | 33 ++++++++++++++++---------- 3 files changed, 21 insertions(+), 57 deletions(-) diff --git a/lib/package-lock.json b/lib/package-lock.json index 6c9b50909..bf7c8e264 100644 --- a/lib/package-lock.json +++ b/lib/package-lock.json @@ -1958,14 +1958,6 @@ "array-find-index": "1.0.2" } }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "requires": { - "es5-ext": "0.10.37" - } - }, "damerau-levenshtein": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", @@ -2336,34 +2328,6 @@ "is-symbol": "1.0.1" } }, - "es5-ext": { - "version": "0.10.37", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", - "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37", - "es6-symbol": "3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37" - } - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -6414,14 +6378,6 @@ "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==", "dev": true }, - "moment-range": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/moment-range/-/moment-range-3.1.0.tgz", - "integrity": "sha1-lqsiRZObHAmR8OQSgHmEMhhBXCk=", - "requires": { - "es6-symbol": "3.1.1" - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", diff --git a/lib/package.json b/lib/package.json index 0252f658d..7acd29cbc 100644 --- a/lib/package.json +++ b/lib/package.json @@ -43,7 +43,6 @@ "date-fns": "^2.0.0-alpha.7" }, "dependencies": { - "moment-range": "^3.0.3", "react-text-mask": "^5.0.2" }, "scripts": { diff --git a/lib/src/utils/moment-utils.js b/lib/src/utils/moment-utils.js index d4f66449f..b4c1542d6 100644 --- a/lib/src/utils/moment-utils.js +++ b/lib/src/utils/moment-utils.js @@ -1,7 +1,4 @@ -import Moment from 'moment'; -import { extendMoment } from 'moment-range'; - -const moment = extendMoment(Moment); +import moment from 'moment'; export default class MomentUtils { static parse = moment @@ -124,20 +121,32 @@ export default class MomentUtils { const start = date.clone().startOf('month').startOf('week'); const end = date.clone().endOf('month').endOf('week'); - const weeks = Array.from(moment.range(start, end).by('week')); - const nestedWeeks = []; - - weeks.forEach((week) => { - const endOfWeek = week.clone().endOf('week'); - nestedWeeks.push(Array.from(moment.range(week, endOfWeek).by('day'))); - }); + let count = 0; + let current = start; + while (current.isBefore(end)) { + const weekNumber = Math.floor(count / 7); + nestedWeeks[weekNumber] = nestedWeeks[weekNumber] || []; + nestedWeeks[weekNumber].push(current); + current = current.clone().add(1, 'day'); + count += 1; + } return nestedWeeks; } static getYearRange(start, end) { - return Array.from(moment.range(start, end).by('year')); + const startDate = moment(start); + const endDate = moment(end); + const years = []; + + let current = startDate; + while (current.isBefore(endDate)) { + years.push(current); + current = current.clone().add(1, 'year'); + } + + return years; } static toNativeDate(date) { From d2dae09a35c88636dd8bb45ee0ffc6e2a246f970 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 26 Feb 2018 14:40:01 +0200 Subject: [PATCH 18/22] Change any date type to MaterialUIPickersDate --- lib/typings/utils.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/typings/utils.ts b/lib/typings/utils.ts index 217ac33fc..27daab0d9 100644 --- a/lib/typings/utils.ts +++ b/lib/typings/utils.ts @@ -32,11 +32,11 @@ export interface Utils { // displaying methods getMeridiemText(ampm: boolean): string; - getCalendarHeaderText(date: any): string; - getDatePickerHeaderText(date: any): string; - getDateTimePickerHeaderText(date: any): string; - getDayText(date: any): string; - getHourText(date: any, ampm: boolean): string; - getMinuteText(date: any): string; - getYearText(date: any): string; + getCalendarHeaderText(date: MaterialUiPickersDate): string; + getDatePickerHeaderText(date: MaterialUiPickersDate): string; + getDateTimePickerHeaderText(date: MaterialUiPickersDate): string; + getDayText(date: MaterialUiPickersDate): string; + getHourText(date: MaterialUiPickersDate, ampm: boolean): string; + getMinuteText(date: MaterialUiPickersDate): string; + getYearText(date: MaterialUiPickersDate): string; } \ No newline at end of file From d986820dcc5c4e596fd57b575a6144fb466282b6 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 26 Feb 2018 20:50:28 +0200 Subject: [PATCH 19/22] Update Readme.md to match new Utils architecture --- README.md | 67 ++++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 3d5173be2..8b8ef9c58 100644 --- a/README.md +++ b/README.md @@ -10,22 +10,35 @@ Changelog available [here](https://github.com/dmtrKovalenko/material-ui-pickers/releases) ### Installation -Available as npm package. Please note that we are using moment as a peer dependency +Available as npm package. ```sh -npm install moment material-ui-pickers -S +npm install material-ui-pickers -S ``` +Now choose the library that pickers will use to work with date. We are providing interfaces for [moment](https://momentjs.com/) and [date-fns](https://date-fns.org/). If you are not using moment in the project (or dont have it in the bundle already) we suggest using date-fns, because it much more lightweight and will be correctly tree-shaked from the bundle. -We are using material-ui-icons font to display icons. Just add this to your html +Teach pickers how to use one of that library using `MuiPickersUtilsProvider`. This component takes an utils property, and makes it available down the React tree thanks to React context. It should preferably be used at the root of your component tree. + +```jsx +import { MuiPickersUtilsProvider } from 'material-ui-pickers'; +import MomentUtils from 'material-ui-picker/utils/moment-utils'; +import DateFnsUtils from 'material-ui-picker/utils/date-fns-utils' + +function App() { + return ( + + + + ); +} + +render(, document.querySelector('#app')); +``` + +We are using material-ui-icons icon font to display icons. Just add this to your html ```html ``` - -If you dont want to use icon font, or you are already use `material-ui-icons` you can pass any icon to the components with the following props -* leftArrowIcon - arrow left for datepicker -* rightArrowIcon - arrow right for datepicker -* dateRangeIcon - date tab icon for datetimepicker -* timeIcon - time tab icon for datetimepicker -* keyboardIcon - icon for keyboard end adornmentic +If you dont want to use icon font, or you are already use `material-ui-icons` you can pass any icon to the components with [corresponding props](https://github.com/dmtrKovalenko/material-ui-pickers#props-documentation) ### Usage Here is a quick example of how to use this package @@ -83,7 +96,7 @@ Here is a list of available props **Note:** Any prop not recognized by the pickers and their sub-components are passed down to material-ui [TextField](https://material-ui-next.com/api/text-field/#props) component. #### Datepicker -* date - string, number, Date object, Moment object ([anything](https://momentjs.com/docs/#/parsing/), that can be parsed by moment) +* date - string, number, Date object or Moment object (if you are using moment utils) Prop | Type | Default | Definition ------------ | ------------- | ------------- | ------------- @@ -175,15 +188,6 @@ mask | text mask (read more [here](https://github.com/text-mask/text-mask/blob/m clearable | boolean | false | If `true`, clear button will be displayed TextFieldComponent | func, string | undefined | Component that should replace the default Material-UI TextField -### l10n -For l10n texts we're currently relying on moment which is stateful. To change the locale you have to import your langauge specific files an change the locale manually via `moment.locale(language)`. -``` -import moment from 'moment' -import 'moment/locale/fr'; - -moment.locale('fr') -``` - ### Jalali Calendar We are fully supporting Jalali calendar system and [right-to-left](https://material-ui-next.com/guides/right-to-left/) material-ui api. Special thanks to @alitaheri. Here is a little example of how to use it @@ -195,24 +199,17 @@ npm install material-ui-pickers-jalali-utils ``` ```jsx -import { TimePicker, DateTimePicker, DatePicker } from 'material-ui-pickers'; +import { MuiPickersUtilsProvider } from 'material-ui-pickers'; import jalaliUtils from 'material-ui-pickers-jalali-utils'; -jMoment.loadPersian({ dialect: 'persian-modern', usePersianDigits: true }); - - date === null ? '' : jMoment(date).format('jYYYY/jMM/jDD hh:mm A')} - value={selectedDate} - onChange={this.handleDateChange} - utils={jalaliUtils} -/> +function App() { + return ( + + + + ); +} ``` - -### Migrate to date-fns? -If you are interested of using moment or date-fns as the peer of this project, please mention that in [this issue](https://github.com/dmtrKovalenko/material-ui-pickers/issues/61), we need to know which library if more useful to be in the peer dependencies of this project. Thank you. - ### Contributing For information about how to contribute, see the [CONTRIBUTING](https://github.com/dmtrKovalenko/material-ui-pickers/blob/master/CONTRIBUTING.md) file. From 51d34ac77265c8c695bf580f19b8668284b04510 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 26 Feb 2018 21:00:59 +0200 Subject: [PATCH 20/22] Change moment type defenitions in proptypes table --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8b8ef9c58..d63a60c6d 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ Here is a list of available props Prop | Type | Default | Definition ------------ | ------------- | ------------- | ------------- value | date | new Date() | Datepicker value -format | string | 'MMMM Do' | Moment format string for input +format | string | 'MMMM Do' | Format string for input autoOk | boolean | false | Auto accept date on selection disablePast | boolean | false | Disable past dates disableFuture | boolean | false | Disable future dates @@ -110,7 +110,7 @@ openToYearSelection | boolean | false | Open datepicker from year selection minDate | date | '1900-01-01' | Minimum selectable date maxDate | date | '2100-01-01' | Maximum selectable date onChange | func | required | Callback firing when date accepted -returnMoment | boolean | true | Will return moment object in onChange +returnMoment | boolean | true | Will return moment object in onChange (if moment utils using) invalidLabel | string | 'Unknown' | Displayed string if date cant be parsed emptyLabel | string | '' | Displayed string if date is `null` (e.g. after clear) okLabel | string | 'OK' | The label for the ok button @@ -178,7 +178,7 @@ rightArrowIcon | react node | `keyboard_arrow_right`| Right arrow i dateRangeIcon | react node | `date_range`| Date tab icon timeIcon | react node | `access_time`| Time tab icon ampm | boolean | true | 12h/24h view for hour selection clock -shouldDisableDate | (date: Moment) => boolean | () => false | Allow to disable custom date in calendar +shouldDisableDate | (date: Moment | Date) => boolean | () => false | Allow to disable custom date in calendar keyboard | boolean | false | Allow to manual input date to the text field keyboardIcon | react node | `event` | Keyboard adornment icon maxDateMessage | string | 'Date should not be after maximal date' | Maximum date error message for keyboard input From 51be3bbf666f92ad96e25f775429af6c4865ca51 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 28 Feb 2018 14:00:46 +0200 Subject: [PATCH 21/22] Fix typo, comment persian pickers docs section --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d63a60c6d..ef6d3eaae 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Teach pickers how to use one of that library using `MuiPickersUtilsProvider`. Th ```jsx import { MuiPickersUtilsProvider } from 'material-ui-pickers'; -import MomentUtils from 'material-ui-picker/utils/moment-utils'; +import MomentUtils from 'material-ui-pickers/utils/moment-utils'; import DateFnsUtils from 'material-ui-picker/utils/date-fns-utils' function App() { @@ -188,6 +188,7 @@ mask | text mask (read more [here](https://github.com/text-mask/text-mask/blob/m clearable | boolean | false | If `true`, clear button will be displayed TextFieldComponent | func, string | undefined | Component that should replace the default Material-UI TextField + + ### Contributing For information about how to contribute, see the [CONTRIBUTING](https://github.com/dmtrKovalenko/material-ui-pickers/blob/master/CONTRIBUTING.md) file. From 0006018942a1f6fe6e2fd19627583fda51c0338d Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 28 Feb 2018 14:07:59 +0200 Subject: [PATCH 22/22] Remove returnMoment prop --- README.md | 3 --- lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx | 1 - .../DateTimePicker/DateTimePickerWrapper.usage.tsx | 2 +- lib/src/DatePicker/index.jsx | 4 ---- lib/src/DateTimePicker/index.jsx | 3 --- lib/src/TimePicker/index.jsx | 5 +---- lib/src/_shared/PickerBase.d.ts | 1 - lib/src/_shared/PickerBase.jsx | 7 +------ lib/src/utils/date-fns-utils.js | 4 ---- lib/src/utils/moment-utils.js | 4 ---- 10 files changed, 3 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index ef6d3eaae..32bec32d4 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,6 @@ openToYearSelection | boolean | false | Open datepicker from year selection minDate | date | '1900-01-01' | Minimum selectable date maxDate | date | '2100-01-01' | Maximum selectable date onChange | func | required | Callback firing when date accepted -returnMoment | boolean | true | Will return moment object in onChange (if moment utils using) invalidLabel | string | 'Unknown' | Displayed string if date cant be parsed emptyLabel | string | '' | Displayed string if date is `null` (e.g. after clear) okLabel | string | 'OK' | The label for the ok button @@ -136,7 +135,6 @@ value | date | new Date() | Timepicker value format | string | 'MMMM Do' | Moment format string for input autoOk | boolean | false | Auto accept time on selection onChange | func | required | Callback firing when date accepted -returnMoment | boolean | true | Will return moment object in onChange invalidLabel | string | 'Unknown' | Displayed string if date cant be parsed emptyLabel | string | '' | Displayed string if date is `null` (e.g. after clear) okLabel | string | 'OK' | The label for the ok button @@ -165,7 +163,6 @@ animateYearScrolling | boolean | false | Will animate year selection minDate | date | '1900-01-01' | Minimum selectable date maxDate | date | '2100-01-01' | Maximum selectable date onChange | func | required | Callback firing when date accepted -returnMoment | boolean | true | Will return moment object in onChangeg invalidLabel | string | 'Unknown' | Displayed string if date cant be parsed emptyLabel | string | '' | Displayed string if date is `null` (e.g. after clear) okLabel | string | 'OK' | The label for the ok button diff --git a/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx b/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx index 8dcf5ab68..a9dd6fcd6 100644 --- a/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx +++ b/lib/__tests__/DatePicker/DatePickerWrapper.usage.tsx @@ -104,7 +104,6 @@ class CustomElements extends Component<{classes: any}, {selectedDate: Date}> { onChange={this.handleDateChange} renderDay={this.renderWrappedDefaultDay} labelFunc={this.formatWeekSelectLabel} - returnMoment /> ); diff --git a/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx b/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx index 1002e2358..40a489e2b 100644 --- a/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx +++ b/lib/__tests__/DateTimePicker/DateTimePickerWrapper.usage.tsx @@ -94,7 +94,7 @@ class CustomElements extends Component<{classes: any}, {selectedDate: Date}> { value={selectedDate} onChange={this.handleDateChange} renderDay={this.renderCustomDayForDateTime} - returnMoment + /> ); diff --git a/lib/src/DatePicker/index.jsx b/lib/src/DatePicker/index.jsx index 2e245c959..50ac898af 100644 --- a/lib/src/DatePicker/index.jsx +++ b/lib/src/DatePicker/index.jsx @@ -29,8 +29,6 @@ export class DatePickerWrapper extends PickerBase { animateYearScrolling: PropTypes.bool, /* Open datepicker from year selection */ openToYearSelection: PropTypes.bool, - /* Return moment object in onChange event */ - returnMoment: PropTypes.bool, /* Displayed string if date can`t be parsed (or null) */ invalidLabel: PropTypes.string, /* Allow to specify dynamic label for text field labelFunc(date, invalidLabel) */ @@ -51,7 +49,6 @@ export class DatePickerWrapper extends PickerBase { value: new Date(), format: 'MMMM Do', autoOk: false, - returnMoment: true, minDate: undefined, maxDate: undefined, disablePast: undefined, @@ -75,7 +72,6 @@ export class DatePickerWrapper extends PickerBase { onChange, animateYearScrolling, openToYearSelection, - returnMoment, invalidLabel, leftArrowIcon, rightArrowIcon, diff --git a/lib/src/DateTimePicker/index.jsx b/lib/src/DateTimePicker/index.jsx index 770575416..41c665524 100644 --- a/lib/src/DateTimePicker/index.jsx +++ b/lib/src/DateTimePicker/index.jsx @@ -22,7 +22,6 @@ export class DateTimePickerWrapper extends PickerBase { minDate: DomainPropTypes.date, maxDate: DomainPropTypes.date, showTabs: PropTypes.bool, - returnMoment: PropTypes.bool, invalidLabel: PropTypes.string, leftArrowIcon: PropTypes.node, rightArrowIcon: PropTypes.node, @@ -46,7 +45,6 @@ export class DateTimePickerWrapper extends PickerBase { minDate: undefined, maxDate: undefined, showTabs: true, - returnMoment: true, invalidLabel: undefined, leftArrowIcon: undefined, rightArrowIcon: undefined, @@ -76,7 +74,6 @@ export class DateTimePickerWrapper extends PickerBase { autoSubmit, disablePast, disableFuture, - returnMoment, invalidLabel, leftArrowIcon, rightArrowIcon, diff --git a/lib/src/TimePicker/index.jsx b/lib/src/TimePicker/index.jsx index 919332855..0957cfbc4 100644 --- a/lib/src/TimePicker/index.jsx +++ b/lib/src/TimePicker/index.jsx @@ -17,7 +17,6 @@ export class TimePickerWrapper extends PickerBase { format: PropTypes.string, onChange: PropTypes.func.isRequired, autoOk: PropTypes.bool, - returnMoment: PropTypes.bool, invalidLabel: PropTypes.string, utils: PropTypes.func.isRequired, ampm: PropTypes.bool, @@ -27,7 +26,6 @@ export class TimePickerWrapper extends PickerBase { value: new Date(), format: undefined, autoOk: false, - returnMoment: true, invalidLabel: undefined, ampm: true, } @@ -38,8 +36,7 @@ export class TimePickerWrapper extends PickerBase { render() { const { date } = this.state; const { - value, format, autoOk, onChange, returnMoment, invalidLabel, - utils, ampm, ...other + value, format, autoOk, onChange, invalidLabel, utils, ampm, ...other } = this.props; return ( diff --git a/lib/src/_shared/PickerBase.d.ts b/lib/src/_shared/PickerBase.d.ts index 83cce0615..05944a47c 100644 --- a/lib/src/_shared/PickerBase.d.ts +++ b/lib/src/_shared/PickerBase.d.ts @@ -4,6 +4,5 @@ import { DateTextFieldProps } from './ModalDialog'; export interface PickerBaseProps { onChange: (date: Date | Moment) => void; autoOk?: boolean; - returnMoment?: boolean; ampm?: boolean; } \ No newline at end of file diff --git a/lib/src/_shared/PickerBase.jsx b/lib/src/_shared/PickerBase.jsx index 86bf4ae4d..08160acac 100644 --- a/lib/src/_shared/PickerBase.jsx +++ b/lib/src/_shared/PickerBase.jsx @@ -9,7 +9,6 @@ export default class PickerBase extends PureComponent { value: DomainPropTypes.date, onChange: PropTypes.func.isRequired, autoOk: PropTypes.bool, - returnMoment: PropTypes.bool, format: PropTypes.string, labelFunc: PropTypes.func, ampm: PropTypes.bool, @@ -50,11 +49,7 @@ export default class PickerBase extends PureComponent { } handleAccept = () => { - const dateToReturn = this.props.returnMoment - ? this.state.date - : this.props.utils.toNativeDate(this.state.date); - - this.props.onChange(dateToReturn); + this.props.onChange(this.state.date); } handleDismiss = () => { diff --git a/lib/src/utils/date-fns-utils.js b/lib/src/utils/date-fns-utils.js index 7a74b0d20..5b6512d06 100644 --- a/lib/src/utils/date-fns-utils.js +++ b/lib/src/utils/date-fns-utils.js @@ -136,10 +136,6 @@ export default class DateFnsUtils { return years; } - static toNativeDate(date) { - return date; - } - // displaying methpds static getCalendarHeaderText(date) { return format(date, 'MMMM YYYY'); diff --git a/lib/src/utils/moment-utils.js b/lib/src/utils/moment-utils.js index b4c1542d6..a499e3ea0 100644 --- a/lib/src/utils/moment-utils.js +++ b/lib/src/utils/moment-utils.js @@ -149,10 +149,6 @@ export default class MomentUtils { return years; } - static toNativeDate(date) { - return date.toDate(); - } - // displaying methods static getCalendarHeaderText(date) { return date.format('MMMM YYYY');