@nateradebaugh/react-datetime
Version:
A lightweight but complete datetime picker React.js component
1,659 lines (1,437 loc) • 59.1 kB
JavaScript
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = require('react');
var React__default = _interopDefault(React);
var reactDom = require('react-dom');
var addDays = _interopDefault(require('date-fns/add_days'));
var format = _interopDefault(require('date-fns/format'));
var getDaysInMonth = _interopDefault(require('date-fns/get_days_in_month'));
var getMonth = _interopDefault(require('date-fns/get_month'));
var getYear = _interopDefault(require('date-fns/get_year'));
var startOfWeek = _interopDefault(require('date-fns/start_of_week'));
var isSameDay = _interopDefault(require('date-fns/is_same_day'));
var isToday = _interopDefault(require('date-fns/is_today'));
var _setDate = _interopDefault(require('date-fns/set_date'));
var subMonths = _interopDefault(require('date-fns/sub_months'));
var getDate = _interopDefault(require('date-fns/get_date'));
var setMonth = _interopDefault(require('date-fns/set_month'));
var setYear = _interopDefault(require('date-fns/set_year'));
var getDaysInYear = _interopDefault(require('date-fns/get_days_in_year'));
var setDayOfYear = _interopDefault(require('date-fns/set_day_of_year'));
var getHours = _interopDefault(require('date-fns/get_hours'));
var startOfMonth = _interopDefault(require('date-fns/start_of_month'));
var isDate = _interopDefault(require('date-fns/is_date'));
var isValidDate = _interopDefault(require('date-fns/is_valid'));
var parse = _interopDefault(require('date-fns/parse'));
var startOfDay = _interopDefault(require('date-fns/start_of_day'));
var startOfYear = _interopDefault(require('date-fns/start_of_year'));
var addMonths = _interopDefault(require('date-fns/add_months'));
var addYears = _interopDefault(require('date-fns/add_years'));
var setHours = _interopDefault(require('date-fns/set_hours'));
var setMinutes = _interopDefault(require('date-fns/set_minutes'));
var setSeconds = _interopDefault(require('date-fns/set_seconds'));
var setMilliseconds = _interopDefault(require('date-fns/set_milliseconds'));
var getMinutes = _interopDefault(require('date-fns/get_minutes'));
var getSeconds = _interopDefault(require('date-fns/get_seconds'));
var getMilliseconds = _interopDefault(require('date-fns/get_milliseconds'));
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
/**
* Check whether some DOM node is our Component's node.
*/
function isNodeFound(current, componentNode, ignoreClass) {
if (current === componentNode) {
return true;
} // SVG <use/> elements do not technically reside in the rendered DOM, so
// they do not have classList directly, but they offer a link to their
// corresponding element, which can have classList. This extra check is for
// that case.
// See: http://www.w3.org/TR/SVG11/struct.html#InterfaceSVGUseElement
// Discussion: https://github.com/Pomax/react-onclickoutside/pull/17
if (current.correspondingElement) {
return current.correspondingElement.classList.contains(ignoreClass);
}
return current.classList.contains(ignoreClass);
}
/**
* Try to find our node in a hierarchy of nodes, returning the document
* node as highest node if our node is not found in the path up.
*/
function findHighest(current, componentNode, ignoreClass) {
if (current === componentNode) {
return true;
} // If source=local then this event came from 'somewhere'
// inside and should be ignored. We could handle this with
// a layered approach, too, but that requires going back to
// thinking in terms of Dom node nesting, running counter
// to React's 'you shouldn't care about the DOM' philosophy.
while (current.parentNode) {
if (isNodeFound(current, componentNode, ignoreClass)) {
return true;
}
current = current.parentNode;
}
return current;
}
/**
* Check if the browser scrollbar was clicked
*/
function clickedScrollbar(evt) {
return document.documentElement.clientWidth <= evt.clientX || document.documentElement.clientHeight <= evt.clientY;
}
// ideally will get replaced with external dep
// when rafrex/detect-passive-events#4 and rafrex/detect-passive-events#5 get merged in
var testPassiveEventSupport = function testPassiveEventSupport() {
if (typeof window === 'undefined' || typeof window.addEventListener !== 'function') {
return;
}
var passive = false;
var options = Object.defineProperty({}, 'passive', {
get: function get() {
passive = true;
}
});
var noop = function noop() {};
window.addEventListener('testPassiveEventSupport', noop, options);
window.removeEventListener('testPassiveEventSupport', noop, options);
return passive;
};
function autoInc(seed) {
if (seed === void 0) {
seed = 0;
}
return function () {
return ++seed;
};
}
var uid = autoInc();
var passiveEventSupport;
var handlersMap = {};
var enabledInstances = {};
var touchEvents = ['touchstart', 'touchmove'];
var IGNORE_CLASS_NAME = 'ignore-react-onclickoutside';
/**
* Options for addEventHandler and removeEventHandler
*/
function getEventHandlerOptions(instance, eventName) {
var handlerOptions = null;
var isTouchEvent = touchEvents.indexOf(eventName) !== -1;
if (isTouchEvent && passiveEventSupport) {
handlerOptions = {
passive: !instance.props.preventDefault
};
}
return handlerOptions;
}
/**
* This function generates the HOC function that you'll use
* in order to impart onOutsideClick listening to an
* arbitrary component. It gets called at the end of the
* bootstrapping code to yield an instance of the
* onClickOutsideHOC function defined inside setupHOC().
*/
function onClickOutsideHOC(WrappedComponent, config) {
var _class, _temp;
return _temp = _class =
/*#__PURE__*/
function (_Component) {
_inheritsLoose(onClickOutside, _Component);
function onClickOutside(props) {
var _this;
_this = _Component.call(this, props) || this;
_this.__outsideClickHandler = function (event) {
if (typeof _this.__clickOutsideHandlerProp === 'function') {
_this.__clickOutsideHandlerProp(event);
return;
}
var instance = _this.getInstance();
if (typeof instance.props.handleClickOutside === 'function') {
instance.props.handleClickOutside(event);
return;
}
if (typeof instance.handleClickOutside === 'function') {
instance.handleClickOutside(event);
return;
}
throw new Error('WrappedComponent lacks a handleClickOutside(event) function for processing outside click events.');
};
_this.enableOnClickOutside = function () {
if (typeof document === 'undefined' || enabledInstances[_this._uid]) {
return;
}
if (typeof passiveEventSupport === 'undefined') {
passiveEventSupport = testPassiveEventSupport();
}
enabledInstances[_this._uid] = true;
var events = _this.props.eventTypes;
if (!events.forEach) {
events = [events];
}
handlersMap[_this._uid] = function (event) {
if (_this.props.disableOnClickOutside) return;
if (_this.componentNode === null) return;
if (_this.props.preventDefault) {
event.preventDefault();
}
if (_this.props.stopPropagation) {
event.stopPropagation();
}
if (_this.props.excludeScrollbar && clickedScrollbar(event)) return;
var current = event.target;
if (findHighest(current, _this.componentNode, _this.props.outsideClickIgnoreClass) !== document) {
return;
}
_this.__outsideClickHandler(event);
};
events.forEach(function (eventName) {
document.addEventListener(eventName, handlersMap[_this._uid], getEventHandlerOptions(_this, eventName));
});
};
_this.disableOnClickOutside = function () {
delete enabledInstances[_this._uid];
var fn = handlersMap[_this._uid];
if (fn && typeof document !== 'undefined') {
var events = _this.props.eventTypes;
if (!events.forEach) {
events = [events];
}
events.forEach(function (eventName) {
return document.removeEventListener(eventName, fn, getEventHandlerOptions(_this, eventName));
});
delete handlersMap[_this._uid];
}
};
_this.getRef = function (ref) {
return _this.instanceRef = ref;
};
_this._uid = uid();
return _this;
}
/**
* Access the WrappedComponent's instance.
*/
var _proto = onClickOutside.prototype;
_proto.getInstance = function getInstance() {
if (!WrappedComponent.prototype.isReactComponent) {
return this;
}
var ref = this.instanceRef;
return ref.getInstance ? ref.getInstance() : ref;
};
/**
* Add click listeners to the current document,
* linked to this component's state.
*/
_proto.componentDidMount = function componentDidMount() {
// If we are in an environment without a DOM such
// as shallow rendering or snapshots then we exit
// early to prevent any unhandled errors being thrown.
if (typeof document === 'undefined' || !document.createElement) {
return;
}
var instance = this.getInstance();
if (config && typeof config.handleClickOutside === 'function') {
this.__clickOutsideHandlerProp = config.handleClickOutside(instance);
if (typeof this.__clickOutsideHandlerProp !== 'function') {
throw new Error('WrappedComponent lacks a function for processing outside click events specified by the handleClickOutside config option.');
}
}
this.componentNode = reactDom.findDOMNode(this.getInstance());
this.enableOnClickOutside();
};
_proto.componentDidUpdate = function componentDidUpdate() {
this.componentNode = reactDom.findDOMNode(this.getInstance());
};
/**
* Remove all document's event listeners for this component
*/
_proto.componentWillUnmount = function componentWillUnmount() {
this.disableOnClickOutside();
};
/**
* Can be called to explicitly enable event listening
* for clicks and touches outside of this element.
*/
/**
* Pass-through render
*/
_proto.render = function render() {
// eslint-disable-next-line no-unused-vars
var _props = this.props,
excludeScrollbar = _props.excludeScrollbar,
props = _objectWithoutProperties(_props, ["excludeScrollbar"]);
if (WrappedComponent.prototype.isReactComponent) {
props.ref = this.getRef;
} else {
props.wrappedRef = this.getRef;
}
props.disableOnClickOutside = this.disableOnClickOutside;
props.enableOnClickOutside = this.enableOnClickOutside;
return React.createElement(WrappedComponent, props);
};
return onClickOutside;
}(React.Component), _class.displayName = "OnClickOutside(" + (WrappedComponent.displayName || WrappedComponent.name || 'Component') + ")", _class.defaultProps = {
eventTypes: ['mousedown', 'touchstart'],
excludeScrollbar: config && config.excludeScrollbar || false,
outsideClickIgnoreClass: IGNORE_CLASS_NAME,
preventDefault: false,
stopPropagation: false
}, _class.getClass = function () {
return WrappedComponent.getClass ? WrappedComponent.getClass() : WrappedComponent;
}, _temp;
}
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var DaysView = function (_Component) {
inherits(DaysView, _Component);
function DaysView(props) {
classCallCheck(this, DaysView);
// Bind functions
var _this = possibleConstructorReturn(this, (DaysView.__proto__ || Object.getPrototypeOf(DaysView)).call(this, props));
_this.renderDays = _this.renderDays.bind(_this);
_this.updateSelectedDate = _this.updateSelectedDate.bind(_this);
_this.renderDay = _this.renderDay.bind(_this);
_this.renderFooter = _this.renderFooter.bind(_this);
_this.alwaysValidDate = _this.alwaysValidDate.bind(_this);
_this.getFormatOptions = _this.getFormatOptions.bind(_this);
return _this;
}
createClass(DaysView, [{
key: "getFormatOptions",
value: function getFormatOptions() {
return { locale: this.props.locale };
}
}, {
key: "render",
value: function render() {
var date = this.props.viewDate || new Date();
var theStartOfWeek = startOfWeek(date);
return React__default.createElement(
"div",
{ className: "rdtDays" },
React__default.createElement(
"table",
null,
React__default.createElement(
"thead",
null,
React__default.createElement(
"tr",
null,
React__default.createElement(
"th",
{
className: "rdtPrev",
onClick: this.props.subtractTime(1, "months")
},
React__default.createElement(
"span",
null,
"\u2039"
)
),
React__default.createElement(
"th",
{
className: "rdtSwitch",
onClick: this.props.showView("months"),
colSpan: 5,
"data-value": getMonth(this.props.viewDate)
},
format(date, "MMMM YYYY", this.getFormatOptions())
),
React__default.createElement(
"th",
{ className: "rdtNext", onClick: this.props.addTime(1, "months") },
React__default.createElement(
"span",
null,
"\u203A"
)
)
),
React__default.createElement(
"tr",
null,
React__default.createElement(
"th",
{ className: "dow" },
format(addDays(theStartOfWeek, 0), "dd", this.getFormatOptions())
),
React__default.createElement(
"th",
{ className: "dow" },
format(addDays(theStartOfWeek, 1), "dd", this.getFormatOptions())
),
React__default.createElement(
"th",
{ className: "dow" },
format(addDays(theStartOfWeek, 2), "dd", this.getFormatOptions())
),
React__default.createElement(
"th",
{ className: "dow" },
format(addDays(theStartOfWeek, 3), "dd", this.getFormatOptions())
),
React__default.createElement(
"th",
{ className: "dow" },
format(addDays(theStartOfWeek, 4), "dd", this.getFormatOptions())
),
React__default.createElement(
"th",
{ className: "dow" },
format(addDays(theStartOfWeek, 5), "dd", this.getFormatOptions())
),
React__default.createElement(
"th",
{ className: "dow" },
format(addDays(theStartOfWeek, 6), "dd", this.getFormatOptions())
)
)
),
React__default.createElement(
"tbody",
null,
this.renderDays()
),
this.renderFooter()
)
);
}
}, {
key: "renderDays",
value: function renderDays() {
var date = this.props.viewDate || new Date();
var selectedDate = this.props.selectedDate ? this.props.selectedDate : undefined;
var prevMonth = subMonths(date, 1);
var currentYear = getYear(date);
var currentMonth = getMonth(date);
var weeks = [];
var days = [];
var renderer = this.props.renderDay || this.renderDay;
var isValid = this.props.isValidDate || this.alwaysValidDate;
var prevMonthLastWeekStart = startOfWeek(_setDate(prevMonth, getDaysInMonth(prevMonth)));
var lastDay = addDays(prevMonthLastWeekStart, 42);
for (var workingDate = prevMonthLastWeekStart; workingDate < lastDay; workingDate = addDays(workingDate, 1)) {
var classes = "rdtDay";
var workingYear = getYear(workingDate);
var workingMonth = getMonth(workingDate);
if (workingYear === currentYear && workingMonth < currentMonth || workingYear < currentYear) {
classes += " rdtOld";
} else if (workingYear === currentYear && workingMonth > currentMonth || workingYear > currentYear) {
classes += " rdtNew";
}
if (selectedDate && isSameDay(workingDate, selectedDate)) {
classes += " rdtActive";
}
if (isToday(workingDate)) {
classes += " rdtToday";
}
var isDisabled = !isValid(workingDate, selectedDate);
if (isDisabled) {
classes += " rdtDisabled";
}
var dayProps = {
key: getDate(workingDate),
className: classes,
"data-value": getDate(workingDate)
};
if (!isDisabled) {
dayProps.onClick = this.updateSelectedDate;
}
days.push(renderer(dayProps, workingDate, selectedDate));
if (days.length === 7) {
weeks.push(React__default.createElement(
"tr",
{ key: workingDate },
days
));
days = [];
}
}
return weeks;
}
}, {
key: "updateSelectedDate",
value: function updateSelectedDate(event) {
this.props.updateSelectedDate(event, true);
}
}, {
key: "renderDay",
value: function renderDay(props, currentDate) {
return React__default.createElement(
"td",
props,
format(currentDate, "D", this.getFormatOptions())
);
}
}, {
key: "renderFooter",
value: function renderFooter() {
if (!this.props.timeFormat) {
return null;
}
var date = this.props.selectedDate || this.props.viewDate;
return React__default.createElement(
"tfoot",
null,
React__default.createElement(
"tr",
null,
React__default.createElement(
"td",
{
onClick: this.props.showView("time"),
colSpan: 7,
className: "rdtTimeToggle"
},
format(date, this.props.timeFormat, this.getFormatOptions())
)
)
);
}
}, {
key: "alwaysValidDate",
value: function alwaysValidDate() {
return 1;
}
}, {
key: "handleClickOutside",
value: function handleClickOutside() {
this.props.handleClickOutside();
}
}]);
return DaysView;
}(React.Component);
var DaysView$1 = onClickOutsideHOC(DaysView);
var MonthsView = function (_Component) {
inherits(MonthsView, _Component);
function MonthsView(props) {
classCallCheck(this, MonthsView);
// Bind functions
var _this = possibleConstructorReturn(this, (MonthsView.__proto__ || Object.getPrototypeOf(MonthsView)).call(this, props));
_this.renderMonths = _this.renderMonths.bind(_this);
_this.updateSelectedMonth = _this.updateSelectedMonth.bind(_this);
_this.renderMonth = _this.renderMonth.bind(_this);
_this.alwaysValidDate = _this.alwaysValidDate.bind(_this);
_this.getFormatOptions = _this.getFormatOptions.bind(_this);
return _this;
}
createClass(MonthsView, [{
key: "getFormatOptions",
value: function getFormatOptions() {
return { locale: this.props.locale };
}
}, {
key: "render",
value: function render() {
var date = this.props.viewDate || new Date();
return React__default.createElement(
"div",
{ className: "rdtMonths" },
React__default.createElement(
"table",
null,
React__default.createElement(
"thead",
null,
React__default.createElement(
"tr",
null,
React__default.createElement(
"th",
{
className: "rdtPrev",
onClick: this.props.subtractTime(1, "years")
},
React__default.createElement(
"span",
null,
"\u2039"
)
),
React__default.createElement(
"th",
{
className: "rdtSwitch",
onClick: this.props.showView("years"),
colSpan: 2,
"data-value": getYear(this.props.viewDate)
},
format(date, "YYYY", this.getFormatOptions())
),
React__default.createElement(
"th",
{ className: "rdtNext", onClick: this.props.addTime(1, "years") },
React__default.createElement(
"span",
null,
"\u203A"
)
)
)
)
),
React__default.createElement(
"table",
null,
React__default.createElement(
"tbody",
null,
this.renderMonths()
)
)
);
}
}, {
key: "renderMonths",
value: function renderMonths() {
var _this2 = this;
var date = this.props.selectedDate;
var year = getYear(this.props.viewDate);
var renderer = this.props.renderMonth || this.renderMonth;
var isValid = this.props.isValidDate || this.alwaysValidDate;
var rows = [];
var months = [];
var _loop = function _loop(i) {
var classes = "rdtMonth";
var currentMonth = setMonth(_this2.props.viewDate, i);
var noOfDaysInMonth = getDaysInMonth(currentMonth);
var daysInMonth = Array.from({ length: noOfDaysInMonth }, function (e, i) {
return i + 1;
});
var validDay = daysInMonth.find(function (d) {
var day = _setDate(currentMonth, d);
return isValid(day);
});
var isDisabled = validDay === undefined;
if (isDisabled) {
classes += " rdtDisabled";
}
if (date && i === getMonth(date) && year === getYear(date)) {
classes += " rdtActive";
}
var props = {
key: i,
"data-value": i,
className: classes
};
if (!isDisabled) {
props.onClick = _this2.props.updateOn === "months" ? _this2.updateSelectedMonth : _this2.props.setDate("month");
}
months.push(renderer(props, i, year, date));
if (months.length === 4) {
rows.push(React__default.createElement(
"tr",
{ key: i },
months
));
months = [];
}
};
for (var i = 0; i < 12; i++) {
_loop(i);
}
return rows;
}
}, {
key: "updateSelectedMonth",
value: function updateSelectedMonth(event) {
this.props.updateSelectedDate(event);
}
}, {
key: "renderMonth",
value: function renderMonth(props, month, year, selected) {
var monthDate = setMonth(new Date(), month);
return React__default.createElement(
"td",
props,
format(monthDate, "MMM", this.getFormatOptions())
);
}
}, {
key: "alwaysValidDate",
value: function alwaysValidDate() {
return 1;
}
}, {
key: "handleClickOutside",
value: function handleClickOutside() {
this.props.handleClickOutside();
}
}]);
return MonthsView;
}(React.Component);
var MonthsView$1 = onClickOutsideHOC(MonthsView);
var YearsView = function (_Component) {
inherits(YearsView, _Component);
function YearsView(props) {
classCallCheck(this, YearsView);
// Bind functions
var _this = possibleConstructorReturn(this, (YearsView.__proto__ || Object.getPrototypeOf(YearsView)).call(this, props));
_this.renderYears = _this.renderYears.bind(_this);
_this.updateSelectedYear = _this.updateSelectedYear.bind(_this);
_this.renderYear = _this.renderYear.bind(_this);
_this.alwaysValidDate = _this.alwaysValidDate.bind(_this);
return _this;
}
createClass(YearsView, [{
key: "render",
value: function render() {
var year = parseInt(getYear(this.props.viewDate) / 10, 10) * 10;
return React__default.createElement(
"div",
{ className: "rdtYears" },
React__default.createElement(
"table",
null,
React__default.createElement(
"thead",
null,
React__default.createElement(
"tr",
null,
React__default.createElement(
"th",
{
className: "rdtPrev",
onClick: this.props.subtractTime(10, "years")
},
React__default.createElement(
"span",
null,
"\u2039"
)
),
React__default.createElement(
"th",
{
className: "rdtSwitch",
onClick: this.props.showView("years"),
colSpan: 2
},
year,
"-",
year + 9
),
React__default.createElement(
"th",
{ className: "rdtNext", onClick: this.props.addTime(10, "years") },
React__default.createElement(
"span",
null,
"\u203A"
)
)
)
)
),
React__default.createElement(
"table",
null,
React__default.createElement(
"tbody",
null,
this.renderYears(year)
)
)
);
}
}, {
key: "renderYears",
value: function renderYears(year) {
var _this2 = this;
var renderer = this.props.renderYear || this.renderYear;
var selectedDate = this.props.selectedDate;
var date = this.props.viewDate || new Date();
var isValid = this.props.isValidDate || this.alwaysValidDate;
var years = [];
var rows = [];
year--;
var _loop = function _loop(i) {
var classes = "rdtYear";
var currentYear = setYear(date, year);
var noOfDaysInYear = getDaysInYear(date);
var daysInYear = Array.from({ length: noOfDaysInYear }, function (e, i) {
return i + 1;
});
var validDay = daysInYear.find(function (d) {
var day = setDayOfYear(currentYear, d);
return isValid(day);
});
var isDisabled = validDay === undefined;
if (isDisabled) {
classes += " rdtDisabled";
}
if (selectedDate && getYear(selectedDate) === year) {
classes += " rdtActive";
}
var props = {
key: year,
"data-value": year,
className: classes
};
if (!isDisabled) {
props.onClick = _this2.props.updateOn === "years" ? _this2.updateSelectedYear : _this2.props.setDate("year");
}
years.push(renderer(props, year, selectedDate && new Date(selectedDate.getTime())));
if (years.length === 4) {
rows.push(React__default.createElement(
"tr",
{ key: i },
years
));
years = [];
}
};
for (var i = -1; i < 11; i++, year++) {
_loop(i);
}
return rows;
}
}, {
key: "updateSelectedYear",
value: function updateSelectedYear(event) {
this.props.updateSelectedDate(event);
}
}, {
key: "renderYear",
value: function renderYear(props, year) {
return React__default.createElement(
"td",
props,
year
);
}
}, {
key: "alwaysValidDate",
value: function alwaysValidDate() {
return 1;
}
}, {
key: "handleClickOutside",
value: function handleClickOutside() {
this.props.handleClickOutside();
}
}]);
return YearsView;
}(React.Component);
var YearsView$1 = onClickOutsideHOC(YearsView);
var padValues = {
hours: 1,
minutes: 2,
seconds: 2,
milliseconds: 3
};
var TimeView = function (_Component) {
inherits(TimeView, _Component);
function TimeView(props) {
classCallCheck(this, TimeView);
var _this = possibleConstructorReturn(this, (TimeView.__proto__ || Object.getPrototypeOf(TimeView)).call(this, props));
_this.state = _this.calculateState(props);
// Bind functions
_this.onStartClicking = _this.onStartClicking.bind(_this);
_this.disableContextMenu = _this.disableContextMenu.bind(_this);
_this.toggleDayPart = _this.toggleDayPart.bind(_this);
_this.increase = _this.increase.bind(_this);
_this.decrease = _this.decrease.bind(_this);
_this.pad = _this.pad.bind(_this);
_this.calculateState = _this.calculateState.bind(_this);
_this.updateMilli = _this.updateMilli.bind(_this);
_this.renderHeader = _this.renderHeader.bind(_this);
_this.renderCounter = _this.renderCounter.bind(_this);
_this.renderDayPart = _this.renderDayPart.bind(_this);
_this.getFormatOptions = _this.getFormatOptions.bind(_this);
return _this;
}
createClass(TimeView, [{
key: "getFormatOptions",
value: function getFormatOptions() {
return { locale: this.props.locale };
}
}, {
key: "componentDidMount",
value: function componentDidMount() {
var _this2 = this;
this.timeConstraints = {
hours: {
min: 0,
max: 23,
step: 1
},
minutes: {
min: 0,
max: 59,
step: 1
},
seconds: {
min: 0,
max: 59,
step: 1
},
milliseconds: {
min: 0,
max: 999,
step: 1
}
};
if (this.props.timeConstraints) {
["hours", "minutes", "seconds", "millisecond"].forEach(function (type) {
if (_this2.props.timeConstraints[type]) {
_this2.timeConstraints[type] = _extends({}, _this2.timeConstraints[type], _this2.props.timeConstraints[type]);
}
});
}
this.setState(this.calculateState(this.props));
}
}, {
key: "UNSAFE_componentWillReceiveProps",
value: function UNSAFE_componentWillReceiveProps(nextProps) {
this.setState(this.calculateState(nextProps));
}
}, {
key: "onStartClicking",
value: function onStartClicking(action, type) {
var _this3 = this;
return function () {
var update = {};
update[type] = _this3[action](type);
_this3.setState(update);
_this3.timer = setTimeout(function () {
_this3.increaseTimer = setInterval(function () {
update[type] = _this3[action](type);
_this3.setState(update);
}, 70);
}, 500);
_this3.mouseUpListener = function () {
clearTimeout(_this3.timer);
clearInterval(_this3.increaseTimer);
_this3.props.setTime(type, _this3.state[type]);
document.body.removeEventListener("mouseup", _this3.mouseUpListener);
document.body.removeEventListener("touchend", _this3.mouseUpListener);
};
document.body.addEventListener("mouseup", _this3.mouseUpListener);
document.body.addEventListener("touchend", _this3.mouseUpListener);
};
}
}, {
key: "disableContextMenu",
value: function disableContextMenu(event) {
event.preventDefault();
return false;
}
}, {
key: "toggleDayPart",
value: function toggleDayPart(type) {
var constraints = this.timeConstraints[type];
// type is always 'hours'
var value = parseInt(this.state[type], 10) + 12;
if (value > constraints.max) {
value = constraints.min + (value - (constraints.max + 1));
}
return this.pad(type, value);
}
}, {
key: "increase",
value: function increase(type) {
var constraints = this.timeConstraints[type];
var value = parseInt(this.state[type], 10) + constraints.step;
if (value > constraints.max) {
value = constraints.min + (value - (constraints.max + 1));
}
return this.pad(type, value);
}
}, {
key: "decrease",
value: function decrease(type) {
var constraints = this.timeConstraints[type];
var value = parseInt(this.state[type], 10) - constraints.step;
if (value < constraints.min) {
value = constraints.max + 1 - (constraints.min - value);
}
return this.pad(type, value);
}
}, {
key: "pad",
value: function pad(type, value) {
var str = value + "";
while (str.length < padValues[type]) {
str = "0" + str;
}return str;
}
}, {
key: "calculateState",
value: function calculateState(props) {
var date = props.selectedDate || props.viewDate;
var timeFormat = typeof props.timeFormat === "string" ? props.timeFormat.toLowerCase() : "";
var counters = [];
if (timeFormat.toLowerCase().indexOf("h") !== -1) {
counters.push("hours");
if (timeFormat.indexOf("m") !== -1) {
counters.push("minutes");
if (timeFormat.indexOf("s") !== -1) {
counters.push("seconds");
}
}
}
var hours = getHours(date);
var daypart = undefined;
if (this.state !== null && timeFormat.indexOf(" a") !== -1) {
if (props.timeFormat.indexOf(" A") !== -1) {
daypart = hours >= 12 ? "PM" : "AM";
} else {
daypart = hours >= 12 ? "pm" : "am";
}
}
return {
hours: hours,
minutes: format(date, "mm", this.getFormatOptions()),
seconds: format(date, "ss", this.getFormatOptions()),
milliseconds: format(date, "SSS", this.getFormatOptions()),
daypart: daypart,
counters: counters
};
}
}, {
key: "updateMilli",
value: function updateMilli(e) {
var milli = parseInt(e.target.value, 10);
if (milli === e.target.value && milli >= 0 && milli < 1000) {
this.props.setTime("milliseconds", milli);
this.setState({ milliseconds: milli });
}
}
}, {
key: "renderHeader",
value: function renderHeader() {
if (!this.props.dateFormat) {
return null;
}
var date = this.props.selectedDate || this.props.viewDate;
return React__default.createElement(
"thead",
null,
React__default.createElement(
"tr",
null,
React__default.createElement(
"th",
{
className: "rdtSwitch",
colSpan: 4,
onClick: this.props.showView("days")
},
format(date, this.props.dateFormat)
)
)
);
}
}, {
key: "renderCounter",
value: function renderCounter(type) {
var timeFormat = typeof this.props.timeFormat === "string" ? this.props.timeFormat.toLowerCase() : "";
if (type !== "daypart") {
var value = this.state[type];
if (type === "hours" && timeFormat.indexOf(" a") !== -1) {
value = (value - 1) % 12 + 1;
if (value === 0) {
value = 12;
}
}
return React__default.createElement(
"div",
{ key: type, className: "rdtCounter" },
React__default.createElement(
"span",
{
className: "rdtBtn",
onMouseDown: this.onStartClicking("increase", type),
onContextMenu: this.disableContextMenu
},
"\u25B2"
),
React__default.createElement(
"div",
{ className: "rdtCount" },
value
),
React__default.createElement(
"span",
{
className: "rdtBtn",
onMouseDown: this.onStartClicking("decrease", type),
onContextMenu: this.disableContextMenu
},
"\u25BC"
)
);
}
return null;
}
}, {
key: "renderDayPart",
value: function renderDayPart() {
return React__default.createElement(
"div",
{ key: "dayPart", className: "rdtCounter" },
React__default.createElement(
"span",
{
className: "rdtBtn",
onMouseDown: this.onStartClicking("toggleDayPart", "hours"),
onContextMenu: this.disableContextMenu
},
"\u25B2"
),
React__default.createElement(
"div",
{ className: "rdtCount" },
this.state.daypart
),
React__default.createElement(
"span",
{
className: "rdtBtn",
onMouseDown: this.onStartClicking("toggleDayPart", "hours"),
onContextMenu: this.disableContextMenu
},
"\u25BC"
)
);
}
}, {
key: "render",
value: function render() {
var _this4 = this;
var counters = [];
this.state.counters.forEach(function (c) {
if (counters.length) {
counters.push(React__default.createElement(
"div",
{ key: "sep" + counters.length, className: "rdtCounterSeparator" },
":"
));
}
counters.push(_this4.renderCounter(c));
});
if (this.state.daypart) {
counters.push(this.renderDayPart());
}
var timeFormat = this.props.timeFormat || "";
if (this.state.counters.length === 3 && timeFormat.indexOf("S") !== -1) {
counters.push(React__default.createElement(
"div",
{ key: "sep5", className: "rdtCounterSeparator" },
":"
));
counters.push(React__default.createElement(
"div",
{ key: "ms", className: "rdtCounter rdtMilli" },
React__default.createElement("input", {
type: "text",
value: this.state.milliseconds,
onChange: this.updateMilli
})
));
}
return React__default.createElement(
"div",
{ className: "rdtTime" },
React__default.createElement(
"table",
null,
this.renderHeader(),
React__default.createElement(
"tbody",
null,
React__default.createElement(
"tr",
null,
React__default.createElement(
"td",
null,
React__default.createElement(
"div",
{ className: "rdtCounters" },
counters
)
)
)
)
)
);
}
}, {
key: "handleClickOutside",
value: function handleClickOutside() {
this.props.handleClickOutside();
}
}]);
return TimeView;
}(React.Component);
var TimeView$1 = onClickOutsideHOC(TimeView);
var viewComponents = {
days: DaysView$1,
months: MonthsView$1,
years: YearsView$1,
time: TimeView$1
};
var CalendarContainer = function CalendarContainer(props) {
var view = props.view,
viewProps = props.viewProps;
var Component = viewComponents[view || "days"];
return React__default.createElement(Component, viewProps);
};
var toUtc = function toUtc(time) {
return new Date(time.getTime() + time.getTimezoneOffset() * 60000);
};
var toUtc$1 = function toUtc(time) {
return new Date(time.getTime() - time.getTimezoneOffset() * 60000);
};
var viewModes = Object.freeze({
YEARS: "years",
MONTHS: "months",
DAYS: "days",
TIME: "time"
});
var allowedSetTime = Object.freeze({
HOURS: "hours",
MINUTES: "minutes",
SECONDS: "seconds",
MILLISECONDS: "milliseconds"
});
var DateTime = function (_Component) {
inherits(DateTime, _Component);
function DateTime(props) {
classCallCheck(this, DateTime);
var _this = possibleConstructorReturn(this, (DateTime.__proto__ || Object.getPrototypeOf(DateTime)).call(this, props));
_this.componentProps = {
fromProps: ["value", "isValidDate", "renderDay", "renderMonth", "renderYear", "timeConstraints", "locale"],
fromState: ["viewDate", "selectedDate", "updateOn"],
fromThis: ["setDate", "setTime", "showView", "addTime", "subtractTime", "updateSelectedDate", "handleClickOutside"]
};
_this.state = _this.getInitialState(props);
// Bind functions
_this.getInitialState = _this.getInitialState.bind(_this);
_this.parseDate = _this.parseDate.bind(_this);
_this.getStateFromProps = _this.getStateFromProps.bind(_this);
_this.getUpdateOn = _this.getUpdateOn.bind(_this);
_this.getFormats = _this.getFormats.bind(_this);
_this.onInputChange = _this.onInputChange.bind(_this);
_this.onInputKey = _this.onInputKey.bind(_this);
_this.showView = _this.showView.bind(_this);
_this.setDate = _this.setDate.bind(_this);
_this.subtractTime = _this.subtractTime.bind(_this);
_this.addTime = _this.addTime.bind(_this);
_this.updateTime = _this.updateTime.bind(_this);
_this.setTime = _this.setTime.bind(_this);
_this.updateSelectedDate = _this.updateSelectedDate.bind(_this);
_this.openCalendar = _this.openCalendar.bind(_this);
_this.closeCalendar = _this.closeCalendar.bind(_this);
_this.handleClickOutside = _this.handleClickOutside.bind(_this);
_this.getComponentProps = _this.getComponentProps.bind(_this);
_this.getFormatOptions = _this.getFormatOptions.bind(_this);
return _this;
}
createClass(DateTime, [{
key: "getInitialState",
value: function getInitialState(props) {
var state = this.getStateFromProps(props);
if (state.open === undefined) state.open = !props.input;
state.currentView = props.dateFormat ? props.viewMode || state.updateOn || viewModes.DAYS : viewModes.TIME;
return state;
}
}, {
key: "parseDate",
value: function parseDate(date, formats) {
if (date) {
var parsedDate = parse(date);
if (isDate(parsedDate) && isValidDate(parsedDate)) {
return parsedDate;
}
}
return undefined;
}
}, {
key: "getStateFromProps",
value: function getStateFromProps(props) {
var formats = this.getFormats(props);
var selectedDate = this.parseDate(props.value || props.defaultValue, formats);
var viewDate = this.parseDate(props.viewDate, formats);
viewDate = selectedDate ? startOfMonth(selectedDate) : viewDate ? startOfMonth(viewDate) : startOfMonth(new Date());
var updateOn = this.getUpdateOn(formats);
var inputValue = selectedDate ? format(selectedDate, formats.datetime, this.getFormatOptions()) : isDate(props.value) && isValidDate(props.value) ? format(props.value, formats.datetime, this.getFormatOptions()) : isDate(props.defaultValue) && isValidDate(props.defaultValue) ? format(props.defaultValue, formats.datetime, this.getFormatOptions()) : props.defaultValue || "";
return {
updateOn: updateOn,
inputFormat: formats.datetime,
viewDate: viewDate,
selectedDate: selectedDate,
inputValue: inputValue,
open: props.open
};
}
}, {
key: "getUpdateOn",
value: function getUpdateOn(formats) {
if (formats.date.match(/[lLD]/)) {
return viewModes.DAYS;
} else if (formats.date.indexOf("M") !== -1) {
return viewModes.MONTHS;
} else if (formats.date.indexOf("Y") !== -1) {
return viewModes.YEARS;
}
return viewModes.DAYS;
}
}, {
key: "getFormats",
value: function getFormats(props) {
var formats = {
date: props.dateFormat || "",
time: props.timeFormat || ""
};
if (formats.date === true) {
formats.date = "MM/DD/YYYY";
} else if (this.getUpdateOn(formats) !== viewModes.DAYS) {
formats.time = "";
}
if (formats.time === true) {
formats.time = "h:mm A";
}
formats.datetime = formats.date && formats.time ? formats.date + " " + formats.time : formats.date || formats.time;
return formats;
}
}, {
key: "UNSAFE_componentWillReceiveProps",
value: function UNSAFE_componentWillReceiveProps(nextProps) {
var formats = this.getFormats(nextProps);
var updatedState = {};
if (nextProps.value !== this.props.value || formats.datetime !== this.getFormats(this.props).datetime) {
updatedState = this.getStateFromProps(nextProps);
}
if (updatedState.open === undefined) {
if (typeof nextProps.open !== "undefined") {
updatedState.open = nextProps.open;
} else if (this.props.closeOnSelect && this.state.currentView !== viewModes.TIME) {
updatedState.open = false;
} else {
updatedState.open = this.state.open;
}
}
if (nextProps.viewMode !== this.props.viewMode) {
updatedState.currentView = nextProps.viewMode;
}
if (nextProps.locale !== this.props.locale) {
updatedState.locale = nextProps.locale;
if (this.state.viewDate) {
var updatedViewDate = this.state.viewDate;
updatedState.viewDate = updatedViewDate;
}
if (this.state.selectedDate) {
var updatedSelectedDate = this.state.selectedDate;
updatedState.selectedDate = updatedSelectedDate;
updatedState.inputValue = format(updatedSelectedDate, formats.datetime, this.getFormatOptions());
}
}
if (nextProps.utc !== this.props.utc) {
// Enabling UTC
if (nextProps.utc) {
if (this.state.viewDate) {
updatedState.viewDate = toUtc(this.state.viewDate);
}
if (this.state.selectedDate) {
updatedState.selectedDate = toUtc(this.state.selectedDate);
updatedState.inputValue = format(updatedState.selectedDate, formats.datetime, this.getFormatOptions());
}
}
// Disabling UTC
else {
if (this.state.viewDate) {
updatedState.viewDate = toUtc$1(this.state.viewDate);
}
if (this.state.selectedDate) {
updatedState.selectedDate = toUtc$1(this.state.selectedDate);
updatedState.inputValue = format(updatedState.selectedDate, formats.datetime, this.getFormatOptions());
}
}
}
if (nextProps.viewDate !== this.props.viewDate) {
updatedState.viewDate = parse(nextProps.viewDate);
}
this.setState(updatedState);
}
}, {