diff --git a/src/inputs/BaseInput.tsx b/src/inputs/BaseInput.tsx index 2984a97c..a6fb2ed8 100644 --- a/src/inputs/BaseInput.tsx +++ b/src/inputs/BaseInput.tsx @@ -8,6 +8,7 @@ import { import { TimeFormat, } from '../pickers/BasePicker'; +import moment = require('moment'); export interface BaseInputProps { [key: string]: any; @@ -132,6 +133,7 @@ abstract class BaseInput<P extends BaseInputProps, S extends BaseInputState> extends React.Component<P, S> { public static defaultProps = { inline: false, + localization: moment.locale(), }; private calendarNode: HTMLElement; diff --git a/src/inputs/DateInput.tsx b/src/inputs/DateInput.tsx index a3414f15..72a10cff 100644 --- a/src/inputs/DateInput.tsx +++ b/src/inputs/DateInput.tsx @@ -28,9 +28,7 @@ import { tick, } from '../lib'; import { - chooseValue, - dateValueToString, - getInitializer, + buildValue, parseArrayOrValue, parseValue, } from './parse'; @@ -98,10 +96,10 @@ class DateInput extends BaseInput<DateInputProps, DateInputState> { * - handle underlying picker change */ public static readonly defaultProps = { + ...BaseInput.defaultProps, dateFormat: 'DD-MM-YYYY', startMode: 'day', preserveViewMode: true, - inline: false, icon: 'calendar', }; @@ -182,7 +180,7 @@ class DateInput extends BaseInput<DateInputProps, DateInputState> { constructor(props: DateInputProps) { super(props); - const parsedValue = parseValue(props.value, props.dateFormat); + const parsedValue = parseValue(props.value, props.dateFormat, props.localization); this.state = { mode: props.startMode, popupIsClosed: true, @@ -270,15 +268,14 @@ class DateInput extends BaseInput<DateInputProps, DateInputState> { pickerStyle, onChange: this.handleSelect, onHeaderClick: this.switchToPrevMode, - initializeWith: getInitializer({ initialDate, dateFormat, dateParams: this.getDateParams(), localization }), - value: parseValue(chooseValue(value, initialDate), dateFormat), - enable: parseArrayOrValue(enable, dateFormat), - minDate: parseValue(minDate, dateFormat), - maxDate: parseValue(maxDate, dateFormat), + value: buildValue(value, initialDate, localization, dateFormat), + enable: parseArrayOrValue(enable, dateFormat, localization), + minDate: parseValue(minDate, dateFormat, localization), + maxDate: parseValue(maxDate, dateFormat, localization), localization, }; - const disableParsed = parseArrayOrValue(disable, dateFormat); - const markedParsed = parseArrayOrValue(marked, dateFormat); + const disableParsed = parseArrayOrValue(disable, dateFormat, localization); + const markedParsed = parseArrayOrValue(marked, dateFormat, localization); const { mode } = this.state; if (mode === 'year') { return ( diff --git a/src/inputs/DateTimeInput.tsx b/src/inputs/DateTimeInput.tsx index eb00c079..6b83e743 100644 --- a/src/inputs/DateTimeInput.tsx +++ b/src/inputs/DateTimeInput.tsx @@ -30,10 +30,10 @@ import BaseInput, { import { tick } from '../lib'; import { chooseValue, - getInitializer, parseArrayOrValue, parseValue, TIME_FORMAT, + buildValue, } from './parse'; import { getDisabledMonths, @@ -116,13 +116,13 @@ class DateTimeInput extends BaseInput<DateTimeInputProps, DateTimeInputState> { * - handle underlying picker change */ public static readonly defaultProps = { + ...BaseInput.defaultProps, dateFormat: 'DD-MM-YYYY', timeFormat: '24', startMode: 'day', divider: ' ', icon: 'calendar', preserveViewMode: true, - inline: false, }; public static readonly propTypes = { @@ -199,7 +199,7 @@ class DateTimeInput extends BaseInput<DateTimeInputProps, DateTimeInputState> { constructor(props: DateTimeInputProps) { super(props); - const parsedValue = parseValue(props.value, props.dateFormat); + const parsedValue = parseValue(props.value, props.dateFormat, props.localization); this.state = { mode: props.startMode, year: parsedValue ? parsedValue.year() : undefined, @@ -307,20 +307,14 @@ class DateTimeInput extends BaseInput<DateTimeInputProps, DateTimeInputState> { closePopup: this.closePopup, onChange: this.handleSelect, onHeaderClick: this.switchToPrevMode, - initializeWith: getInitializer({ - initialDate, - dateFormat: dateTimeFormat, - dateParams: this.getDateParams(), - localization, - }), - value: parseValue(chooseValue(value, initialDate), dateTimeFormat), - minDate: parseValue(minDate, dateFormat), - maxDate: parseValue(maxDate, dateFormat), - marked: parseArrayOrValue(marked, dateFormat), + value: buildValue(value, initialDate, localization, dateFormat), + minDate: parseValue(minDate, dateFormat, localization), + maxDate: parseValue(maxDate, dateFormat, localization), + marked: parseArrayOrValue(marked, dateFormat, localization), markColor, localization, }; - const disableParsed = parseArrayOrValue(disable, dateFormat); + const disableParsed = parseArrayOrValue(disable, dateFormat, localization); const { mode } = this.state; if (mode === 'year') { return ( diff --git a/src/inputs/DatesRangeInput.tsx b/src/inputs/DatesRangeInput.tsx index f22b9f4f..c431e399 100644 --- a/src/inputs/DatesRangeInput.tsx +++ b/src/inputs/DatesRangeInput.tsx @@ -10,6 +10,7 @@ import { parseDatesRange, parseValue, parseArrayOrValue, + buildValue, } from './parse'; import DatesRangePicker, { @@ -44,9 +45,9 @@ class DatesRangeInput extends BaseInput<DatesRangeInputProps, BaseInputState> { * string 'start - end') */ public static readonly defaultProps = { + ...BaseInput.defaultProps, dateFormat: 'DD-MM-YYYY', icon: 'calendar', - inline: false, }; public static readonly propTypes = { @@ -154,7 +155,7 @@ class DatesRangeInput extends BaseInput<DatesRangeInputProps, BaseInputState> { start, end, } = parseDatesRange(value, dateFormat); - const markedParsed = parseArrayOrValue(marked, dateFormat); + const markedParsed = parseArrayOrValue(marked, dateFormat, localization); return ( <DatesRangePicker @@ -165,13 +166,13 @@ class DatesRangeInput extends BaseInput<DatesRangeInputProps, BaseInputState> { closePopup={this.closePopup} onChange={this.handleSelect} dateFormat={dateFormat} - initializeWith={getInitializer({ initialDate, dateFormat, localization })} + initializeWith={buildValue(start, initialDate, localization, dateFormat)} start={start} end={end} marked={markedParsed} markColor={markColor} - minDate={parseValue(minDate, dateFormat)} - maxDate={parseValue(maxDate, dateFormat)} + minDate={parseValue(minDate, dateFormat, localization)} + maxDate={parseValue(maxDate, dateFormat, localization)} localization={localization} onHeaderClick={() => undefined} tabIndex={tabIndex} diff --git a/src/inputs/MonthInput.tsx b/src/inputs/MonthInput.tsx index 281d21de..11dcc537 100644 --- a/src/inputs/MonthInput.tsx +++ b/src/inputs/MonthInput.tsx @@ -16,9 +16,9 @@ import BaseInput, { MinMaxValueProps, } from './BaseInput'; import { - getInitializer, parseArrayOrValue, parseValue, + buildValue, } from './parse'; export type MonthInputProps = @@ -33,9 +33,9 @@ export interface MonthInputOnChangeData extends MonthInputProps { class MonthInput extends BaseInput<MonthInputProps, BaseInputState> { public static readonly defaultProps = { + ...BaseInput.defaultProps, dateFormat: 'MMM', icon: 'calendar', - inline: false, }; public static readonly propTypes = { @@ -130,11 +130,11 @@ class MonthInput extends BaseInput<MonthInputProps, BaseInputState> { const { value, dateFormat, - initialDate, disable, maxDate, minDate, localization, + initialDate, } = this.props; return ( @@ -146,11 +146,10 @@ class MonthInput extends BaseInput<MonthInputProps, BaseInputState> { closePopup={this.closePopup} hasHeader={false} onChange={this.handleSelect} - initializeWith={getInitializer({ initialDate, dateFormat, localization })} - value={parseValue(value, dateFormat)} - disable={parseArrayOrValue(disable, dateFormat)} - maxDate={parseValue(maxDate, dateFormat)} - minDate={parseValue(minDate, dateFormat)} + value={buildValue(value, initialDate, localization, dateFormat)} + disable={parseArrayOrValue(disable, dateFormat, localization)} + maxDate={parseValue(maxDate, dateFormat, localization)} + minDate={parseValue(minDate, dateFormat, localization)} localization={localization} onHeaderClick={() => undefined} /> diff --git a/src/inputs/MonthRangeInput.tsx b/src/inputs/MonthRangeInput.tsx index c87eebb3..d90509e1 100644 --- a/src/inputs/MonthRangeInput.tsx +++ b/src/inputs/MonthRangeInput.tsx @@ -9,10 +9,11 @@ import MonthRangePicker, {MonthRangePickerOnChangeData} from '../pickers/monthPi import InputView from '../views/InputView'; import {MonthInputProps} from './MonthInput'; import { - getInitializer, parseDatesRange, parseValue, + buildValue, } from './parse'; +import moment = require('moment'); const DATES_SEPARATOR = ' - '; @@ -28,9 +29,9 @@ export interface MonthRangeInputOnChangeData extends MonthInputProps { class MonthRangeInput extends BaseInput<MonthRangeInputProps, BaseInputState> { public static readonly defaultProps = { + ...BaseInput.defaultProps, dateFormat: 'MM-YYYY', icon: 'calendar', - inline: false, }; public static readonly propTypes = { @@ -134,11 +135,11 @@ class MonthRangeInput extends BaseInput<MonthRangeInputProps, BaseInputState> { closePopup={this.closePopup} onChange={this.handleSelect} dateFormat={dateFormat} - initializeWith={getInitializer({initialDate, dateFormat, localization})} + initializeWith={buildValue(start, initialDate, localization, dateFormat)} start={start} end={end} - minDate={parseValue(minDate, dateFormat)} - maxDate={parseValue(maxDate, dateFormat)} + minDate={parseValue(minDate, dateFormat, localization)} + maxDate={parseValue(maxDate, dateFormat, localization)} localization={localization} onHeaderClick={() => undefined} /> diff --git a/src/inputs/TimeInput.tsx b/src/inputs/TimeInput.tsx index 0c8e537b..05b307fa 100644 --- a/src/inputs/TimeInput.tsx +++ b/src/inputs/TimeInput.tsx @@ -22,6 +22,7 @@ import { getInitializer, parseValue, TIME_FORMAT, + buildValue, } from './parse'; function getNextMode(currentMode) { @@ -55,10 +56,10 @@ class TimeInput extends BaseInput<TimeInputProps, TimeInputState> { * - handle HourPicker/MinutePicker change (format { hour: number, minute: number } into output time string) */ public static readonly defaultProps = { + ...BaseInput.defaultProps, icon: 'time', timeFormat: '24', disableMinute: false, - inline: false, }; public static readonly propTypes = { @@ -168,7 +169,7 @@ class TimeInput extends BaseInput<TimeInputProps, TimeInputState> { pickerStyle, pickerWidth, } = this.props; - const currentValue = parseValue(value, TIME_FORMAT[timeFormat]); + const currentValue = parseValue(value, TIME_FORMAT[timeFormat], localization); const pickerProps = { inline, onCalendarViewMount: this.onCalendarViewMount, @@ -179,7 +180,7 @@ class TimeInput extends BaseInput<TimeInputProps, TimeInputState> { pickerStyle, onHeaderClick: () => undefined, closePopup: this.closePopup, - initializeWith: getInitializer({ initialDate: currentValue, dateFormat: TIME_FORMAT[timeFormat], localization }), + initializeWith: buildValue(currentValue, null, localization, TIME_FORMAT[timeFormat]), value: currentValue, onChange: this.handleSelect, timeFormat, diff --git a/src/inputs/YearInput.tsx b/src/inputs/YearInput.tsx index b5988594..2ac2b74a 100644 --- a/src/inputs/YearInput.tsx +++ b/src/inputs/YearInput.tsx @@ -15,9 +15,9 @@ import BaseInput, { MinMaxValueProps, } from './BaseInput'; import { - getInitializer, parseArrayOrValue, parseValue, + buildValue, } from './parse'; export type YearInputProps = @@ -32,8 +32,8 @@ export interface YearInputOnChangeData extends YearInputProps { class YearInput extends BaseInput<YearInputProps, BaseInputState> { public static readonly defaultProps = { + ...BaseInput.defaultProps, dateFormat: 'YYYY', - inline: false, icon: 'calendar', }; @@ -133,12 +133,6 @@ class YearInput extends BaseInput<YearInputProps, BaseInputState> { dateFormat, localization, } = this.props; - const initializeWith = getInitializer({ - dateParams: { year: parseInt(value, 10) }, - initialDate, - dateFormat, - localization, - }); return ( <YearPicker @@ -148,11 +142,10 @@ class YearInput extends BaseInput<YearInputProps, BaseInputState> { onCalendarViewMount={this.onCalendarViewMount} closePopup={this.closePopup} onChange={this.handleSelect} - initializeWith={initializeWith} - value={parseValue(value, dateFormat)} - disable={parseArrayOrValue(disable, dateFormat)} - maxDate={parseValue(maxDate, dateFormat)} - minDate={parseValue(minDate, dateFormat)} + value={buildValue(value, initialDate, localization, dateFormat)} + disable={parseArrayOrValue(disable, dateFormat, localization)} + maxDate={parseValue(maxDate, dateFormat, localization)} + minDate={parseValue(minDate, dateFormat, localization)} onHeaderClick={() => undefined} /> ); diff --git a/src/inputs/parse.ts b/src/inputs/parse.ts index 38e9653f..e8e69f9d 100644 --- a/src/inputs/parse.ts +++ b/src/inputs/parse.ts @@ -3,7 +3,7 @@ import isArray from 'lodash/isArray'; import isString from 'lodash/isString'; import compact from 'lodash/compact'; -import moment from 'moment'; +import moment, { Moment } from 'moment'; export const TIME_FORMAT = { 24: 'HH:mm', @@ -20,10 +20,12 @@ type ParseValueData = * * Return unedfined on invalid input. */ -export function parseValue(value: ParseValueData, dateFormat: string): moment.Moment { +export function parseValue(value: ParseValueData, dateFormat: string, localization: string): moment.Moment { if (!isNil(value) && !isNil(dateFormat)) { const date = moment(value, dateFormat); if (date.isValid()) { + date.locale(localization); + return date; } } @@ -38,14 +40,14 @@ type ParseArrayOrValueData = * Return array of moments. Returned value contains only valid moments. * Return undefined if none of the input values are valid. */ -export function parseArrayOrValue(data: ParseArrayOrValueData, dateFormat: string) { +export function parseArrayOrValue(data: ParseArrayOrValueData, dateFormat: string, localization: string) { if (isArray(data)) { - const parsed = compact((data as ParseValueData[]).map((item) => parseValue(item, dateFormat))); + const parsed = compact((data as ParseValueData[]).map((item) => parseValue(item, dateFormat, localization))); if (parsed.length > 0) { return parsed; } } - const parsedValue = parseValue((data as ParseValueData), dateFormat); + const parsedValue = parseValue((data as ParseValueData), dateFormat, localization); return parsedValue && [parsedValue]; } @@ -83,7 +85,7 @@ export function getInitializer(context: GetInitializerParams): moment.Moment { return parsedParams; } } - const parsedInitialDate = parseValue(initialDate, dateFormat); + const parsedInitialDate = parseValue(initialDate, dateFormat, localization); if (parsedInitialDate) { return parsedInitialDate; } @@ -104,6 +106,27 @@ export function chooseValue(value: string, return value; } +/** Creates moment instance from provided value or initialDate. + * Creates today by default. + */ +export function buildValue(value: ParseValueData, + initialDate: InitialDate, + localization: string, + dateFormat: string): Moment { + const valueParsed = parseValue(value, dateFormat, localization); + if (valueParsed) { + return valueParsed; + } + const initialDateParsed = parseValue(initialDate, dateFormat, localization); + if (initialDateParsed) { + return initialDateParsed; + } + const defaultVal = moment(); + defaultVal.locale(localization); + + return defaultVal; +} + export function dateValueToString(value: DateValue, dateFormat: string): string { if (isString(value)) { return value; diff --git a/src/pickers/BasePicker.tsx b/src/pickers/BasePicker.tsx index abaf815e..3838726d 100644 --- a/src/pickers/BasePicker.tsx +++ b/src/pickers/BasePicker.tsx @@ -41,7 +41,7 @@ export interface BasePickerProps { /** Currently selected date. */ value?: Moment; /** A value for initializing day picker's state. */ - initializeWith: Moment; + initializeWith?: Moment; /** Forse popup to close. */ closePopup: () => void; /** Whether to display picker without a popup or inside a popup. */ @@ -111,7 +111,7 @@ abstract class BasePicker<P extends BasePickerProps> extends React.Component<P, super(props); this.state = { hoveredCellPosition: undefined, - date: props.initializeWith.clone(), + date: props.value ? this.props.value.clone() : this.props.initializeWith.clone(), }; } diff --git a/src/pickers/monthPicker/MonthRangePicker.tsx b/src/pickers/monthPicker/MonthRangePicker.tsx index 4d471429..1290eeef 100644 --- a/src/pickers/monthPicker/MonthRangePicker.tsx +++ b/src/pickers/monthPicker/MonthRangePicker.tsx @@ -50,7 +50,6 @@ class MonthRangePicker public render() { const { onChange, - value, initializeWith, closePopup, inline, diff --git a/test/pickers/testMonthPicker.js b/test/pickers/testMonthPicker.js index b651009a..f05b7f2b 100644 --- a/test/pickers/testMonthPicker.js +++ b/test/pickers/testMonthPicker.js @@ -41,13 +41,6 @@ describe('<MonthPicker />: getActiveCellPosition', () => { assert.equal(wrapper.instance().getActiveCellPosition(), 1, 'return index 1 (means February)'); }); - it('return undefined if year of `value` does not equal to year of `date`', () => { - const wrapper = mount(<MonthPicker - value={moment('2020-02-18')} - initializeWith={date} />); - assert(_.isUndefined(wrapper.instance().getActiveCellPosition()), 'return undefined'); - }); - it('return undefined `value` is not provided', () => { const wrapper = mount(<MonthPicker initializeWith={date} />); diff --git a/test/pickers/testMonthRangePicker.js b/test/pickers/testMonthRangePicker.js index fd649706..839e15a3 100644 --- a/test/pickers/testMonthRangePicker.js +++ b/test/pickers/testMonthRangePicker.js @@ -44,7 +44,6 @@ describe('<MonthRangePicker />: getActiveCellPosition', () => { /* current year 2015 */ it('return index of start month', () => { const wrapper = mount(<MonthRangePicker - value='03-2015 - ' start={moment({year: '2015', month: '03'})} initializeWith={date} />); const rangeIndexes = wrapper.instance().getActiveCellsPositions(); @@ -55,7 +54,6 @@ describe('<MonthRangePicker />: getActiveCellPosition', () => { it('return undefined if year of `value` does not equal to year of `date`', () => { const wrapper = mount(<MonthRangePicker - value='02-2020 - ' start={moment({year: '2020', month: '02'})} initializeWith={date} />); const rangeIndexes = wrapper.instance().getActiveCellsPositions(); @@ -65,7 +63,6 @@ describe('<MonthRangePicker />: getActiveCellPosition', () => { it('return indexes of start and end month', () => { const wrapper = mount(<MonthRangePicker - value={'03-2015 - 07-2015'} start={moment({year: '2015', month: '03'})} end={moment({year: '2015', month: '07'})} initializeWith={date} />); @@ -321,7 +318,6 @@ describe('<MonthRangePicker />: handleChange', () => { const onChangeFake = sinon.fake(); const wrapper = mount(<MonthRangePicker onChange={onChangeFake} - value='03-2015 - ' start={moment({year: '2015', month: '03'})} initializeWith={date} />);