UNPKG

@demark-pro/react-booking-calendar

Version:

A responsive customizable React Booking calendar with overbooking protection

1,130 lines (1,108 loc) 139 kB
/*! @demark-pro/react-booking-calendar v4.0.5 undefined Released under the MIT License. */ 'use strict'; var React = require('react'); var memoize = require('memoize-one'); var reactWindow = require('react-window'); var AutoSizer = require('react-virtualized-auto-sizer'); function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; } var React__default = /*#__PURE__*/_interopDefaultCompat(React); var memoize__default = /*#__PURE__*/_interopDefaultCompat(memoize); var AutoSizer__default = /*#__PURE__*/_interopDefaultCompat(AutoSizer); 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) { if (pack || arguments.length === 2) 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)); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; var toDate = function toDate(value) { return new Date(value); }; var getGregorianFormat = function getGregorianFormat(format) { return _assign(_assign({}, format), { calendar: "gregory" }); }; function formatDate(date, format, options) { var _date = toDate(date); return _date.toLocaleDateString(options === null || options === void 0 ? void 0 : options.locale, getGregorianFormat(format)); } function formatNumber(value, options) { var locale = options === null || options === void 0 ? void 0 : options.locale; return new Intl.NumberFormat(locale, { useGrouping: false }).format(value); } function formatDay(date, options) { return formatNumber(toDate(date).getDate(), options); } function formatMonthYear(date, options) { return formatDate(date, { month: "long", year: "numeric" }, options); } 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 isBetween(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 isBetweenInterval(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(function (className) { return typeof className === "string" && className.length > 0; }).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 getSelectedDates(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 preProtection(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__default.default(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__default.default(function (_a) { var dateOfMonth = _a.dateOfMonth, options = _a.options, _b = _a.monthsCount, monthsCount = _b === void 0 ? 6 : _b; var days = []; var _loop_1 = function _loop_1(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, true); }; for (var i in Array.from({ length: monthsCount })) { _loop_1(i); } return days; }); var getDayState = function getDayState(_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 dayStart = startOfDay(date); var dayEnd = endOfDay(date); var todayStart = startOfDay(today); var state = {}; 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 = dayStart.getTime() < todayStart.getTime(); 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.some(function (r) { return isBetween(dayEnd, r.startDate, r.endDate, "{}") && isBetween(dayStart, r.startDate, r.endDate, "{}"); }); state.isAvailable = !state.isReserved; state.isReservedStart = reserved.some(function (r) { return isSameDay(r.startDate, date); }); state.isReservedEnd = reserved.some(function (r) { return isSameDay(r.endDate, date); }); state.isDisabled = typeof disabled === "function" ? disabled(date, state) : disabled; 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 CalendarContainer(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 /*#__PURE__*/React__default.default.createElement("div", _assign({ className: classNames }, getAttributes({ "data-scrollable": !!isScrollable }), restInner), children); }; var MonthContainer = function MonthContainer(props) { var children = props.children, innerProps = props.innerProps, getClassNames = props.getClassNames; var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, _b = _a.className, className = _b === void 0 ? "" : _b, restInner = __rest(_a, ["className"]); return /*#__PURE__*/React__default.default.createElement("div", _assign({ className: getClassNames("MonthContainer", className) }, restInner), children); }; var WeekContainer = function WeekContainer(props) { var getClassNames = props.getClassNames, children = props.children, innerProps = props.innerProps; var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, _b = _a.className, className = _b === void 0 ? "" : _b, restInner = __rest(_a, ["className"]); return /*#__PURE__*/React__default.default.createElement("div", _assign({ className: getClassNames("WeekContainer", className) }, restInner), children); }; var DaysContainer = function DaysContainer(props) { var getClassNames = props.getClassNames, children = props.children, innerProps = props.innerProps; var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, _b = _a.className, className = _b === void 0 ? "" : _b, restInner = __rest(_a, ["className"]); return /*#__PURE__*/React__default.default.createElement("div", _assign({ role: "listbox", className: getClassNames("DaysContainer", className) }, restInner), children); }; var DayContainer = function DayContainer(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, _b = _a.className, className = _b === void 0 ? "" : _b, restInner = __rest(_a, ["onClick", "className"]); 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 /*#__PURE__*/React__default.default.createElement("div", _assign({ "aria-label": formatDate(date, {}, options), role: "option", tabIndex: -1, className: getClassNames("DayContainer", className), onClick: function onClick() { return _onClick && _onClick(date, state); } }, attributes, restInner), children); }; var MonthArrowBack = function MonthArrowBack(props) { var innerProps = props.innerProps, getClassNames = props.getClassNames, month = props.month, year = props.year, options = props.options; var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, _b = _a.className, className = _b === void 0 ? "" : _b, ariaLabel = _a["aria-label"], restInner = __rest(_a, ["className", "aria-label"]); var label = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : typeof month === "number" && typeof year === "number" ? formatMonthYear(new Date(year, month - 1), options) : "Previous month"; return /*#__PURE__*/React__default.default.createElement("button", _assign({ type: "button", className: getClassNames("MonthArrowBack", className), "aria-label": label }, restInner), /*#__PURE__*/React__default.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24" }, /*#__PURE__*/React__default.default.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 MonthArrowNext(props) { var innerProps = props.innerProps, getClassNames = props.getClassNames, month = props.month, year = props.year, options = props.options; var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, _b = _a.className, className = _b === void 0 ? "" : _b, ariaLabel = _a["aria-label"], restInner = __rest(_a, ["className", "aria-label"]); var label = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : typeof month === "number" && typeof year === "number" ? formatMonthYear(new Date(year, month + 1), options) : "Next month"; return /*#__PURE__*/React__default.default.createElement("button", _assign({ type: "button", "aria-label": label, className: getClassNames("MonthArrowNext", className) }, restInner), /*#__PURE__*/React__default.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24" }, /*#__PURE__*/React__default.default.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 MonthContent(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 _b = _a.className, className = _b === void 0 ? "" : _b, restInner = __rest(_a, ["isScrollable", "className"]); var date = new Date(year, month); var monthContent = formatDate(date, { month: "long" }, options); var yearContent = formatNumber(year, options); var attributes = getAttributes({ "data-some-month": isSameMonth(date, new Date()), "data-some-year": isSameYear(date, new Date()) }); return /*#__PURE__*/React__default.default.createElement("div", _assign({ className: getClassNames("MonthContent", className) }, attributes, restInner), /*#__PURE__*/React__default.default.createElement("span", null, monthContent), /*#__PURE__*/React__default.default.createElement("span", null, yearContent)); }; var WeekContent = function WeekContent(props) { var day = props.day, options = props.options, innerProps = props.innerProps, getClassNames = props.getClassNames; var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, _b = _a.className, className = _b === void 0 ? "" : _b, restInner = __rest(_a, ["className"]); var startDate = startOfWeek(new Date(), options); var date = addDays(startDate, day); return /*#__PURE__*/React__default.default.createElement("div", _assign({ className: getClassNames("WeekContent", className) }, getAttributes({ "data-weekend": isWeekend(date) }), restInner), formatDate(date, { weekday: "short" }, options)); }; var DayContent = function DayContent(props) { var children = props.children, innerProps = props.innerProps, state = props.state, options = props.options, getClassNames = props.getClassNames; var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, _b = _a.className, className = _b === void 0 ? "" : _b, restInner = __rest(_a, ["className"]); return /*#__PURE__*/React__default.default.createElement("div", _assign({ className: getClassNames("DayContent", className) }, getDayAttributes(state, options), restInner), children); }; var DaySelection = function DaySelection(props) { var innerProps = props.innerProps, state = props.state, options = props.options, getClassNames = props.getClassNames; var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, _b = _a.className, className = _b === void 0 ? "" : _b, restInner = __rest(_a, ["className"]); if (!isShow$1(state)) return null; return /*#__PURE__*/React__default.default.createElement("div", _assign({ className: getClassNames("DaySelection", className) }, getDayAttributes(state, options), restInner)); }; var isShow$1 = function isShow(state) { return state.isSelected || state.isSelectedStart || state.isSelectedEnd; }; var DayToday = function DayToday(props) { var innerProps = props.innerProps, state = props.state, getClassNames = props.getClassNames; var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, _b = _a.className, className = _b === void 0 ? "" : _b, restInner = __rest(_a, ["className"]); if (!state.isToday) return null; return /*#__PURE__*/React__default.default.createElement("div", _assign({ className: getClassNames("DayToday", className) }, restInner)); }; var DayReservation = function DayReservation(props) { var innerProps = props.innerProps, state = props.state, getClassNames = props.getClassNames; var _a = innerProps !== null && innerProps !== void 0 ? innerProps : {}, _b = _a.className, className = _b === void 0 ? "" : _b, restInner = __rest(_a, ["className"]); if (!isShow(state)) return null; return /*#__PURE__*/React__default.default.createElement("div", _assign({ className: getClassNames("DayReservation", className) }, restInner)); }; var isShow = function isShow(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 defaultComponents(componentsByProps) { if (componentsByProps === void 0) { componentsByProps = {}; } return _assign(_assign({}, components), componentsByProps); }; var selectedInit = [null, null]; var isStartInit = true; var initialDateInit = new Date(); var reservedInit = []; var rangeInit = false; var disabledInit = false; new Date().getMonth(); new Date().getFullYear(); var getProtectedTime = function getProtectedTime(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); 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 validateBooking(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, _c = props.initialDate, initialDate = _c === void 0 ? initialDateInit : _c, _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 defaultDate = initialDate ? new Date(initialDate) : initialDateInit; var initialMonth = isNumeric(month) ? month : defaultDate.getMonth(); var initialYear = isNumeric(year) ? year : defaultDate.getFullYear(); var _l = React.useState(initialMonth), activeMonth = _l[0], setActiveMonth = _l[1]; var _m = React.useState(initialYear), activeYear = _m[0], setActiveYear = _m[1]; var isMonthControlled = isNumeric(month); var isYearControlled = isNumeric(year); var isControled = isMonthControlled && isYearControlled; React.useEffect(function () { if (isMonthControlled) setActiveMonth(month); }, [isMonthControlled, month]); React.useEffect(function () { if (isYearControlled) setActiveYear(year); }, [isYearControlled, year]); var currentMonth = isControled ? month : activeMonth; var currentYear = isControled ? year : activeYear; var _o = getSelectedDates(selected), startDate = _o[0], endDate = _o[1]; // ============================== // getClassNames // ============================== var getClassNames = function getClassNames(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 handleChangeMonth(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 !== null && onYearChange) onYearChange(newYear); if (isControled) return; setActiveMonth(newMonth); if (newYear !== null) setActiveYear(newYear); }; // ============================== // handleClickDay // ============================== var handleClickDay = function handleClickDay(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 /*#__PURE__*/React__default.default.createElement(CalendarContainer, _assign({}, commonProps, { innerProps: _assign({}, innerProps) }), /*#__PURE__*/React__default.default.createElement(MonthContainer, _assign({}, commonProps), /*#__PURE__*/React__default.default.createElement(MonthArrowBack, _assign({}, commonProps, { month: currentMonth, year: currentYear, innerProps: { onClick: function onClick() { return handleChangeMonth(currentMonth - 1); } } })), /*#__PURE__*/React__default.default.createElement(MonthContent, _assign({ month: currentMonth, year: currentYear }, commonProps)), /*#__PURE__*/React__default.default.createElement(MonthArrowNext, _assign({}, commonProps, { month: currentMonth, year: currentYear, innerProps: { onClick: function onClick() { return handleChangeMonth(currentMonth + 1); } } }))), /*#__PURE__*/React__default.default.createElement(WeekContainer, _assign({}, commonProps), Array.from({ length: 7 }).map(function (_, key) { return /*#__PURE__*/React__default.default.createElement(WeekContent, _assign({ key: "calendar_week_container_".concat(key), day: key }, commonProps, { innerProps: {} })); })), /*#__PURE__*/React__default.default.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 /*#__PURE__*/React__default.default.createElement(DayContainer, _assign({ key: "calendar_day_container_".concat(key), innerProps: { onClick: handleClickDay } }, dayProps, commonProps), /*#__PURE__*/React__default.default.createElement(DayContent, _assign({}, dayProps, commonProps), formatDay(day.date, options)), /*#__PURE__*/React__default.default.createElement(DayToday, _assign({}, dayProps, commonProps)), /*#__PURE__*/React__default.default.createElement(DaySelection, _assign({}, dayProps, commonProps)), /*#__PURE__*/React__default.default.createElement(DayReservation, _assign({}, dayProps, commonProps))); }))); } var getMonthYear = function getMonthYear(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 = /*#__PURE__*/React.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, options = commonProps.options; 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 handleClickDay() { 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 /*#__PURE__*/React__default.default.createElement(MonthContainer, _assign({}, commonProps, { innerProps: { style: style } }), /*#__PURE__*/React__default.default.createElement(MonthContent, _assign({ month: day.date.getMonth(), year: day.date.getFullYear() }, commonProps, { innerProps: { isScrollable: true } }))); } var dayProps = { date: day.date, state: state }; return /*#__PURE__*/React__default.default.createElement(DayContainer, _assign({ innerProps: { style: style, onClick: handleClickDay } }, dayProps, commonProps), state.isSameMonth && /*#__PURE__*/React__default.default.createElement(React__default.default.Fragment, null, /*#__PURE__*/React__default.default.createElement(DayContent, _assign({}, dayProps, commonProps), formatDay(day.date, options)), /*#__PURE__*/React__default.default.createElement(DayToday, _assign({}, dayProps, { state: state }, commonProps)), /*#__PURE__*/React__default.default.createElement(DaySelection, _assign({}, dayProps, { state: state }, commonProps)), /*#__PURE__*/React__default.default.createElement(DayReservation, _assign({}, dayProps, { state: state }, commonProps)))); }, reactWindow.areEqual); var Grid = function Grid(_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"]); React.useEffect(function () {}, [items, initialScroll]); return /*#__PURE__*/React__default.default.createElement(reactWindow.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 ScrollableCalendar(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 getClassNames(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 /*#__PURE__*/React__default.default.createElement(CalendarContainer, _assign({}, commonProps, { innerProps: _assign(_assign({}, innerProps), { isScrollable: true }) }), /*#__PURE__*/React__default.default.createElement(WeekContainer, _assign({ innerProps: {} }, commonProps), Array.from({ length: 7 }).map(function (_, key) { return /*#__PURE__*/React__default.default.createElement(WeekContent, _assign({ key: "scrollable_calendar_week_container_".concat(key), day: key }, commonProps, { innerProps: {} })); })), /*#__PURE__*/React__default.default.createElement(DaysContainer, _assign({}, commonProps), /*#__PURE__*/React__default.default.createElement(AutoSizer__default.default, null, function (_a) { var height = _a.height, width = _a.width; return /*#__PURE__*/React__default.default.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 getInitialScroll(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; }; exports.Calendar = Calendar; exports.ScrollableCalendar = ScrollableCalendar; exports.getProtectedInterval = getProtectedInterval; exports.getProtectedTime = getProtectedTime; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzIjpbIi4uLy4uL25vZGVfbW9kdWxlcy90c2xpYi90c2xpYi5lczYuanMiLCIuLi8uLi9zcmMvdXRpbHMvZGF0ZS51dGlscy50cyIsIi4uLy4uL3NyYy9oZWxwZXJzLnRzIiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvY29udGFpbmVycy50c3giLCIuLi8uLi9zcmMvY29tcG9uZW50cy9Nb250aEFycm93QmFjay50c3giLCIuLi8uLi9zcmMvY29tcG9uZW50cy9Nb250aEFycm93TmV4dC50c3giLCIuLi8uLi9zcmMvY29tcG9uZW50cy9Nb250aENvbnRlbnQudHN4IiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvV2Vla0NvbnRlbnQudHN4IiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvRGF5Q29udGVudC50c3giLCIuLi8uLi9zcmMvY29tcG9uZW50cy9EYXlTZWxlY3Rpb24udHN4IiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvRGF5VG9kYXkudHN4IiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvRGF5UmVzZXJ2YXRpb24udHN4IiwiLi4vLi4vc3JjL2NvbXBvbmVudHMvaW5kZXgudHMiLCIuLi8uLi9zcmMvY29uc3RhbnRzLnRzIiwiLi4vLi4vc3JjL3V0aWxzL2dldC1wcm90ZWN0ZWQtdGltZS50c3giLCIuLi8uLi9zcmMvdXRpbHMvZ2V0LXByb3RlY3RlZC1pbnRlcnZhbC50cyIsIi4uLy4uL3NyYy9jYWxlbmRhci50c3giLCIuLi8uLi9zcmMvc2Nyb2xsYWJsZS1jYWxlbmRhci50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlLCBTdXBwcmVzc2VkRXJyb3IsIFN5bWJvbCwgSXRlcmF0b3IgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXHJcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH1cclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSlcclxuICAgICAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgICAgIH1cclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXNEZWNvcmF0ZShjdG9yLCBkZXNjcmlwdG9ySW4sIGRlY29yYXRvcnMsIGNvbnRleHRJbiwgaW5pdGlhbGl6ZXJzLCBleHRyYUluaXRpYWxpemVycykge1xyXG4gICAgZnVuY3Rpb24gYWNjZXB0KGYpIHsgaWYgKGYgIT09IHZvaWQgMCAmJiB0eXBlb2YgZiAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiRnVuY3Rpb24gZXhwZWN0ZWRcIik7IHJldHVybiBmOyB9XHJcbiAgICB2YXIga2luZCA9IGNvbnRleHRJbi5raW5kLCBrZXkgPSBraW5kID09PSBcImdldHRlclwiID8gXCJnZXRcIiA6IGtpbmQgPT09IFwic2V0dGVyXCIgPyBcInNldFwiIDogXCJ2YWx1ZVwiO1xyXG4gICAgdmFyIHRhcmdldCA9ICFkZXNjcmlwdG9ySW4gJiYgY3RvciA/IGNvbnRleHRJbltcInN0YXRpY1wiXSA/IGN0b3IgOiBjdG9yLnByb3RvdHlwZSA6IG51bGw7XHJcbiAgICB2YXIgZGVzY3JpcHRvciA9IGRlc2NyaXB0b3JJbiB8fCAodGFyZ2V0ID8gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGNvbnRleHRJbi5uYW1lKSA6IHt9KTtcclxuICAgIHZhciBfLCBkb25lID0gZmFsc2U7XHJcbiAgICBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgIHZhciBjb250ZXh0ID0ge307XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4pIGNvbnRleHRbcF0gPSBwID09PSBcImFjY2Vzc1wiID8ge30gOiBjb250ZXh0SW5bcF07XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4uYWNjZXNzKSBjb250ZXh0LmFjY2Vzc1twXSA9IGNvbnRleHRJbi5hY2Nlc3NbcF07XHJcbiAgICAgICAgY29udGV4dC5hZGRJbml0aWFsaXplciA9IGZ1bmN0aW9uIChmKSB7IGlmIChkb25lKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGFkZCBpbml0aWFsaXplcnMgYWZ0ZXIgZGVjb3JhdGlvbiBoYXMgY29tcGxldGVkXCIpOyBleHRyYUluaXRpYWxpemVycy5wdXNoKGFjY2VwdChmIHx8IG51bGwpKTsgfTtcclxuICAgICAgICB2YXIgcmVzdWx0ID0gKDAsIGRlY29yYXRvcnNbaV0pKGtpbmQgPT09IFwiYWNjZXNzb3JcIiA/IHsgZ2V0OiBkZXNjcmlwdG9yLmdldCwgc2V0OiBkZXNjcmlwdG9yLnNldCB9IDogZGVzY3JpcHRvcltrZXldLCBjb250ZXh0KTtcclxuICAgICAgICBpZiAoa2luZCA9PT0gXCJhY2Nlc3NvclwiKSB7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IHZvaWQgMCkgY29udGludWU7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwgfHwgdHlwZW9mIHJlc3VsdCAhPT0gXCJvYmplY3RcIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk9iamVjdCBleHBlY3RlZFwiKTtcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmdldCkpIGRlc2NyaXB0b3IuZ2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LnNldCkpIGRlc2NyaXB0b3Iuc2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmluaXQpKSBpbml0aWFsaXplcnMudW5zaGlmdChfKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoXyA9IGFjY2VwdChyZXN1bHQpKSB7XHJcbiAgICAgICAgICAgIGlmIChraW5kID09PSBcImZpZWxkXCIpIGluaXRpYWxpemVycy51bnNoaWZ0KF8pO1xyXG4gICAgICAgICAgICBlbHNlIGRlc2NyaXB0b3Jba2V5XSA9IF87XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHRhcmdldCkgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgY29udGV4dEluLm5hbWUsIGRlc2NyaXB0b3IpO1xyXG4gICAgZG9uZSA9IHRydWU7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19ydW5Jbml0aWFsaXplcnModGhpc0FyZywgaW5pdGlhbGl6ZXJzLCB2YWx1ZSkge1xyXG4gICAgdmFyIHVzZVZhbHVlID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluaXRpYWxpemVycy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIHZhbHVlID0gdXNlVmFsdWUgPyBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnLCB2YWx1ZSkgOiBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnKTtcclxuICAgIH1cclxuICAgIHJldHVybiB1c2VWYWx1ZSA/IHZhbHVlIDogdm9pZCAwO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcHJvcEtleSh4KSB7XHJcbiAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3ltYm9sXCIgPyB4IDogXCJcIi5jb25jYXQoeCk7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zZXRGdW5jdGlvbk5hbWUoZiwgbmFtZSwgcHJlZml4KSB7XHJcbiAgICBpZiAodHlwZW9mIG5hbWUgPT09IFwic3ltYm9sXCIpIG5hbWUgPSBuYW1lLmRlc2NyaXB0aW9uID8gXCJbXCIuY29uY2F0KG5hbWUuZGVzY3JpcHRpb24sIFwiXVwiKSA6IFwiXCI7XHJcbiAgICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KGYsIFwibmFtZVwiLCB7IGNvbmZpZ3VyYWJsZTogdHJ1ZSwgdmFsdWU6IHByZWZpeCA/IFwiXCIuY29uY2F0KHByZWZpeCwgXCIgXCIsIG5hbWUpIDogbmFtZSB9KTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZ