@demark-pro/react-booking-calendar
Version:
A responsive customizable React Booking calendar with overbooking protection
730 lines (711 loc) • 109 kB
JavaScript
/*!
@demark-pro/react-booking-calendar v4.0.3
undefined
Released under the MIT License.
*/
import React, { useState, memo, useEffect } from 'react';
import memoize from 'memoize-one';
import { areEqual, FixedSizeGrid } from 'react-window';
import AutoSizer from 'react-virtualized-auto-sizer';
var _assign = function __assign() {
_assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return _assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
}
function __spreadArray(to, from, pack) {
for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
var toDate = function (value) { return new Date(value); };
function formatDate(date, format, options) {
var _date = toDate(date);
return _date.toLocaleDateString(options === null || options === void 0 ? void 0 : options.locale, format);
}
function addDays(date, amount) {
var _date = toDate(date);
if (!amount)
return _date;
_date.setDate(_date.getDate() + amount);
return _date;
}
function addMonths(date, amount) {
var _date = toDate(date);
if (!amount)
return _date;
var dayOfMonth = _date.getDate();
var endOfDesiredMonth = _date;
endOfDesiredMonth.setMonth(_date.getMonth() + amount + 1, 0);
var daysInMonth = endOfDesiredMonth.getDate();
if (dayOfMonth >= daysInMonth) {
return endOfDesiredMonth;
}
else {
_date.setFullYear(endOfDesiredMonth.getFullYear(), endOfDesiredMonth.getMonth(), dayOfMonth);
return _date;
}
}
function startOfDay(date) {
var _date = toDate(date);
_date.setHours(0, 0, 0, 0);
return _date;
}
function endOfDay(date) {
var _date = toDate(date);
_date.setHours(23, 59, 59, 999);
return _date;
}
function isSameDay(dateLeft, dateRight) {
var dateLeftStartOfDay = startOfDay(dateLeft);
var dateRightStartOfDay = startOfDay(dateRight);
return +dateLeftStartOfDay === +dateRightStartOfDay;
}
function isSameMonth(dateLeft, dateRight) {
var _dateLeft = toDate(dateLeft);
var _dateRight = toDate(dateRight);
return (_dateLeft.getFullYear() === _dateRight.getFullYear() &&
_dateLeft.getMonth() === _dateRight.getMonth());
}
function isSameYear(dateLeft, dateRight) {
var _dateLeft = toDate(dateLeft);
var _dateRight = toDate(dateRight);
return _dateLeft.getFullYear() === _dateRight.getFullYear();
}
function isWeekend(date) {
var day = toDate(date).getDay();
return day === 0 || day === 6;
}
function isBefore(date, dateToCompare) {
var _date = toDate(date);
var _dateToCompare = toDate(dateToCompare);
return +_date < +_dateToCompare;
}
function isAfter(date, dateToCompare) {
var _date = toDate(date);
var _dateToCompare = toDate(dateToCompare);
return _date.getTime() > _dateToCompare.getTime();
}
function isEqual(leftDate, rightDate) {
var _dateLeft = toDate(leftDate);
var _dateRight = toDate(rightDate);
return +_dateLeft === +_dateRight;
}
function startOfWeek(date, options) {
var _a;
var weekStartsOn = (_a = options === null || options === void 0 ? void 0 : options.weekStartsOn) !== null && _a !== void 0 ? _a : 0;
var _date = toDate(date);
var day = _date.getDay();
var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;
_date.setDate(_date.getDate() - diff);
_date.setHours(0, 0, 0, 0);
return _date;
}
function endOfWeek(date, options) {
var _a;
var weekStartsOn = (_a = options === null || options === void 0 ? void 0 : options.weekStartsOn) !== null && _a !== void 0 ? _a : 0;
var _date = toDate(date);
var day = _date.getDay();
var diff = (day < weekStartsOn ? -7 : 0) + 6 - (day - weekStartsOn);
_date.setDate(_date.getDate() + diff);
_date.setHours(23, 59, 59, 999);
return _date;
}
function startOfMonth(date) {
var _date = toDate(date);
_date.setDate(1);
_date.setHours(0, 0, 0, 0);
return _date;
}
function endOfMonth(date) {
var _date = toDate(date);
var month = _date.getMonth();
_date.setFullYear(_date.getFullYear(), month + 1, 0);
_date.setHours(23, 59, 59, 999);
return _date;
}
var isBetween = function (date, from, to, inclusivity) {
if (inclusivity === void 0) { inclusivity = "()"; }
var isBeforeSome = inclusivity[0] === "{", isAfterSome = inclusivity[1] === "}", isBeforeEqual = inclusivity[0] === "[", isAfterEqual = inclusivity[1] === "]";
if (isBeforeSome || isAfterSome) {
return ((isBeforeSome
? isSameDay(from, date) || isBefore(from, date)
: isBefore(from, date)) &&
(isAfterSome
? isSameDay(to, date) || isAfter(to, date)
: isAfter(to, date)));
}
return ((isBeforeEqual
? isEqual(from, date) || isBefore(from, date)
: isBefore(from, date)) &&
(isAfterEqual ? isEqual(to, date) || isAfter(to, date) : isAfter(to, date)));
};
var isBetweenInterval = function (startDate, endDate, from, to, inclusivity) {
if (inclusivity === void 0) { inclusivity = "()"; }
return (isBetween(startDate, from, to, inclusivity) ||
isBetween(endDate, from, to, inclusivity));
};
function cn() {
var classes = [];
for (var _i = 0; _i < arguments.length; _i++) {
classes[_i] = arguments[_i];
}
return classes.filter(Boolean).join(" ");
}
function getAttributes(attributes) {
return Object.entries(attributes).reduce(function (a, _a) {
var _b;
var k = _a[0], v = _a[1];
return (!!v ? _assign(_assign({}, a), (_b = {}, _b[k] = true, _b)) : a);
}, {});
}
var getSelectedDates = function (selected) {
return selected
.map(function (s) { return (s ? new Date(s) : null); })
.concat(Array.from({ length: 2 - selected.length }, function () { return null; }));
};
var preProtection = function (date, state, commonProps) {
var protection = commonProps.protection, range = commonProps.range, isStart = commonProps.isStart, selected = commonProps.selected;
if (state.isDisabled || !!protection)
return null;
var startDate = selected[0], endDate = selected[1];
if (range)
return startDate ? [startDate, date] : [date];
return isStart ? [date, endDate] : [startDate, date];
};
var createMonthDays = memoize(function (_a) {
var dateOfMonth = _a.dateOfMonth, options = _a.options;
var days = [];
var monthStart = startOfMonth(dateOfMonth);
var monthEnd = endOfMonth(dateOfMonth);
var weekStart = startOfWeek(monthStart, options);
var weekEnd = endOfWeek(monthEnd, options);
var day = weekStart;
while (day <= weekEnd) {
var cloneDay = day;
days.push({ date: cloneDay, monthStartDate: monthStart });
day = addDays(cloneDay, 1);
}
return days;
});
var createScrollableDays = memoize(function (_a) {
var dateOfMonth = _a.dateOfMonth, options = _a.options, _b = _a.monthsCount, monthsCount = _b === void 0 ? 6 : _b;
var days = [];
var _loop_1 = function (i) {
var currentMonth = addMonths(dateOfMonth, +i);
var monthDays = createMonthDays({
dateOfMonth: currentMonth,
options: options,
});
var rowFiller = Array.from({ length: 7 }).map(function () { return ({
date: currentMonth,
monthStartDate: currentMonth,
isMonthRow: true,
}); });
days = __spreadArray(__spreadArray(__spreadArray([], days, true), rowFiller, true), monthDays);
};
for (var i in Array.from({ length: monthsCount })) {
_loop_1(i);
}
return days;
});
var getDayState = function (_a) {
var day = _a.day, _b = _a.selected, selected = _b === void 0 ? [] : _b, _c = _a.reserved, reserved = _c === void 0 ? [] : _c, _d = _a.disabled, disabled = _d === void 0 ? false : _d;
var date = day.date, monthStartDate = day.monthStartDate;
var today = new Date();
var state = {};
state.isDisabled =
typeof disabled === "function" ? disabled(date, state) : disabled;
state.isSameYear = date.getFullYear() === today.getFullYear();
state.isSameMonth = isSameMonth(date, monthStartDate);
state.isStartMonth = isSameDay(date, startOfMonth(date));
state.isEndMonth = isSameDay(date, endOfMonth(date));
state.isToday = isSameDay(date, today);
state.isPast = date.getTime() - today.getTime() < 0;
state.isSelectedStart = selected[0] ? isSameDay(date, selected[0]) : false;
state.isSelectedEnd = selected[1] ? isSameDay(date, selected[1]) : false;
state.isSelected = !!(selected[0] &&
selected[1] &&
isBetween(date, selected[0], selected[1], "{}"));
state.isReserved = !!reserved.find(function (r) {
return isBetween(endOfDay(date), r.startDate, r.endDate, "{}") &&
isBetween(startOfDay(date), r.startDate, r.endDate, "{}");
});
state.isAvailable = !!reserved.find(function (r) {
return !isBetween(endOfDay(date), r.startDate, r.endDate, "[]") ||
!isBetween(startOfDay(date), r.startDate, r.endDate, "[]");
});
state.isReservedStart = !!reserved.find(function (r) { return isSameDay(r.startDate, date); });
state.isReservedEnd = !!reserved.find(function (r) { return isSameDay(r.endDate, date); });
return state;
};
function getDayAttributes(state, options) {
if (!options || !options.useAttributes)
return {};
var attributes = {};
if (state.isSelected || state.isSelectedStart || state.isSelectedEnd)
attributes["data-selected"] = true;
if (state.isSelectedStart)
attributes["data-selected-start"] = true;
if (state.isSelectedEnd)
attributes["data-selected-end"] = true;
if (state.isReserved)
attributes["data-reserved"] = true;
if (state.isReservedStart)
attributes["data-reserved-start"] = true;
if (state.isReservedEnd)
attributes["data-reserved-end"] = true;
if (state.isPast)
attributes["data-past"] = true;
if (state.isToday)
attributes["data-today"] = true;
return attributes;
}
function isNumeric(value) {
return typeof value === "number";
}
var CalendarContainer = function (props) {
var getClassNames = props.getClassNames, children = props.children, innerProps = props.innerProps;
var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, isScrollable = _a.isScrollable, _b = _a.className, className = _b === void 0 ? "" : _b, restInner = __rest(_a, ["isScrollable", "className"]);
var classNames = getClassNames("CalendarContainer", className);
return (React.createElement("div", _assign({ className: classNames }, getAttributes({ "data-scrollable": !!isScrollable }), restInner), children));
};
var MonthContainer = function (props) {
var children = props.children, innerProps = props.innerProps, getClassNames = props.getClassNames;
return (React.createElement("div", _assign({ className: getClassNames("MonthContainer") }, innerProps), children));
};
var WeekContainer = function (props) {
var getClassNames = props.getClassNames, children = props.children;
return React.createElement("div", { className: getClassNames("WeekContainer") }, children);
};
var DaysContainer = function (props) {
var getClassNames = props.getClassNames, children = props.children;
return (React.createElement("div", { role: "listbox", className: getClassNames("DaysContainer") }, children));
};
var DayContainer = function (props) {
var date = props.date, state = props.state, innerProps = props.innerProps, children = props.children, getClassNames = props.getClassNames, options = props.options;
var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, onClick = _a.onClick, restInner = __rest(_a, ["onClick"]);
var attributes = getAttributes({
"data-selected": !!state.isSelected || !!state.isSelectedStart || !!state.isSelectedEnd,
"data-reserved": !!state.isReserved,
"data-past": !!state.isPast,
"data-start-month": !!state.isStartMonth,
"data-end-month": !!state.isEndMonth,
});
return (React.createElement("div", _assign({ "aria-label": formatDate(date, {}, options), role: "option", tabIndex: -1, className: getClassNames("DayContainer"), onClick: function () { return onClick && onClick(date, state); } }, attributes, restInner), children));
};
var MonthArrowBack = function (props) {
var innerProps = props.innerProps, getClassNames = props.getClassNames;
return (React.createElement("button", _assign({ type: "button", className: getClassNames("MonthArrowBack"), "aria-label": "Previous Month" }, innerProps),
React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24" },
React.createElement("path", { d: "M14 17a1 1 0 0 1-.707-.293l-4-4a1 1 0 0 1 0-1.414l4-4a1 1 0 1 1 1.414 1.414L11.414 12l3.293 3.293A1 1 0 0 1 14 17z" }))));
};
var MonthArrowNext = function (props) {
var innerProps = props.innerProps, getClassNames = props.getClassNames;
return (React.createElement("button", _assign({ type: "button", "aria-label": "Next Month", className: getClassNames("MonthArrowNext") }, innerProps),
React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24" },
React.createElement("path", { d: "M14 17a1 1 0 0 1-.707-.293l-4-4a1 1 0 0 1 0-1.414l4-4a1 1 0 1 1 1.414 1.414L11.414 12l3.293 3.293A1 1 0 0 1 14 17z" }))));
};
var MonthContent = function (props) {
var year = props.year, month = props.month, options = props.options, innerProps = props.innerProps, getClassNames = props.getClassNames;
var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}; _a.isScrollable; var restInner = __rest(_a, ["isScrollable"]);
var date = new Date(year, month);
var monthContent = formatDate(date, { month: "long" }, options);
var attributes = getAttributes({
"data-some-month": isSameMonth(date, new Date()),
"data-some-year": isSameYear(date, new Date()),
});
return (React.createElement("div", _assign({ className: getClassNames("MonthContent") }, attributes, restInner),
React.createElement("span", null, monthContent),
React.createElement("span", null, year)));
};
var WeekContent = function (props) {
var day = props.day, options = props.options, innerProps = props.innerProps, getClassNames = props.getClassNames;
var startDate = startOfWeek(new Date(), options);
var date = addDays(startDate, day);
return (React.createElement("div", _assign({ className: getClassNames("WeekContent") }, getAttributes({ "data-weekend": isWeekend(date) }), innerProps), formatDate(date, { weekday: "short" }, options)));
};
var DayContent = function (props) {
var children = props.children, innerProps = props.innerProps, state = props.state, options = props.options, getClassNames = props.getClassNames;
return (React.createElement("div", _assign({ className: getClassNames("DayContent") }, getDayAttributes(state, options), innerProps), children));
};
var DaySelection = function (props) {
var innerProps = props.innerProps, state = props.state, options = props.options, getClassNames = props.getClassNames;
if (!isShow$1(state))
return null;
return (React.createElement("div", _assign({ className: getClassNames("DaySelection") }, getDayAttributes(state, options), innerProps)));
};
var isShow$1 = function (state) {
return state.isSelected || state.isSelectedStart || state.isSelectedEnd;
};
var DayToday = function (props) {
var innerProps = props.innerProps, state = props.state, getClassNames = props.getClassNames;
if (!state.isToday)
return null;
return React.createElement("div", _assign({ className: getClassNames("DayToday") }, innerProps));
};
var DayReservation = function (props) {
var innerProps = props.innerProps, state = props.state, getClassNames = props.getClassNames;
if (!isShow(state))
return null;
return React.createElement("div", _assign({ className: getClassNames("DayReservation") }, innerProps));
};
var isShow = function (state) {
return state.isReserved || state.isReservedStart || state.isReservedEnd;
};
var componentClasses = {
CalendarContainer: "calendar-container",
MonthContainer: "month-container",
MonthContent: "month-content",
MonthArrowBack: "month-arrow-back",
MonthArrowNext: "month-arrow-next",
WeekContainer: "week-container",
WeekContent: "week-content",
DaysContainer: "days-container",
DayContainer: "day-container",
DayContent: "day-content",
DaySelection: "day-selection",
DayReservation: "day-reservation",
DayToday: "day-today",
};
var components = {
CalendarContainer: CalendarContainer,
MonthContainer: MonthContainer,
MonthContent: MonthContent,
MonthArrowBack: MonthArrowBack,
MonthArrowNext: MonthArrowNext,
WeekContainer: WeekContainer,
WeekContent: WeekContent,
DaysContainer: DaysContainer,
DayContainer: DayContainer,
DayContent: DayContent,
DaySelection: DaySelection,
DayReservation: DayReservation,
DayToday: DayToday,
};
var defaultComponents = function (componentsByProps) {
if (componentsByProps === void 0) { componentsByProps = {}; }
return (_assign(_assign({}, components), componentsByProps));
};
var selectedInit = [null, null];
var isStartInit = true;
var reservedInit = [];
var rangeInit = false;
var disabledInit = false;
var monthInit = new Date().getMonth();
var yearInit = new Date().getFullYear();
var getProtectedTime = function (date, reserved) {
var initTime = {
// startDate: startOfDay(date),
// endDate: endOfDay(date),
startDate: date,
endDate: date,
};
var reserveEnd = reserved.find(function (d) { return isSameDay(d.endDate, date); });
var reserveStart = reserved.find(function (d) { return isSameDay(d.startDate, date); });
if (reserveEnd)
initTime.startDate = new Date(reserveEnd.endDate);
if (reserveStart)
initTime.endDate = new Date(reserveStart.startDate);
console.log(initTime);
return initTime;
};
function getProtectedInterval(date, state, commonProps) {
var selected = commonProps.selected, reserved = commonProps.reserved, range = commonProps.range;
var validate = validateBooking(date, state, commonProps);
if (validate)
return validate;
var startDate = selected[0], endDate = selected[1];
var isStart = range ? !startDate : commonProps.isStart;
var freeTime = getProtectedTime(date, reserved);
var newStart = isStart
? isSameDay(date, new Date())
? new Date()
: freeTime.startDate
: startDate;
var newEnd = !isStart ? freeTime.endDate : endDate;
var interval = [newStart || null, newEnd || null];
return { overbookType: null, interval: interval };
}
var validateBooking = function (date, state, commonProps) {
var selected = commonProps.selected, reserved = commonProps.reserved, range = commonProps.range;
var startDate = selected[0], endDate = selected[1];
var isStart = range ? !startDate : commonProps.isStart;
var interval = [getProtectedTime(date, reserved).startDate];
// if "PAST"
if (state.isPast)
return { overbookType: "PAST", interval: null };
// if reserved between
if (!state.isAvailable)
return { overbookType: "BOOKED", interval: null };
// if selected length 0 or 2 then set selected date
if (range && ((!startDate && !endDate) || (startDate && endDate))) {
return { overbookType: null, interval: interval };
}
if (isStart) {
// if selected start date after end date
if (endDate && isBefore(endDate, date)) {
return {
overbookType: "AFTER_END",
interval: range ? interval : null,
};
}
}
else {
// if selected end date before start date
if (startDate && isBefore(date, startDate)) {
return {
overbookType: "BEFORE_START",
interval: range ? interval : null,
};
}
}
var isReservedBetween = startDate &&
reserved.find(function (r) {
return isBetweenInterval(r.startDate, r.endDate, startDate, startOfDay(date));
});
// if booked beetwen start date and current date
if (isReservedBetween) {
return {
overbookType: "BOOKED_BETWEEN",
interval: range || isStart ? interval : null,
};
}
return null;
};
function Calendar(props) {
var _a = props.selected, selected = _a === void 0 ? selectedInit : _a, _b = props.isStart, isStart = _b === void 0 ? isStartInit : _b; props.initialDate; var _d = props.reserved, reserved = _d === void 0 ? reservedInit : _d, _e = props.range, range = _e === void 0 ? rangeInit : _e, _f = props.protection, protection = _f === void 0 ? true : _f, _g = props.disabled, disabled = _g === void 0 ? disabledInit : _g, month = props.month, year = props.year, _h = props.components, components = _h === void 0 ? {} : _h, _j = props.classNames, classNames = _j === void 0 ? {} : _j, _k = props.options, options = _k === void 0 ? {} : _k, onOverbook = props.onOverbook, onChange = props.onChange, onMonthChange = props.onMonthChange, onYearChange = props.onYearChange, innerProps = __rest(props, ["selected", "isStart", "initialDate", "reserved", "range", "protection", "disabled", "month", "year", "components", "classNames", "options", "onOverbook", "onChange", "onMonthChange", "onYearChange"]);
var _l = useState(monthInit), activeMonth = _l[0], setActiveMonth = _l[1];
var _m = useState(yearInit), activeYear = _m[0], setActiveYear = _m[1];
var currentMonth = isNumeric(month) ? month : activeMonth;
var currentYear = isNumeric(year) ? year : activeYear;
var isControled = isNumeric(month) || isNumeric(year);
var _o = getSelectedDates(selected), startDate = _o[0], endDate = _o[1];
// ==============================
// getClassNames
// ==============================
var getClassNames = function (name, classes) {
var defaultClass = "calendar__".concat(componentClasses[name]);
var propsClasses = classNames[name];
return cn(defaultClass, propsClasses, classes);
};
// ==============================
// commonProps
// ==============================
var commonProps = {
selected: [startDate, endDate],
reserved: reserved,
disabled: disabled,
protection: protection,
range: range,
isStart: isStart,
options: options,
getClassNames: getClassNames,
};
// ==============================
// handleMonthChange
// ==============================
var handleChangeMonth = function (value) {
var _a = getMonthYear(value, currentYear), newMonth = _a[0], newYear = _a[1];
if (onMonthChange) {
onMonthChange(newMonth, newYear !== null && newYear !== void 0 ? newYear : currentYear);
if (newYear && onYearChange)
onYearChange(newYear);
if (isControled)
return;
}
setActiveMonth(newMonth);
if (newYear)
setActiveYear(newYear);
};
// ==============================
// handleClickDay
// ==============================
var handleClickDay = function (date, state) {
var preSelected = preProtection(date, state, commonProps);
if (preSelected !== null) {
if (onChange)
onChange(preSelected);
return;
}
var _a = getProtectedInterval(date, state, commonProps), interval = _a.interval, overbookType = _a.overbookType;
if (overbookType && !interval) {
if (onOverbook)
onOverbook(date, overbookType);
return;
}
if (interval && onChange)
onChange(interval);
return;
};
// ==============================
// Import components
// ==============================
var _p = defaultComponents(components), CalendarContainer = _p.CalendarContainer, MonthContainer = _p.MonthContainer, MonthArrowBack = _p.MonthArrowBack, MonthArrowNext = _p.MonthArrowNext, MonthContent = _p.MonthContent, WeekContainer = _p.WeekContainer, WeekContent = _p.WeekContent, DaysContainer = _p.DaysContainer, DayContainer = _p.DayContainer, DayContent = _p.DayContent, DaySelection = _p.DaySelection, DayReservation = _p.DayReservation, DayToday = _p.DayToday;
var startMonth = new Date(currentYear, currentMonth);
var days = createMonthDays({ dateOfMonth: startMonth, options: options });
return (React.createElement(CalendarContainer, _assign({}, commonProps, { innerProps: _assign({}, innerProps) }),
React.createElement(MonthContainer, _assign({}, commonProps),
React.createElement(MonthArrowBack, _assign({}, commonProps, { innerProps: {
onClick: function () {
return handleChangeMonth((currentMonth - 1));
},
} })),
React.createElement(MonthContent, _assign({ month: currentMonth, year: currentYear }, commonProps)),
React.createElement(MonthArrowNext, _assign({}, commonProps, { innerProps: {
onClick: function () {
return handleChangeMonth((currentMonth + 1));
},
} }))),
React.createElement(WeekContainer, _assign({}, commonProps), Array.from({ length: 7 }).map(function (_, key) { return (React.createElement(WeekContent, _assign({ key: "calendar_week_container_".concat(key), day: key }, commonProps, { innerProps: {} }))); })),
React.createElement(DaysContainer, _assign({}, commonProps), days.map(function (day, key) {
var dayProps = {
date: day.date,
state: getDayState({ day: day, selected: selected, reserved: reserved, disabled: disabled }),
};
return (React.createElement(DayContainer, _assign({ key: "calendar_day_container_".concat(key), innerProps: { onClick: handleClickDay } }, dayProps, commonProps),
React.createElement(DayContent, _assign({}, dayProps, commonProps), day.date.getDate()),
React.createElement(DayToday, _assign({}, dayProps, commonProps)),
React.createElement(DaySelection, _assign({}, dayProps, commonProps)),
React.createElement(DayReservation, _assign({}, dayProps, commonProps))));
}))));
}
var getMonthYear = function (newMonth, year) {
var month = newMonth;
var newYear = null;
if (newMonth > 11) {
month = 0;
newYear = year + 1;
}
if (newMonth < 0) {
month = 11;
newYear = year - 1;
}
return [month, newYear];
};
// ==============================
// Cell
// ==============================
var Cell = memo(function (_a) {
var columnIndex = _a.columnIndex, rowIndex = _a.rowIndex, style = _a.style, data = _a.data;
var days = data.days, components = data.components, commonProps = data.commonProps, onChange = data.onChange, onOverbook = data.onOverbook;
var selected = commonProps.selected, reserved = commonProps.reserved, disabled = commonProps.disabled;
var MonthContainer = components.MonthContainer, MonthContent = components.MonthContent, DayContainer = components.DayContainer, DayContent = components.DayContent, DayToday = components.DayToday, DaySelection = components.DaySelection, DayReservation = components.DayReservation;
var dayIndex = rowIndex * 7 + columnIndex;
var day = days[dayIndex];
if (!day)
return null;
var date = day.date;
var state = getDayState({ day: day, selected: selected, reserved: reserved, disabled: disabled });
var handleClickDay = function () {
var preSelected = preProtection(date, state, commonProps);
if (preSelected !== null) {
if (onChange)
onChange(preSelected);
return;
}
var _a = getProtectedInterval(date, state, commonProps), interval = _a.interval, overbookType = _a.overbookType;
if (overbookType && !interval) {
if (onOverbook)
onOverbook(date, overbookType);
return;
}
if (interval && onChange)
onChange(interval);
};
if (day.isMonthRow) {
if (columnIndex !== 3)
return null;
return (React.createElement(MonthContainer, _assign({}, commonProps, { innerProps: { style: style } }),
React.createElement(MonthContent, _assign({ month: day.date.getMonth(), year: day.date.getFullYear() }, commonProps, { innerProps: { isScrollable: true } }))));
}
var dayProps = { date: day.date, state: state };
return (React.createElement(DayContainer, _assign({ innerProps: { style: style, onClick: handleClickDay } }, dayProps, commonProps), state.isSameMonth && (React.createElement(React.Fragment, null,
React.createElement(DayContent, _assign({}, dayProps, commonProps), formatDate(day.date, { day: "numeric" })),
React.createElement(DayToday, _assign({}, dayProps, { state: state }, commonProps)),
React.createElement(DaySelection, _assign({}, dayProps, { state: state }, commonProps)),
React.createElement(DayReservation, _assign({}, dayProps, { state: state }, commonProps))))));
}, areEqual);
var Grid = function (_a) {
var width = _a.width, height = _a.height, colHeight = _a.colHeight, items = _a.items, initialScroll = _a.initialScroll, components = _a.components, commonProps = _a.commonProps, isStart = _a.isStart, range = _a.range, onOverbook = _a.onOverbook, onScroll = _a.onScroll, onChange = _a.onChange, props = __rest(_a, ["width", "height", "colHeight", "items", "initialScroll", "components", "commonProps", "isStart", "range", "onOverbook", "onScroll", "onChange"]);
useEffect(function () { }, [items, initialScroll]);
return (React.createElement(FixedSizeGrid, _assign({ height: height, width: width, columnCount: 7, columnWidth: width / 7, rowCount: items.length / 7, rowHeight: colHeight, overscanRowCount: 4, initialScrollTop: getInitialScroll(colHeight, items, initialScroll), itemData: {
days: items,
commonProps: commonProps,
components: components,
isStart: isStart,
range: range,
onOverbook: onOverbook,
onChange: onChange,
}, onScroll: onScroll }, props), Cell));
};
var ScrollableCalendar = function (props) {
var _a = props.startMonth, startMonth = _a === void 0 ? new Date() : _a, _b = props.selected, selected = _b === void 0 ? selectedInit : _b, _c = props.reserved, reserved = _c === void 0 ? reservedInit : _c, _d = props.components, components = _d === void 0 ? {} : _d, _e = props.classNames, classNames = _e === void 0 ? {} : _e, _f = props.isStart, isStart = _f === void 0 ? isStartInit : _f, _g = props.range, range = _g === void 0 ? rangeInit : _g, _h = props.disabled, disabled = _h === void 0 ? disabledInit : _h, _j = props.protection, protection = _j === void 0 ? false : _j, initialScroll = props.initialScroll, _k = props.monthsCount, monthsCount = _k === void 0 ? 6 : _k, _l = props.colHeight, colHeight = _l === void 0 ? 55 : _l, _m = props.options, options = _m === void 0 ? {} : _m, onOverbook = props.onOverbook, onChange = props.onChange, onScroll = props.onScroll, innerProps = __rest(props, ["startMonth", "selected", "reserved", "components", "classNames", "isStart", "range", "disabled", "protection", "initialScroll", "monthsCount", "colHeight", "options", "onOverbook", "onChange", "onScroll"]);
var _o = getSelectedDates(selected), startDate = _o[0], endDate = _o[1];
// ==============================
// getClassNames
// ==============================
var getClassNames = function (compName, classes) {
var defaultClass = "calendar__".concat(componentClasses[compName]);
var propsClasses = classNames[compName];
return cn(defaultClass, propsClasses, classes);
};
var commonProps = {
selected: [startDate, endDate],
reserved: reserved,
disabled: disabled,
protection: protection,
range: range,
isStart: isStart,
options: options,
getClassNames: getClassNames,
};
var calendarComponents = defaultComponents(components);
var CalendarContainer = calendarComponents.CalendarContainer, WeekContainer = calendarComponents.WeekContainer, WeekContent = calendarComponents.WeekContent, DaysContainer = calendarComponents.DaysContainer;
var items = createScrollableDays({
dateOfMonth: startMonth,
monthsCount: monthsCount,
options: options,
});
return (React.createElement(CalendarContainer, _assign({}, commonProps, { innerProps: _assign(_assign({}, innerProps), { isScrollable: true }) }),
React.createElement(WeekContainer, _assign({ innerProps: {} }, commonProps), Array.from({ length: 7 }).map(function (_, key) { return (React.createElement(WeekContent, _assign({ key: "scrollable_calendar_week_container_".concat(key), day: key }, commonProps, { innerProps: {} }))); })),
React.createElement(DaysContainer, _assign({}, commonProps),
React.createElement(AutoSizer, null, function (_a) {
var height = _a.height, width = _a.width;
return (React.createElement(Grid, { height: height, width: width, items: items, colHeight: colHeight, initialScroll: initialScroll, components: calendarComponents, commonProps: commonProps, isStart: isStart, range: range, onScroll: onScroll, onOverbook: onOverbook, onChange: onChange }));
}))));
};
var getInitialScroll = function (colHeight, days, initialScroll) {
if (!days || days.length === 0 || !initialScroll)
return;
var rows = 0;
for (var key in days) {
var day = days[key];
if (+key !== 0 && +key % 7 === 0)
rows++;
if (isSameDay(day.date, initialScroll)) {
if (day.date.getDate() === 1)
rows--;
break;
}
}
return rows * colHeight;
};
export { Calendar, ScrollableCalendar, getProtectedInterval, getProtectedTime };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzIjpbIi4uLy4uL25vZGVfbW9kdWxlcy90c2xpYi90c2xpYi5lczYuanMiLCIuLi8uLi9zcmMvdXRpbHMvZGF0ZS51dGlscy50cyIsIi4uLy4uL3NyYy9oZWxwZXJzLnRzIiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvY29udGFpbmVycy50c3giLCIuLi8uLi9zcmMvY29tcG9uZW50cy9Nb250aEFycm93QmFjay50c3giLCIuLi8uLi9zcmMvY29tcG9uZW50cy9Nb250aEFycm93TmV4dC50c3giLCIuLi8uLi9zcmMvY29tcG9uZW50cy9Nb250aENvbnRlbnQudHN4IiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvV2Vla0NvbnRlbnQudHN4IiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvRGF5Q29udGVudC50c3giLCIuLi8uLi9zcmMvY29tcG9uZW50cy9EYXlTZWxlY3Rpb24udHN4IiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvRGF5VG9kYXkudHN4IiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvRGF5UmVzZXJ2YXRpb24udHN4IiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvaW5kZXgudHMiLCIuLi8uLi9zcmMvY29uc3RhbnRzLnRzIiwiLi4vLi4vc3JjL3V0aWxzL2dldC1wcm90ZWN0ZWQtdGltZS50c3giLCIuLi8uLi9zcmMvdXRpbHMvZ2V0LXByb3RlY3RlZC1pbnRlcnZhbC50cyIsIi4uLy4uL3NyYy9jYWxlbmRhci50c3giLCIuLi8uLi9zcmMvc2Nyb2xsYWJsZS1jYWxlbmRhci50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxyXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMCAmJiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwocywgcFtpXSkpXHJcbiAgICAgICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgICAgICB9XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcclxuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3BhcmFtKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2VzRGVjb3JhdGUoY3RvciwgZGVzY3JpcHRvckluLCBkZWNvcmF0b3JzLCBjb250ZXh0SW4sIGluaXRpYWxpemVycywgZXh0cmFJbml0aWFsaXplcnMpIHtcclxuICAgIGZ1bmN0aW9uIGFjY2VwdChmKSB7IGlmIChmICE9PSB2b2lkIDAgJiYgdHlwZW9mIGYgIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkZ1bmN0aW9uIGV4cGVjdGVkXCIpOyByZXR1cm4gZjsgfVxyXG4gICAgdmFyIGtpbmQgPSBjb250ZXh0SW4ua2luZCwga2V5ID0ga2luZCA9PT0gXCJnZXR0ZXJcIiA/IFwiZ2V0XCIgOiBraW5kID09PSBcInNldHRlclwiID8gXCJzZXRcIiA6IFwidmFsdWVcIjtcclxuICAgIHZhciB0YXJnZXQgPSAhZGVzY3JpcHRvckluICYmIGN0b3IgPyBjb250ZXh0SW5bXCJzdGF0aWNcIl0gPyBjdG9yIDogY3Rvci5wcm90b3R5cGUgOiBudWxsO1xyXG4gICAgdmFyIGRlc2NyaXB0b3IgPSBkZXNjcmlwdG9ySW4gfHwgKHRhcmdldCA/IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBjb250ZXh0SW4ubmFtZSkgOiB7fSk7XHJcbiAgICB2YXIgXywgZG9uZSA9IGZhbHNlO1xyXG4gICAgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgICB2YXIgY29udGV4dCA9IHt9O1xyXG4gICAgICAgIGZvciAodmFyIHAgaW4gY29udGV4dEluKSBjb250ZXh0W3BdID0gcCA9PT0gXCJhY2Nlc3NcIiA/IHt9IDogY29udGV4dEluW3BdO1xyXG4gICAgICAgIGZvciAodmFyIHAgaW4gY29udGV4dEluLmFjY2VzcykgY29udGV4dC5hY2Nlc3NbcF0gPSBjb250ZXh0SW4uYWNjZXNzW3BdO1xyXG4gICAgICAgIGNvbnRleHQuYWRkSW5pdGlhbGl6ZXIgPSBmdW5jdGlvbiAoZikgeyBpZiAoZG9uZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBhZGQgaW5pdGlhbGl6ZXJzIGFmdGVyIGRlY29yYXRpb24gaGFzIGNvbXBsZXRlZFwiKTsgZXh0cmFJbml0aWFsaXplcnMucHVzaChhY2NlcHQoZiB8fCBudWxsKSk7IH07XHJcbiAgICAgICAgdmFyIHJlc3VsdCA9ICgwLCBkZWNvcmF0b3JzW2ldKShraW5kID09PSBcImFjY2Vzc29yXCIgPyB7IGdldDogZGVzY3JpcHRvci5nZXQsIHNldDogZGVzY3JpcHRvci5zZXQgfSA6IGRlc2NyaXB0b3Jba2V5XSwgY29udGV4dCk7XHJcbiAgICAgICAgaWYgKGtpbmQgPT09IFwiYWNjZXNzb3JcIikge1xyXG4gICAgICAgICAgICBpZiAocmVzdWx0ID09PSB2b2lkIDApIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsIHx8IHR5cGVvZiByZXN1bHQgIT09IFwib2JqZWN0XCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJPYmplY3QgZXhwZWN0ZWRcIik7XHJcbiAgICAgICAgICAgIGlmIChfID0gYWNjZXB0KHJlc3VsdC5nZXQpKSBkZXNjcmlwdG9yLmdldCA9IF87XHJcbiAgICAgICAgICAgIGlmIChfID0gYWNjZXB0KHJlc3VsdC5zZXQpKSBkZXNjcmlwdG9yLnNldCA9IF87XHJcbiAgICAgICAgICAgIGlmIChfID0gYWNjZXB0KHJlc3VsdC5pbml0KSkgaW5pdGlhbGl6ZXJzLnB1c2goXyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKF8gPSBhY2NlcHQocmVzdWx0KSkge1xyXG4gICAgICAgICAgICBpZiAoa2luZCA9PT0gXCJmaWVsZFwiKSBpbml0aWFsaXplcnMucHVzaChfKTtcclxuICAgICAgICAgICAgZWxzZSBkZXNjcmlwdG9yW2tleV0gPSBfO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGlmICh0YXJnZXQpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGNvbnRleHRJbi5uYW1lLCBkZXNjcmlwdG9yKTtcclxuICAgIGRvbmUgPSB0cnVlO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcnVuSW5pdGlhbGl6ZXJzKHRoaXNBcmcsIGluaXRpYWxpemVycywgdmFsdWUpIHtcclxuICAgIHZhciB1c2VWYWx1ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAyO1xyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbml0aWFsaXplcnMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICB2YWx1ZSA9IHVzZVZhbHVlID8gaW5pdGlhbGl6ZXJzW2ldLmNhbGwodGhpc0FyZywgdmFsdWUpIDogaW5pdGlhbGl6ZXJzW2ldLmNhbGwodGhpc0FyZyk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdXNlVmFsdWUgPyB2YWx1ZSA6IHZvaWQgMDtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Byb3BLZXkoeCkge1xyXG4gICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN5bWJvbFwiID8geCA6IFwiXCIuY29uY2F0KHgpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc2V0RnVuY3Rpb25OYW1lKGYsIG5hbWUsIHByZWZpeCkge1xyXG4gICAgaWYgKHR5cGVvZiBuYW1lID09PSBcInN5bWJvbFwiKSBuYW1lID0gbmFtZS5kZXNjcmlwdGlvbiA/IFwiW1wiLmNvbmNhdChuYW1lLmRlc2NyaXB0aW9uLCBcIl1cIikgOiBcIlwiO1xyXG4gICAgcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShmLCBcIm5hbWVcIiwgeyBjb25maWd1cmFibGU6IHRydWUsIHZhbHVlOiBwcmVmaXggPyBcIlwiLmNvbmNhdChwcmVmaXgsIFwiIFwiLCBuYW1lKSA6IG5hbWUgfSk7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSkge1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0Lm1ldGFkYXRhID09PSBcImZ1bmN0aW9uXCIpIHJldHVybiBSZWZsZWN0Lm1ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXRlcih0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcclxuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxyXG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XHJcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XHJcbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2dlbmVyYXRvcih0aGlzQXJnLCBib2R5KSB7XHJcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xyXG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fY3JlYXRlQmluZGluZyA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcclxuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XHJcbiAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XHJcbiAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xyXG4gICAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XHJcbiAgICB9XHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xyXG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIG9bazJdID0gbVtrXTtcclxufSk7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIG8pIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobywgcCkpIF9fY3JlYXRlQmluZGluZyhvLCBtLCBwKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBzID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIFN5bWJvbC5pdGVyYXRvciwgbSA9IHMgJiYgb1tzXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAg