react-datetime-picker
Advanced tools
Comparing version 1.0.1 to 1.2.0
@@ -43,2 +43,6 @@ 'use strict'; | ||
var _Divider = require('./Divider'); | ||
var _Divider2 = _interopRequireDefault(_Divider); | ||
var _NativeInput = require('./DateTimeInput/NativeInput'); | ||
@@ -52,4 +56,2 @@ | ||
var _locales = require('./shared/locales'); | ||
var _propTypes3 = require('./shared/propTypes'); | ||
@@ -68,2 +70,3 @@ | ||
var allViews = ['hour', 'minute', 'second']; | ||
var className = 'react-datetime-picker__button__input'; | ||
@@ -124,2 +127,5 @@ var datesAreDifferent = function datesAreDifferent(date1, date2) { | ||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = DateTimeInput.__proto__ || Object.getPrototypeOf(DateTimeInput)).call.apply(_ref, [this].concat(args))), _this), _this.state = { | ||
year: null, | ||
month: null, | ||
day: null, | ||
hour: null, | ||
@@ -153,3 +159,8 @@ minute: null, | ||
}, _this.onChange = function (event) { | ||
_this.setState(_defineProperty({}, event.target.name, parseInt(event.target.value, 10)), _this.onChangeExternal); | ||
var _event$target = event.target, | ||
name = _event$target.name, | ||
value = _event$target.value; | ||
_this.setState(_defineProperty({}, name, value ? parseInt(value, 10) : null), _this.onChangeExternal); | ||
}, _this.onChangeNative = function (event) { | ||
@@ -185,3 +196,2 @@ var value = event.target.value; | ||
value: function componentWillMount() { | ||
(0, _locales.setLocale)(this.props.locale); | ||
this.updateValues(); | ||
@@ -192,3 +202,2 @@ } | ||
value: function componentWillReceiveProps(nextProps) { | ||
var props = this.props; | ||
var nextValue = nextProps.value; | ||
@@ -198,9 +207,5 @@ var value = this.props.value; | ||
if (nextProps.locale !== props.locale) { | ||
(0, _locales.setLocale)(nextProps.locale); | ||
} | ||
if ( | ||
// Toggling clock visibility resets values | ||
nextProps.isCalendarOpen !== props.isCalendarOpen || datesAreDifferent(nextValue, value)) { | ||
nextProps.isWidgetOpen !== this.props.isWidgetOpen || datesAreDifferent(nextValue, value)) { | ||
this.updateValues(nextProps); | ||
@@ -251,4 +256,6 @@ } | ||
key: 'day', | ||
className: className, | ||
maxDetail: this.props.maxDetail, | ||
month: this.state.month, | ||
showLeadingZeros: this.props.showLeadingZeros, | ||
year: this.state.year, | ||
@@ -263,4 +270,6 @@ value: this.state.day | ||
key: 'month', | ||
className: className, | ||
maxDetail: this.props.maxDetail, | ||
minDate: this.props.minDate, | ||
showLeadingZeros: this.props.showLeadingZeros, | ||
value: this.state.month | ||
@@ -274,2 +283,3 @@ }, this.commonInputProps)); | ||
key: 'year', | ||
className: className, | ||
value: this.state.year, | ||
@@ -284,2 +294,3 @@ valueType: 'day' | ||
key: 'hour', | ||
className: className, | ||
value: this.state.hour | ||
@@ -301,2 +312,3 @@ }, this.commonInputProps)); | ||
key: 'minute', | ||
className: className, | ||
maxDetail: this.props.maxDetail, | ||
@@ -319,2 +331,3 @@ value: this.state.minute | ||
key: 'second', | ||
className: className, | ||
maxDetail: this.props.maxDetail, | ||
@@ -330,3 +343,2 @@ value: this.state.second | ||
var dateDivider = this.dateDivider, | ||
dateDividerElement = this.dateDividerElement, | ||
datePlaceholder = this.datePlaceholder; | ||
@@ -350,4 +362,9 @@ | ||
if (index + 1 < array.length) { | ||
result.push( | ||
// eslint-disable-next-line react/no-array-index-key | ||
result.push(_react2.default.cloneElement(dateDividerElement, { key: 'separator_' + index })); | ||
_react2.default.createElement( | ||
_Divider2.default, | ||
{ key: 'separator_' + index }, | ||
dateDivider | ||
)); | ||
} | ||
@@ -364,3 +381,2 @@ | ||
var timeDivider = this.timeDivider, | ||
timeDividerElement = this.timeDividerElement, | ||
timePlaceholder = this.timePlaceholder; | ||
@@ -388,4 +404,9 @@ | ||
if (index + 1 < array.length) { | ||
result.push( | ||
// eslint-disable-next-line react/no-array-index-key | ||
result.push(_react2.default.cloneElement(timeDividerElement, { key: 'separator_' + index })); | ||
_react2.default.createElement( | ||
_Divider2.default, | ||
{ key: 'separator_' + index }, | ||
timeDivider | ||
)); | ||
} | ||
@@ -401,2 +422,3 @@ | ||
key: 'time', | ||
disabled: this.props.disabled, | ||
maxDate: this.props.maxDate, | ||
@@ -416,6 +438,10 @@ minDate: this.props.minDate, | ||
'div', | ||
{ className: 'react-datetime-picker__button__input' }, | ||
{ className: className }, | ||
this.renderNativeInput(), | ||
this.renderCustomDateInputs(), | ||
this.dividerElement, | ||
_react2.default.createElement( | ||
_Divider2.default, | ||
null, | ||
'\xA0' | ||
), | ||
this.renderCustomTimeInputs() | ||
@@ -437,15 +463,8 @@ ); | ||
get: function get() { | ||
var locale = this.props.locale; | ||
var date = new Date(2017, 11, 11); | ||
return removeUnwantedCharacters((0, _dateFormatter.formatDate)(date)).match(/[^0-9]/)[0]; | ||
return removeUnwantedCharacters((0, _dateFormatter.formatDate)(date, locale)).match(/[^0-9]/)[0]; | ||
} | ||
}, { | ||
key: 'dateDividerElement', | ||
get: function get() { | ||
return _react2.default.createElement( | ||
'span', | ||
{ className: 'react-datetime-picker__button__input__divider' }, | ||
this.dateDivider | ||
); | ||
} | ||
@@ -457,15 +476,8 @@ // eslint-disable-next-line class-methods-use-this | ||
get: function get() { | ||
var locale = this.props.locale; | ||
var date = new Date(2017, 0, 1, 21, 12, 13); | ||
return removeUnwantedCharacters((0, _dateFormatter.formatTime)(date)).match(/[^0-9]/)[0]; | ||
return removeUnwantedCharacters((0, _dateFormatter.formatTime)(date, locale)).match(/[^0-9]/)[0]; | ||
} | ||
}, { | ||
key: 'timeDividerElement', | ||
get: function get() { | ||
return _react2.default.createElement( | ||
'span', | ||
{ className: 'react-datetime-picker__button__input__divider' }, | ||
this.timeDivider | ||
); | ||
} | ||
@@ -475,19 +487,9 @@ // eslint-disable-next-line class-methods-use-this | ||
}, { | ||
key: 'dividerElement', | ||
key: 'datePlaceholder', | ||
get: function get() { | ||
return _react2.default.createElement( | ||
'span', | ||
{ className: 'react-datetime-picker__button__input__divider' }, | ||
' ' | ||
); | ||
} | ||
var locale = this.props.locale; | ||
// eslint-disable-next-line class-methods-use-this | ||
}, { | ||
key: 'datePlaceholder', | ||
get: function get() { | ||
var date = new Date(2017, 11, 11); | ||
return removeUnwantedCharacters((0, _dateFormatter.formatDate)(date)).replace('2017', 'year').replace('12', 'month').replace('11', 'day'); | ||
return removeUnwantedCharacters((0, _dateFormatter.formatDate)(date, locale)).replace('2017', 'year').replace('12', 'month').replace('11', 'day'); | ||
} | ||
@@ -500,5 +502,7 @@ | ||
get: function get() { | ||
var locale = this.props.locale; | ||
var date = new Date(2017, 0, 1, 21, 13, 14); | ||
return removeUnwantedCharacters((0, _dateFormatter.formatTime)(date)).replace('21', 'hour-24').replace('9', 'hour-12').replace('13', 'minute').replace('14', 'second').replace(/AM|PM/, this.timeDivider + 'ampm'); | ||
return removeUnwantedCharacters((0, _dateFormatter.formatTime)(date, locale)).replace('21', 'hour-24').replace('9', 'hour-12').replace('13', 'minute').replace('14', 'second').replace(/AM|PM/, this.timeDivider + 'ampm'); | ||
} | ||
@@ -511,2 +515,3 @@ }, { | ||
return { | ||
disabled: this.props.disabled, | ||
maxDate: this.props.maxDate, | ||
@@ -518,3 +523,3 @@ minDate: this.props.minDate, | ||
// This is only for showing validity when editing | ||
required: this.props.required || this.props.isCalendarOpen, | ||
required: this.props.required || this.props.isWidgetOpen, | ||
itemRef: function itemRef(ref) { | ||
@@ -542,6 +547,7 @@ if (!ref) return; | ||
DateTimeInput.propTypes = { | ||
isCalendarOpen: _propTypes2.default.bool, | ||
disabled: _propTypes2.default.bool, | ||
isWidgetOpen: _propTypes2.default.bool, | ||
locale: _propTypes2.default.string, | ||
maxDate: _propTypes3.isMaxDate, | ||
maxDetail: _propTypes2.default.oneOf(allViews), | ||
maxDate: _propTypes3.isMaxDate, | ||
minDate: _propTypes3.isMinDate, | ||
@@ -551,3 +557,4 @@ name: _propTypes2.default.string, | ||
required: _propTypes2.default.bool, | ||
showLeadingZeros: _propTypes2.default.bool, | ||
value: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.instanceOf(Date)]) | ||
}; |
@@ -54,2 +54,3 @@ 'use strict'; | ||
var _props = this.props, | ||
disabled = _props.disabled, | ||
maxDate = _props.maxDate, | ||
@@ -65,2 +66,3 @@ minDate = _props.minDate, | ||
type: 'datetime-local', | ||
disabled: disabled, | ||
max: maxDate ? nativeValueParser(maxDate) : null, | ||
@@ -90,2 +92,3 @@ min: minDate ? nativeValueParser(minDate) : null, | ||
NativeInput.propTypes = { | ||
disabled: _propTypes2.default.bool, | ||
maxDate: _propTypes3.isMaxDate, | ||
@@ -92,0 +95,0 @@ minDate: _propTypes3.isMinDate, |
@@ -53,4 +53,4 @@ 'use strict'; | ||
var DateTimePicker = function (_Component) { | ||
_inherits(DateTimePicker, _Component); | ||
var DateTimePicker = function (_PureComponent) { | ||
_inherits(DateTimePicker, _PureComponent); | ||
@@ -85,6 +85,2 @@ function DateTimePicker() { | ||
}); | ||
}, _this.toggleClock = function () { | ||
_this.setState(function (prevState) { | ||
return { isClockOpen: !prevState.isClockOpen }; | ||
}); | ||
}, _this.openCalendar = function () { | ||
@@ -101,2 +97,19 @@ _this.setState({ | ||
}); | ||
}, _this.onDateChange = function (value) { | ||
var closeWidgets = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; | ||
var prevValue = _this.props.value; | ||
if (prevValue) { | ||
var valueWithHour = new Date(value); | ||
valueWithHour.setHours(prevValue.getHours(), prevValue.getMinutes(), prevValue.getSeconds(), prevValue.getMilliseconds()); | ||
_this.onChange(valueWithHour, closeWidgets); | ||
} else { | ||
_this.onChange(value, closeWidgets); | ||
} | ||
}, _this.onTimeChange = function (value) { | ||
var closeWidgets = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; | ||
_this.onChange(value, closeWidgets); | ||
}, _this.onChange = function (value) { | ||
@@ -165,13 +178,6 @@ var closeWidgets = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; | ||
value: function renderInputs() { | ||
var _props = this.props, | ||
clearIcon = _props.clearIcon, | ||
calendarIcon = _props.calendarIcon, | ||
locale = _props.locale, | ||
maxDetail = _props.maxDetail, | ||
maxDate = _props.maxDate, | ||
minDate = _props.minDate, | ||
name = _props.name, | ||
required = _props.required, | ||
value = _props.value; | ||
var isCalendarOpen = this.state.isCalendarOpen; | ||
var disabled = this.props.disabled; | ||
var _state = this.state, | ||
isCalendarOpen = _state.isCalendarOpen, | ||
isClockOpen = _state.isClockOpen; | ||
@@ -183,12 +189,14 @@ | ||
_react2.default.createElement(_DateTimeInput2.default, { | ||
locale: locale, | ||
isCalendarOpen: isCalendarOpen, | ||
maxDetail: maxDetail, | ||
maxDate: maxDate, | ||
minDate: minDate, | ||
name: name, | ||
onChange: this.onChange, | ||
disabled: disabled, | ||
locale: this.props.locale, | ||
isWidgetOpen: isCalendarOpen || isClockOpen, | ||
maxDetail: this.props.maxDetail, | ||
maxDate: this.props.maxDate, | ||
minDate: this.props.minDate, | ||
name: this.props.name, | ||
onChange: this.onTimeChange, | ||
placeholder: this.placeholder, | ||
required: required, | ||
value: value | ||
required: this.props.required, | ||
showLeadingZeros: this.props.showLeadingZeros, | ||
value: this.props.value | ||
}), | ||
@@ -199,2 +207,3 @@ _react2.default.createElement( | ||
className: 'react-datetime-picker__clear-button react-datetime-picker__button__icon', | ||
disabled: disabled, | ||
onClick: this.clear, | ||
@@ -204,3 +213,3 @@ onFocus: this.stopPropagation, | ||
}, | ||
clearIcon | ||
this.props.clearIcon | ||
), | ||
@@ -211,2 +220,3 @@ _react2.default.createElement( | ||
className: 'react-datetime-picker__calendar-button react-datetime-picker__button__icon', | ||
disabled: disabled, | ||
onClick: this.toggleCalendar, | ||
@@ -217,3 +227,3 @@ onFocus: this.stopPropagation, | ||
}, | ||
calendarIcon | ||
this.props.calendarIcon | ||
) | ||
@@ -232,8 +242,9 @@ ); | ||
var _props2 = this.props, | ||
calendarClassName = _props2.calendarClassName, | ||
dateTimePickerMaxDetail = _props2.maxDetail, | ||
dateTimePickerClassName = _props2.className, | ||
onChange = _props2.onChange, | ||
calendarProps = _objectWithoutProperties(_props2, ['calendarClassName', 'maxDetail', 'className', 'onChange']); | ||
var _props = this.props, | ||
calendarClassName = _props.calendarClassName, | ||
dateTimePickerMaxDetail = _props.maxDetail, | ||
dateTimePickerClassName = _props.className, | ||
onChange = _props.onChange, | ||
value = _props.value, | ||
calendarProps = _objectWithoutProperties(_props, ['calendarClassName', 'maxDetail', 'className', 'onChange', 'value']); | ||
@@ -262,3 +273,4 @@ var className = 'react-datetime-picker__calendar'; | ||
className: calendarClassName, | ||
onChange: this.onChange | ||
onChange: this.onDateChange, | ||
value: value || null | ||
}, calendarProps)) | ||
@@ -277,8 +289,8 @@ ); | ||
var _props3 = this.props, | ||
clockClassName = _props3.clockClassName, | ||
timePickerClassName = _props3.className, | ||
maxDetail = _props3.maxDetail, | ||
onChange = _props3.onChange, | ||
clockProps = _objectWithoutProperties(_props3, ['clockClassName', 'className', 'maxDetail', 'onChange']); | ||
var _props2 = this.props, | ||
clockClassName = _props2.clockClassName, | ||
timePickerClassName = _props2.className, | ||
maxDetail = _props2.maxDetail, | ||
onChange = _props2.onChange, | ||
clockProps = _objectWithoutProperties(_props2, ['clockClassName', 'className', 'maxDetail', 'onChange']); | ||
@@ -324,3 +336,3 @@ var className = 'react-datetime-picker__clock'; | ||
{ | ||
className: (0, _mergeClassNames2.default)(className, className + '--' + (this.state.isCalendarOpen || this.state.isClockOpen ? 'open' : 'closed'), this.props.className), | ||
className: (0, _mergeClassNames2.default)(className, className + '--' + (this.state.isCalendarOpen || this.state.isClockOpen ? 'open' : 'closed'), className + '--' + (this.props.disabled ? 'disabled' : 'enabled'), this.props.className), | ||
onFocus: this.onFocus, | ||
@@ -339,3 +351,3 @@ ref: function ref(_ref4) { | ||
return DateTimePicker; | ||
}(_react.Component); | ||
}(_react.PureComponent); | ||
@@ -376,3 +388,3 @@ exports.default = DateTimePicker; | ||
DateTimePicker.propTypes = { | ||
DateTimePicker.propTypes = _extends({}, _entry2.default.propTypes, _entry4.default.propTypes, { | ||
calendarClassName: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.arrayOf(_propTypes2.default.string)]), | ||
@@ -383,2 +395,3 @@ clockClassName: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.arrayOf(_propTypes2.default.string)]), | ||
clearIcon: _propTypes2.default.node, | ||
disabled: _propTypes2.default.bool, | ||
isCalendarOpen: _propTypes2.default.bool, | ||
@@ -393,3 +406,4 @@ isClockOpen: _propTypes2.default.bool, | ||
required: _propTypes2.default.bool, | ||
showLeadingZeros: _propTypes2.default.bool, | ||
value: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.instanceOf(Date)]) | ||
}; | ||
}); |
@@ -16,27 +16,31 @@ 'use strict'; | ||
*/ | ||
var getFormatter = function getFormatter(options) { | ||
var locales = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : (0, _locales.getLocale)(); | ||
var getFormatter = function getFormatter(options, locale) { | ||
if (!locale) { | ||
// Default parameter is not enough as it does not protect us from null values | ||
// eslint-disable-next-line no-param-reassign | ||
locale = (0, _locales.getDefaultLocale)(); | ||
} | ||
var stringifiedOptions = JSON.stringify(options); | ||
if (!formatterCache[locales]) { | ||
formatterCache[locales] = {}; | ||
if (!formatterCache[locale]) { | ||
formatterCache[locale] = {}; | ||
} | ||
if (!formatterCache[locales][stringifiedOptions]) { | ||
formatterCache[locales][stringifiedOptions] = new Intl.DateTimeFormat(locales, options).format; | ||
if (!formatterCache[locale][stringifiedOptions]) { | ||
formatterCache[locale][stringifiedOptions] = new Intl.DateTimeFormat(locale, options).format; | ||
} | ||
return formatterCache[locales][stringifiedOptions]; | ||
return formatterCache[locale][stringifiedOptions]; | ||
}; | ||
var formatDate = exports.formatDate = function formatDate(date) { | ||
return getFormatter({ day: 'numeric', month: 'numeric', year: 'numeric' })(date); | ||
var formatDate = exports.formatDate = function formatDate(date, locale) { | ||
return getFormatter({ day: 'numeric', month: 'numeric', year: 'numeric' }, locale)(date); | ||
}; | ||
var formatTime = exports.formatTime = function formatTime(date) { | ||
return getFormatter({ hour: 'numeric', minute: 'numeric', second: 'numeric' })(date); | ||
var formatTime = exports.formatTime = function formatTime(date, locale) { | ||
return getFormatter({ hour: 'numeric', minute: 'numeric', second: 'numeric' }, locale)(date); | ||
}; | ||
var formatDateTime = exports.formatDateTime = function formatDateTime(date) { | ||
var formatDateTime = exports.formatDateTime = function formatDateTime(date, locale) { | ||
return getFormatter({ | ||
@@ -49,3 +53,3 @@ day: 'numeric', | ||
second: 'numeric' | ||
})(date); | ||
}, locale)(date); | ||
}; |
@@ -60,3 +60,3 @@ 'use strict'; | ||
if (Number.isNaN(date.getTime())) { | ||
if (isNaN(date.getTime())) { | ||
throw new Error('Invalid date: ' + value); | ||
@@ -63,0 +63,0 @@ } |
@@ -6,38 +6,10 @@ 'use strict'; | ||
}); | ||
exports.setLocale = exports.getLocale = exports.getDefaultLocale = exports.getDefaultLocales = undefined; | ||
var _lodash = require('lodash.once'); | ||
var _locales = require('react-date-picker/dist/shared/locales'); | ||
var _lodash2 = _interopRequireDefault(_lodash); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
var userLocale = null; | ||
var getDefaultLocales = exports.getDefaultLocales = (0, _lodash2.default)(function () { | ||
var languageList = []; | ||
if (window.navigator.languages) { | ||
languageList.push.apply(languageList, _toConsumableArray(window.navigator.languages)); | ||
} else if (window.navigator.userLanguage) { | ||
languageList.push(window.navigator.userLanguage); | ||
Object.defineProperty(exports, 'getDefaultLocale', { | ||
enumerable: true, | ||
get: function get() { | ||
return _locales.getDefaultLocale; | ||
} | ||
languageList.push('en-GB'); // Fallback | ||
return languageList; | ||
}); | ||
var getDefaultLocale = exports.getDefaultLocale = (0, _lodash2.default)(function () { | ||
return getDefaultLocales()[0]; | ||
}); | ||
var getLocale = exports.getLocale = function getLocale() { | ||
return userLocale || getDefaultLocale(); | ||
}; | ||
var setLocale = exports.setLocale = function setLocale(locale) { | ||
userLocale = locale; | ||
}; | ||
}); |
@@ -7,35 +7,21 @@ 'use strict'; | ||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
var _utils = require('react-date-picker/dist/shared/utils'); | ||
var min = exports.min = function min() { | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
Object.defineProperty(exports, 'min', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.min; | ||
} | ||
return Math.min.apply(Math, _toConsumableArray(args.filter(function (a) { | ||
return typeof a === 'number'; | ||
}))); | ||
}; | ||
var max = exports.max = function max() { | ||
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
}); | ||
Object.defineProperty(exports, 'max', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.max; | ||
} | ||
return Math.max.apply(Math, _toConsumableArray(args.filter(function (a) { | ||
return typeof a === 'number'; | ||
}))); | ||
}; | ||
var updateInputWidth = exports.updateInputWidth = function updateInputWidth(element) { | ||
var span = document.createElement('span'); | ||
span.innerHTML = element.value || element.placeholder; | ||
var container = element.parentElement; | ||
container.appendChild(span); | ||
var width = span.getBoundingClientRect().width + 4; | ||
element.style.width = width + 'px'; | ||
container.removeChild(span); | ||
}; | ||
}); | ||
Object.defineProperty(exports, 'updateInputWidth', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.updateInputWidth; | ||
} | ||
}); |
{ | ||
"name": "react-datetime-picker", | ||
"version": "1.0.1", | ||
"description": "An input component for picking date and time for your React application.", | ||
"version": "1.2.0", | ||
"description": "A date range picker for your React app.", | ||
"main": "dist/entry.js", | ||
@@ -13,10 +13,6 @@ "es6": "src/entry.js", | ||
"prepublishOnly": "npm run build", | ||
"preversion": "npm run version-sample && npm run version-test", | ||
"test": "npm run test-eslint && npm run test-jest", | ||
"test-eslint": "eslint ./src", | ||
"test-jest": "jest", | ||
"test-jest-coverage": "jest --coverage", | ||
"version": "npm run build && git add .", | ||
"version-sample": "cd sample && npm version patch", | ||
"version-test": "cd test && npm version patch" | ||
"test-jest-coverage": "jest --coverage" | ||
}, | ||
@@ -53,7 +49,7 @@ "jest": { | ||
"react": ">=15.5", | ||
"react-calendar": "^2.9.0", | ||
"react-calendar": "^2.13.0", | ||
"react-clock": "^2.2.0", | ||
"react-date-picker": "^6.6.1", | ||
"react-date-picker": "^6.9.0", | ||
"react-dom": ">=15.5", | ||
"react-time-picker": "^2.1.2" | ||
"react-time-picker": "^2.3.0" | ||
}, | ||
@@ -63,3 +59,4 @@ "devDependencies": { | ||
"babel-core": "^6.26.0", | ||
"babel-eslint": "^8.0.3", | ||
"babel-eslint": "^8.2.1", | ||
"babel-jest": "^22.1.0", | ||
"babel-plugin-transform-class-properties": "^6.24.1", | ||
@@ -70,12 +67,12 @@ "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", | ||
"babel-preset-stage-2": "^6.24.1", | ||
"enzyme": "^3.2.0", | ||
"enzyme-adapter-react-16": "^1.1.0", | ||
"eslint": "^4.13.1", | ||
"enzyme": "^3.3.0", | ||
"enzyme-adapter-react-16": "^1.1.1", | ||
"eslint": "^4.17.0", | ||
"eslint-config-airbnb": "^16.1.0", | ||
"eslint-plugin-class-property": "^1.0.6", | ||
"eslint-plugin-class-property": "^1.1.0", | ||
"eslint-plugin-import": "^2.8.0", | ||
"eslint-plugin-jsx-a11y": "^6.0.3", | ||
"eslint-plugin-react": "^7.5.1", | ||
"jest": "^22.0.4", | ||
"jest-cli": "^22.0.4", | ||
"eslint-plugin-react": "^7.6.1", | ||
"jest": "^22.1.4", | ||
"jest-cli": "^22.1.4", | ||
"less": "^2.7.3", | ||
@@ -82,0 +79,0 @@ "react-test-renderer": "^16.2.0" |
@@ -6,4 +6,8 @@ ![downloads](https://img.shields.io/npm/dt/react-datetime-picker.svg) ![build](https://img.shields.io/travis/wojtekmaj/react-datetime-picker.svg) ![dependencies](https://img.shields.io/david/wojtekmaj/react-datetime-picker.svg | ||
# React-DateTime-Picker | ||
An input component for picking date and time for your React application. | ||
A datetime picker for your React app. | ||
* Supports virtually any language | ||
* No moment.js needed | ||
## tl;dr | ||
@@ -28,15 +32,11 @@ * Install by executing `npm install react-datetime-picker` or `yarn add react-datetime-picker`. | ||
[React-Calendar](https://github.com/wojtekmaj/react-calendar), on which React-DateTime-Picker relies heavily, uses modern web technologies. That's why it's so fast, lightweight and easy to style. This, however, comes at a cost of supporting only modern browsers. | ||
Your project needs to use React 16 or later. If you use older version of React, please refer to the table below to find suitable React-DateTime-Picker version. | ||
|Browser|Minimum supported version| | ||
|React version|Newest supported React-DateTime-Picker| | ||
|----|----| | ||
|Google Chrome|24| | ||
|Mozilla Firefox|29| | ||
|Microsoft Edge|12| | ||
|Apple Safari|10| | ||
|Apple Safari (iOS)|10.2| | ||
|Opera|15| | ||
|Internet Explorer|11| | ||
|Samsung Internet|4| | ||
|>16.0|latest| | ||
|>15.0|1.0.1| | ||
[React-Calendar](https://github.com/wojtekmaj/react-calendar), on which React-DateTime-Picker relies heavily, uses modern web technologies. That's why it's so fast, lightweight and easy to style. This, however, comes at a cost of [supporting only modern browsers](https://caniuse.com/#feat=internationalization). | ||
#### Legacy browsers | ||
@@ -95,30 +95,26 @@ | ||
|calendarIcon|Defines the content of the calendar button.|<ul><li>String: `"Calendar"`</li><li>React element: `<CalendarIcon />`</li></ul>| | ||
|calendarType|Defines which type of calendar should be used. Can be "US" or "ISO 8601". Defaults to "US" for "en-US" locale, "ISO 8601" to all the others.|`"ISO 8601"`| | ||
|className|Defines class name(s) that will be added along with "react-datetime-picker" to the main React-DateTime-Picker `<div>` element.|<ul><li>String: `"class1 class2"`</li><li>Array of strings: `["class1", "class2 class3"]`</li></ul>| | ||
|clearIcon|Defines the content of the clear button.|<ul><li>String: `"Clear"`</li><li>React element: `<ClearIcon />`</li></ul>| | ||
|disabled|Defines whether the date picker should be disabled. Defaults to false.|`true`| | ||
|isCalendarOpen|Defines whether the calendar should be opened. Defaults to false.|`true`| | ||
|isClockOpen|Defines whether the clock should be opened. Defaults to false.|`true`| | ||
|locale|Defines which locale should be used by the calendar. Can be any [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag). Defaults to user's browser settings.|`"hu-HU"`| | ||
|maxDate|Defines maximum date that the user can select. Periods partially overlapped by maxDate will also be selectable, although react-datetime-picker will ensure that no later date is selected.|Date: `new Date()`| | ||
|maxDetail|Defines how detailed time picking shall be. Can be "hour", "minute" or "second". Defaults to "minute".|`"second"`| | ||
|minDate|Defines minimum date that the user can select. Periods partially overlapped by minDate will also be selectable, although react-datetime-picker will ensure that no earlier date is selected.|Date: `new Date()`| | ||
|minDetail|Defines the least detailed view that the user shall see. Can be "month", "year", "decade" or "century". Defaults to "century".|`"century"`| | ||
|nextLabel|Defines the content of the "next" button on the navigation pane. Defaults to "›".|<ul><li>String: `"›"`</li><li>React element: `<NextIcon />`</li></ul>| | ||
|next2Label|Defines the content of the "next on higher level" button on the navigation pane. Defaults to "»". |<ul><li>String: `"»"`</li><li>React element: `<DoubleNextIcon />`</li></ul>| | ||
|locale|Defines which locale should be used by the datetime picker and the calendar. Can be any [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag). Defaults to user's browser settings.|`"hu-HU"`| | ||
|maxDate|Defines maximum date that the user can select. Periods partially overlapped by maxDate will also be selectable, although React-DateTime-Picker will ensure that no later date is selected.|Date: `new Date()`| | ||
|maxDetail|Defines the most detailed calendar view that the user shall see. View defined here also becomes the one on which clicking an item in the calendar will select a date and pass it to onChange. Can be "month", "year", "decade" or "century". Defaults to "month".|`"month"`| | ||
|minDate|Defines minimum date that the user can select. Periods partially overlapped by minDate will also be selectable, although React-DateTime-Picker will ensure that no earlier date is selected.|Date: `new Date()`| | ||
|minDetail|Defines the least detailed calendar view that the user shall see. Can be "month", "year", "decade" or "century". Defaults to "century".|`"century"`| | ||
|name|Defines input name. Defaults to "datetime".|`"myCustomName"`| | ||
|onChange|Function called when the user clicks an item on the most detailed view available.|`(value) => alert('New date is: ', value)`| | ||
|onClickDay|Function called when the user clicks a day on a calendar.|`(value) => alert('Clicked day: ', value)`| | ||
|onClickDecade|Function called when the user clicks a decade on a calendar.|`(value) => alert('Clicked decade: ', value)`| | ||
|onClickMonth|Function called when the user clicks a month on a calendar.|`(value) => alert('Clicked month: ', value)`| | ||
|onClickYear|Function called when the user clicks a year on a calendar.|`(value) => alert('Clicked year: ', value)`| | ||
|prevLabel|Defines the content of the "previous" button on the navigation pane. Defaults to "‹".|<ul><li>String: `"‹"`</li><li>React element: `<PreviousIcon />`</li></ul>| | ||
|prev2Label|Defines the content of the "previous on higher level" button on the navigation pane. Defaults to "«".|<ul><li>String: `"«"`</li><li>React element: `<DoublePreviousIcon />`</li></ul>| | ||
|returnValue|Defines which dates shall be passed by the calendar to the onChange function and onClick{Period} functions. Can be "start", "end" or "range". The latter will cause an array with start and end values to be passed. Defaults to "start".|`"range"`| | ||
|required|Defines whether date input should be required. Defaults to false.|`true`| | ||
|showNeighboringMonth|Defines whether days from previous or next month shall be rendered if the month doesn't start on the first day of the week or doesn't end on the last day of the week, respectively. Defaults to true.|`false`| | ||
|tileClassName|Defines class name(s) that will be applied to a given calendar item (day on month view, month on year view and so on).|<ul><li>String: `"class1 class2"`</li><li>Array of strings: `["class1", "class2 class3"]`</li><li>Function: `({ date, view }) => view === 'month' && date.getDay() === 3 ? 'wednesday' : null`</li></ul>| | ||
|tileContent|Allows to render custom content within a given calendar item (day on month view, month on year view and so on).|<ul><li>String: `"Sample"`</li><li>React element: `<TileContent />`</li><li>Function: `({ date, view }) => view === 'month' && date.getDay() === 0 ? <p>It's Sunday!</p> : null`</li></ul>| | ||
|showWeekNumbers|Defines whether week numbers shall be shown at the left of MonthView or not. Defaults to false.|`true`| | ||
|value|Defines the value of the input.|<ul><li>Date: `new Date()`</li><li>An array of dates: `[new Date(2017, 0, 1), new Date(2017, 7, 1)]`</li></ul>| | ||
|view|Determines which calendar view shall be opened initially. Does not disable navigation. Can be "month", "year", "decade" or "century". Defaults to the most detailed view allowed.|`"year"`| | ||
### Calendar | ||
DateTimePicker component passes all props to React-Calendar, with the exception of `className` (you can use `calendarClassName` for that instead). There are tons of customizations you can do! For more information, see [Calendar component props](https://github.com/wojtekmaj/react-calendar#props). | ||
### Clock | ||
DateTimePicker component passes all props to React-Clock, with the exception of `className` (you can use `clockClassName` for that instead). There are tons of customizations you can do! For more information, see [Clock component props](https://github.com/wojtekmaj/react-clock#props). | ||
## License | ||
@@ -125,0 +121,0 @@ |
@@ -134,3 +134,3 @@ import React from 'react'; | ||
expect(separators.at(0).text()).toBe('/'); | ||
expect(separators.at(2).text()).toBe(' '); | ||
expect(separators.at(2).text()).toBe('\u00a0'); // Non-breaking space | ||
expect(separators.at(3).text()).toBe(':'); | ||
@@ -137,0 +137,0 @@ }); |
@@ -8,2 +8,18 @@ import React from 'react'; | ||
const mockDocumentListeners = () => { | ||
const eventMap = {}; | ||
document.addEventListener = jest.fn((method, cb) => { | ||
if (!eventMap[method]) { | ||
eventMap[method] = []; | ||
} | ||
eventMap[method].push(cb); | ||
}); | ||
return { | ||
simulate: (method, args) => { | ||
eventMap[method].forEach(cb => cb(args)); | ||
}, | ||
}; | ||
}; | ||
describe('DateTimePicker', () => { | ||
@@ -84,3 +100,3 @@ it('applies className to its wrapper when given a string', () => { | ||
it('renders DateInput and Calendar component when given isOpen flag', () => { | ||
it('renders DateInput and Calendar components when given isCalendarOpen flag', () => { | ||
const component = mount( | ||
@@ -97,3 +113,3 @@ <DateTimePicker isCalendarOpen /> | ||
it('renders DateInput and Clock component when given isOpen flag', () => { | ||
it('renders DateInput and Clock components when given isClockOpen flag', () => { | ||
const component = mount( | ||
@@ -197,2 +213,34 @@ <DateTimePicker isClockOpen /> | ||
}); | ||
it('closes Calendar and Clock component when clicked outside', () => { | ||
const { simulate } = mockDocumentListeners(); | ||
const component = mount( | ||
<DateTimePicker isCalendarOpen isClockOpen /> | ||
); | ||
simulate('mousedown', { | ||
target: document, | ||
}); | ||
component.update(); | ||
expect(component.state('isCalendarOpen')).toBe(false); | ||
expect(component.state('isClockOpen')).toBe(false); | ||
}); | ||
it('does not close Calendar and Clock component when clicked inside', () => { | ||
const { simulate } = mockDocumentListeners(); | ||
const component = mount( | ||
<DateTimePicker isCalendarOpen isClockOpen /> | ||
); | ||
simulate('mousedown', { | ||
target: component.getDOMNode(), | ||
}); | ||
component.update(); | ||
expect(component.state('isCalendarOpen')).toBe(true); | ||
expect(component.state('isClockOpen')).toBe(true); | ||
}); | ||
}); |
@@ -10,2 +10,3 @@ import React, { Component } from 'react'; | ||
import SecondInput from 'react-time-picker/dist/TimeInput/SecondInput'; | ||
import Divider from './Divider'; | ||
import NativeInput from './DateTimeInput/NativeInput'; | ||
@@ -22,6 +23,6 @@ | ||
} from './shared/dates'; | ||
import { setLocale } from './shared/locales'; | ||
import { isMaxDate, isMinDate } from './shared/propTypes'; | ||
const allViews = ['hour', 'minute', 'second']; | ||
const className = 'react-datetime-picker__button__input'; | ||
@@ -70,2 +71,5 @@ const datesAreDifferent = (date1, date2) => ( | ||
state = { | ||
year: null, | ||
month: null, | ||
day: null, | ||
hour: null, | ||
@@ -77,3 +81,2 @@ minute: null, | ||
componentWillMount() { | ||
setLocale(this.props.locale); | ||
this.updateValues(); | ||
@@ -83,13 +86,8 @@ } | ||
componentWillReceiveProps(nextProps) { | ||
const { props } = this; | ||
const { value: nextValue } = nextProps; | ||
const { value } = this.props; | ||
if (nextProps.locale !== props.locale) { | ||
setLocale(nextProps.locale); | ||
} | ||
if ( | ||
// Toggling clock visibility resets values | ||
(nextProps.isCalendarOpen !== props.isCalendarOpen) || | ||
(nextProps.isWidgetOpen !== this.props.isWidgetOpen) || | ||
datesAreDifferent(nextValue, value) | ||
@@ -111,6 +109,7 @@ ) { | ||
get dateDivider() { | ||
const { locale } = this.props; | ||
const date = new Date(2017, 11, 11); | ||
return ( | ||
removeUnwantedCharacters(formatDate(date)) | ||
removeUnwantedCharacters(formatDate(date, locale)) | ||
.match(/[^0-9]/)[0] | ||
@@ -120,16 +119,9 @@ ); | ||
get dateDividerElement() { | ||
return ( | ||
<span className="react-datetime-picker__button__input__divider"> | ||
{this.dateDivider} | ||
</span> | ||
); | ||
} | ||
// eslint-disable-next-line class-methods-use-this | ||
get timeDivider() { | ||
const { locale } = this.props; | ||
const date = new Date(2017, 0, 1, 21, 12, 13); | ||
return ( | ||
removeUnwantedCharacters(formatTime(date)) | ||
removeUnwantedCharacters(formatTime(date, locale)) | ||
.match(/[^0-9]/)[0] | ||
@@ -139,25 +131,9 @@ ); | ||
get timeDividerElement() { | ||
return ( | ||
<span className="react-datetime-picker__button__input__divider"> | ||
{this.timeDivider} | ||
</span> | ||
); | ||
} | ||
// eslint-disable-next-line class-methods-use-this | ||
get dividerElement() { | ||
return ( | ||
<span className="react-datetime-picker__button__input__divider"> | ||
{' '} | ||
</span> | ||
); | ||
} | ||
// eslint-disable-next-line class-methods-use-this | ||
get datePlaceholder() { | ||
const { locale } = this.props; | ||
const date = new Date(2017, 11, 11); | ||
return ( | ||
removeUnwantedCharacters(formatDate(date)) | ||
removeUnwantedCharacters(formatDate(date, locale)) | ||
.replace('2017', 'year') | ||
@@ -171,6 +147,7 @@ .replace('12', 'month') | ||
get timePlaceholder() { | ||
const { locale } = this.props; | ||
const date = new Date(2017, 0, 1, 21, 13, 14); | ||
return ( | ||
removeUnwantedCharacters(formatTime(date)) | ||
removeUnwantedCharacters(formatTime(date, locale)) | ||
.replace('21', 'hour-24') | ||
@@ -186,2 +163,3 @@ .replace('9', 'hour-12') | ||
return { | ||
disabled: this.props.disabled, | ||
maxDate: this.props.maxDate, | ||
@@ -193,3 +171,3 @@ minDate: this.props.minDate, | ||
// This is only for showing validity when editing | ||
required: this.props.required || this.props.isCalendarOpen, | ||
required: this.props.required || this.props.isWidgetOpen, | ||
itemRef: (ref) => { | ||
@@ -245,4 +223,6 @@ if (!ref) return; | ||
onChange = (event) => { | ||
const { name, value } = event.target; | ||
this.setState( | ||
{ [event.target.name]: parseInt(event.target.value, 10) }, | ||
{ [name]: value ? parseInt(value, 10) : null }, | ||
this.onChangeExternal, | ||
@@ -303,4 +283,6 @@ ); | ||
key="day" | ||
className={className} | ||
maxDetail={this.props.maxDetail} | ||
month={this.state.month} | ||
showLeadingZeros={this.props.showLeadingZeros} | ||
year={this.state.year} | ||
@@ -317,4 +299,6 @@ value={this.state.day} | ||
key="month" | ||
className={className} | ||
maxDetail={this.props.maxDetail} | ||
minDate={this.props.minDate} | ||
showLeadingZeros={this.props.showLeadingZeros} | ||
value={this.state.month} | ||
@@ -330,2 +314,3 @@ {...this.commonInputProps} | ||
key="year" | ||
className={className} | ||
value={this.state.year} | ||
@@ -342,2 +327,3 @@ valueType="day" | ||
key="hour" | ||
className={className} | ||
value={this.state.hour} | ||
@@ -360,2 +346,3 @@ {...this.commonInputProps} | ||
key="minute" | ||
className={className} | ||
maxDetail={this.props.maxDetail} | ||
@@ -379,2 +366,3 @@ value={this.state.minute} | ||
key="second" | ||
className={className} | ||
maxDetail={this.props.maxDetail} | ||
@@ -388,3 +376,3 @@ value={this.state.second} | ||
renderCustomDateInputs() { | ||
const { dateDivider, dateDividerElement, datePlaceholder } = this; | ||
const { dateDivider, datePlaceholder } = this; | ||
@@ -407,4 +395,8 @@ return ( | ||
if (index + 1 < array.length) { | ||
// eslint-disable-next-line react/no-array-index-key | ||
result.push(React.cloneElement(dateDividerElement, { key: `separator_${index}` })); | ||
result.push( | ||
// eslint-disable-next-line react/no-array-index-key | ||
<Divider key={`separator_${index}`}> | ||
{dateDivider} | ||
</Divider>, | ||
); | ||
} | ||
@@ -418,3 +410,3 @@ | ||
renderCustomTimeInputs() { | ||
const { timeDivider, timeDividerElement, timePlaceholder } = this; | ||
const { timeDivider, timePlaceholder } = this; | ||
@@ -439,4 +431,8 @@ return ( | ||
if (index + 1 < array.length) { | ||
// eslint-disable-next-line react/no-array-index-key | ||
result.push(React.cloneElement(timeDividerElement, { key: `separator_${index}` })); | ||
result.push( | ||
// eslint-disable-next-line react/no-array-index-key | ||
<Divider key={`separator_${index}`}> | ||
{timeDivider} | ||
</Divider>, | ||
); | ||
} | ||
@@ -453,2 +449,3 @@ | ||
key="time" | ||
disabled={this.props.disabled} | ||
maxDate={this.props.maxDate} | ||
@@ -467,6 +464,8 @@ minDate={this.props.minDate} | ||
return ( | ||
<div className="react-datetime-picker__button__input"> | ||
<div className={className}> | ||
{this.renderNativeInput()} | ||
{this.renderCustomDateInputs()} | ||
{this.dividerElement} | ||
<Divider> | ||
{'\u00a0'} | ||
</Divider> | ||
{this.renderCustomTimeInputs()} | ||
@@ -484,6 +483,7 @@ </div> | ||
DateTimeInput.propTypes = { | ||
isCalendarOpen: PropTypes.bool, | ||
disabled: PropTypes.bool, | ||
isWidgetOpen: PropTypes.bool, | ||
locale: PropTypes.string, | ||
maxDate: isMaxDate, | ||
maxDetail: PropTypes.oneOf(allViews), | ||
maxDate: isMaxDate, | ||
minDate: isMinDate, | ||
@@ -493,2 +493,3 @@ name: PropTypes.string, | ||
required: PropTypes.bool, | ||
showLeadingZeros: PropTypes.bool, | ||
value: PropTypes.oneOfType([ | ||
@@ -495,0 +496,0 @@ PropTypes.string, |
import React, { PureComponent } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { | ||
getISOLocalDateTime, | ||
} from '../shared/dates'; | ||
import { getISOLocalDateTime } from '../shared/dates'; | ||
import { isMaxDate, isMinDate } from '../shared/propTypes'; | ||
@@ -16,3 +14,3 @@ | ||
const { | ||
maxDate, minDate, name, onChange, required, value, | ||
disabled, maxDate, minDate, name, onChange, required, value, | ||
} = this.props; | ||
@@ -23,2 +21,3 @@ | ||
type="datetime-local" | ||
disabled={disabled} | ||
max={maxDate ? nativeValueParser(maxDate) : null} | ||
@@ -43,2 +42,3 @@ min={minDate ? nativeValueParser(minDate) : null} | ||
NativeInput.propTypes = { | ||
disabled: PropTypes.bool, | ||
maxDate: isMaxDate, | ||
@@ -45,0 +45,0 @@ minDate: isMinDate, |
@@ -1,2 +0,2 @@ | ||
import React, { Component } from 'react'; | ||
import React, { PureComponent } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
@@ -15,3 +15,3 @@ import mergeClassNames from 'merge-class-names'; | ||
export default class DateTimePicker extends Component { | ||
export default class DateTimePicker extends PureComponent { | ||
state = { | ||
@@ -62,6 +62,2 @@ isCalendarOpen: this.props.isCalendarOpen, | ||
toggleClock = () => { | ||
this.setState(prevState => ({ isClockOpen: !prevState.isClockOpen })); | ||
} | ||
openCalendar = () => { | ||
@@ -82,2 +78,24 @@ this.setState({ | ||
onDateChange = (value, closeWidgets = true) => { | ||
const { value: prevValue } = this.props; | ||
if (prevValue) { | ||
const valueWithHour = new Date(value); | ||
valueWithHour.setHours( | ||
prevValue.getHours(), | ||
prevValue.getMinutes(), | ||
prevValue.getSeconds(), | ||
prevValue.getMilliseconds(), | ||
); | ||
this.onChange(valueWithHour, closeWidgets); | ||
} else { | ||
this.onChange(value, closeWidgets); | ||
} | ||
} | ||
onTimeChange = (value, closeWidgets = true) => { | ||
this.onChange(value, closeWidgets); | ||
} | ||
onChange = (value, closeWidgets = true) => { | ||
@@ -116,15 +134,5 @@ this.setState(prevState => ({ | ||
renderInputs() { | ||
const { | ||
clearIcon, | ||
calendarIcon, | ||
locale, | ||
maxDetail, | ||
maxDate, | ||
minDate, | ||
name, | ||
required, | ||
value, | ||
} = this.props; | ||
const { disabled } = this.props; | ||
const { isCalendarOpen } = this.state; | ||
const { isCalendarOpen, isClockOpen } = this.state; | ||
@@ -134,15 +142,18 @@ return ( | ||
<DateTimeInput | ||
locale={locale} | ||
isCalendarOpen={isCalendarOpen} | ||
maxDetail={maxDetail} | ||
maxDate={maxDate} | ||
minDate={minDate} | ||
name={name} | ||
onChange={this.onChange} | ||
disabled={disabled} | ||
locale={this.props.locale} | ||
isWidgetOpen={isCalendarOpen || isClockOpen} | ||
maxDetail={this.props.maxDetail} | ||
maxDate={this.props.maxDate} | ||
minDate={this.props.minDate} | ||
name={this.props.name} | ||
onChange={this.onTimeChange} | ||
placeholder={this.placeholder} | ||
required={required} | ||
value={value} | ||
required={this.props.required} | ||
showLeadingZeros={this.props.showLeadingZeros} | ||
value={this.props.value} | ||
/> | ||
<button | ||
className="react-datetime-picker__clear-button react-datetime-picker__button__icon" | ||
disabled={disabled} | ||
onClick={this.clear} | ||
@@ -152,6 +163,7 @@ onFocus={this.stopPropagation} | ||
> | ||
{clearIcon} | ||
{this.props.clearIcon} | ||
</button> | ||
<button | ||
className="react-datetime-picker__calendar-button react-datetime-picker__button__icon" | ||
disabled={disabled} | ||
onClick={this.toggleCalendar} | ||
@@ -162,3 +174,3 @@ onFocus={this.stopPropagation} | ||
> | ||
{calendarIcon} | ||
{this.props.calendarIcon} | ||
</button> | ||
@@ -181,2 +193,3 @@ </div> | ||
onChange, | ||
value, | ||
...calendarProps | ||
@@ -209,3 +222,4 @@ } = this.props; | ||
className={calendarClassName} | ||
onChange={this.onChange} | ||
onChange={this.onDateChange} | ||
value={value || null} | ||
{...calendarProps} | ||
@@ -274,2 +288,3 @@ /> | ||
`${className}--${this.state.isCalendarOpen || this.state.isClockOpen ? 'open' : 'closed'}`, | ||
`${className}--${this.props.disabled ? 'disabled' : 'enabled'}`, | ||
this.props.className, | ||
@@ -316,2 +331,4 @@ )} | ||
DateTimePicker.propTypes = { | ||
...Calendar.propTypes, | ||
...Clock.propTypes, | ||
calendarClassName: PropTypes.oneOfType([ | ||
@@ -331,2 +348,3 @@ PropTypes.string, | ||
clearIcon: PropTypes.node, | ||
disabled: PropTypes.bool, | ||
isCalendarOpen: PropTypes.bool, | ||
@@ -341,2 +359,3 @@ isClockOpen: PropTypes.bool, | ||
required: PropTypes.bool, | ||
showLeadingZeros: PropTypes.bool, | ||
value: PropTypes.oneOfType([ | ||
@@ -343,0 +362,0 @@ PropTypes.string, |
@@ -0,0 +0,0 @@ import 'react-calendar/dist/Calendar.css'; |
import DateTimePicker from './DateTimePicker'; | ||
export default DateTimePicker; |
@@ -1,2 +0,2 @@ | ||
import { getLocale } from './locales'; | ||
import { getDefaultLocale } from './locales'; | ||
@@ -9,31 +9,42 @@ const formatterCache = {}; | ||
*/ | ||
const getFormatter = (options, locales = getLocale()) => { | ||
const getFormatter = (options, locale) => { | ||
if (!locale) { | ||
// Default parameter is not enough as it does not protect us from null values | ||
// eslint-disable-next-line no-param-reassign | ||
locale = getDefaultLocale(); | ||
} | ||
const stringifiedOptions = JSON.stringify(options); | ||
if (!formatterCache[locales]) { | ||
formatterCache[locales] = {}; | ||
if (!formatterCache[locale]) { | ||
formatterCache[locale] = {}; | ||
} | ||
if (!formatterCache[locales][stringifiedOptions]) { | ||
formatterCache[locales][stringifiedOptions] = new Intl.DateTimeFormat(locales, options).format; | ||
if (!formatterCache[locale][stringifiedOptions]) { | ||
formatterCache[locale][stringifiedOptions] = new Intl.DateTimeFormat(locale, options).format; | ||
} | ||
return formatterCache[locales][stringifiedOptions]; | ||
return formatterCache[locale][stringifiedOptions]; | ||
}; | ||
export const formatDate = date => getFormatter( | ||
export const formatDate = (date, locale) => getFormatter( | ||
{ day: 'numeric', month: 'numeric', year: 'numeric' }, | ||
locale, | ||
)(date); | ||
export const formatTime = date => getFormatter( | ||
export const formatTime = (date, locale) => getFormatter( | ||
{ hour: 'numeric', minute: 'numeric', second: 'numeric' }, | ||
locale, | ||
)(date); | ||
export const formatDateTime = date => getFormatter({ | ||
day: 'numeric', | ||
month: 'numeric', | ||
year: 'numeric', | ||
hour: 'numeric', | ||
minute: 'numeric', | ||
second: 'numeric', | ||
})(date); | ||
export const formatDateTime = (date, locale) => getFormatter( | ||
{ | ||
day: 'numeric', | ||
month: 'numeric', | ||
year: 'numeric', | ||
hour: 'numeric', | ||
minute: 'numeric', | ||
second: 'numeric', | ||
}, | ||
locale, | ||
)(date); |
@@ -24,3 +24,3 @@ import { getISOLocalDate } from 'react-calendar/dist/shared/dates'; | ||
if (Number.isNaN(date.getTime())) { | ||
if (isNaN(date.getTime())) { | ||
throw new Error(`Invalid date: ${value}`); | ||
@@ -27,0 +27,0 @@ } |
@@ -1,25 +0,4 @@ | ||
import once from 'lodash.once'; | ||
let userLocale = null; | ||
export const getDefaultLocales = once(() => { | ||
const languageList = []; | ||
if (window.navigator.languages) { | ||
languageList.push(...window.navigator.languages); | ||
} else if (window.navigator.userLanguage) { | ||
languageList.push(window.navigator.userLanguage); | ||
} | ||
languageList.push('en-GB'); // Fallback | ||
return languageList; | ||
}); | ||
export const getDefaultLocale = once(() => getDefaultLocales()[0]); | ||
export const getLocale = () => userLocale || getDefaultLocale(); | ||
export const setLocale = (locale) => { | ||
userLocale = locale; | ||
}; | ||
/* eslint-disable import/prefer-default-export */ | ||
export { | ||
getDefaultLocale, | ||
} from 'react-date-picker/dist/shared/locales'; |
@@ -0,0 +0,0 @@ export { |
@@ -1,16 +0,5 @@ | ||
export const min = (...args) => Math.min(...args.filter(a => typeof a === 'number')); | ||
export const max = (...args) => Math.max(...args.filter(a => typeof a === 'number')); | ||
export const updateInputWidth = (element) => { | ||
const span = document.createElement('span'); | ||
span.innerHTML = element.value || element.placeholder; | ||
const container = element.parentElement; | ||
container.appendChild(span); | ||
const width = span.getBoundingClientRect().width + 4; | ||
element.style.width = `${width}px`; | ||
container.removeChild(span); | ||
}; | ||
export { | ||
min, | ||
max, | ||
updateInputWidth, | ||
} from 'react-date-picker/dist/shared/utils'; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
99356
31
2403
21
135
Updatedreact-calendar@^2.13.0
Updatedreact-date-picker@^6.9.0
Updatedreact-time-picker@^2.3.0