220 lines
15 KiB
JavaScript
220 lines
15 KiB
JavaScript
define(["require", "exports", "react", "../../../FocusZone", "@fluentui/date-time-utilities", "../../../Icon", "./CalendarMonth.styles", "@fluentui/utilities", "../CalendarYear/CalendarYear", "@fluentui/react-hooks", "../defaults"], function (require, exports, React, FocusZone_1, date_time_utilities_1, Icon_1, CalendarMonth_styles_1, utilities_1, CalendarYear_1, react_hooks_1, defaults_1) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.CalendarMonthBase = void 0;
|
|
var MONTHS_PER_ROW = 4;
|
|
var getClassNames = (0, utilities_1.classNamesFunction)();
|
|
var DEFAULT_PROPS = {
|
|
styles: CalendarMonth_styles_1.getStyles,
|
|
strings: undefined,
|
|
navigationIcons: defaults_1.defaultCalendarNavigationIcons,
|
|
dateTimeFormatter: date_time_utilities_1.DEFAULT_DATE_FORMATTING,
|
|
yearPickerHidden: false,
|
|
};
|
|
function useAnimateBackwards(_a) {
|
|
var navigatedDate = _a.navigatedDate;
|
|
var currentYear = navigatedDate.getFullYear();
|
|
var previousYear = (0, react_hooks_1.usePrevious)(currentYear);
|
|
if (previousYear === undefined || previousYear === currentYear) {
|
|
return undefined;
|
|
}
|
|
else {
|
|
return previousYear > currentYear;
|
|
}
|
|
}
|
|
function useFocusLogic(_a) {
|
|
var componentRef = _a.componentRef;
|
|
var navigatedMonthRef = React.useRef(null);
|
|
var calendarYearRef = React.useRef(null);
|
|
var focusOnUpdate = React.useRef(false);
|
|
var focus = React.useCallback(function () {
|
|
if (calendarYearRef.current) {
|
|
calendarYearRef.current.focus();
|
|
}
|
|
else if (navigatedMonthRef.current) {
|
|
navigatedMonthRef.current.focus();
|
|
}
|
|
}, []);
|
|
React.useImperativeHandle(componentRef, function () { return ({ focus: focus }); }, [focus]);
|
|
React.useEffect(function () {
|
|
if (focusOnUpdate.current) {
|
|
focus();
|
|
focusOnUpdate.current = false;
|
|
}
|
|
});
|
|
var focusOnNextUpdate = function () {
|
|
focusOnUpdate.current = true;
|
|
};
|
|
return [navigatedMonthRef, calendarYearRef, focusOnNextUpdate];
|
|
}
|
|
var CalendarMonthBase = function (propsWithoutDefaults) {
|
|
var _a, _b;
|
|
var props = (0, utilities_1.getPropsWithDefaults)(DEFAULT_PROPS, propsWithoutDefaults);
|
|
var _c = useFocusLogic(props), navigatedMonthRef = _c[0], calendarYearRef = _c[1], focusOnNextUpdate = _c[2];
|
|
var _d = React.useState(false), isYearPickerVisible = _d[0], setIsYearPickerVisible = _d[1];
|
|
var animateBackwards = useAnimateBackwards(props);
|
|
var navigatedDate = props.navigatedDate, selectedDate = props.selectedDate, strings = props.strings, _e = props.today, today = _e === void 0 ? new Date() : _e, navigationIcons = props.navigationIcons, dateTimeFormatter = props.dateTimeFormatter, minDate = props.minDate, maxDate = props.maxDate, theme = props.theme, styles = props.styles, className = props.className, allFocusable = props.allFocusable, highlightCurrentMonth = props.highlightCurrentMonth, highlightSelectedMonth = props.highlightSelectedMonth, animationDirection = props.animationDirection, yearPickerHidden = props.yearPickerHidden, onNavigateDate = props.onNavigateDate;
|
|
var selectMonthCallback = function (newMonth) {
|
|
return function () { return onSelectMonth(newMonth); };
|
|
};
|
|
var onSelectNextYear = function () {
|
|
onNavigateDate((0, date_time_utilities_1.addYears)(navigatedDate, 1), false);
|
|
};
|
|
var onSelectPrevYear = function () {
|
|
onNavigateDate((0, date_time_utilities_1.addYears)(navigatedDate, -1), false);
|
|
};
|
|
var onSelectMonth = function (newMonth) {
|
|
var _a;
|
|
// If header is clickable the calendars are overlayed, switch back to day picker when month is clicked
|
|
(_a = props.onHeaderSelect) === null || _a === void 0 ? void 0 : _a.call(props);
|
|
onNavigateDate((0, date_time_utilities_1.setMonth)(navigatedDate, newMonth), true);
|
|
};
|
|
var onHeaderSelect = function () {
|
|
var _a;
|
|
if (!yearPickerHidden) {
|
|
focusOnNextUpdate();
|
|
setIsYearPickerVisible(true);
|
|
}
|
|
else {
|
|
(_a = props.onHeaderSelect) === null || _a === void 0 ? void 0 : _a.call(props);
|
|
}
|
|
};
|
|
var onSelectYear = function (selectedYear) {
|
|
focusOnNextUpdate();
|
|
var navYear = navigatedDate.getFullYear();
|
|
if (navYear !== selectedYear) {
|
|
var newNavigationDate = new Date(navigatedDate.getTime());
|
|
newNavigationDate.setFullYear(selectedYear);
|
|
// for min and max dates, adjust the new navigation date - perhaps this should be
|
|
// checked on the master navigation date handler (i.e. in Calendar)
|
|
if (maxDate && newNavigationDate > maxDate) {
|
|
newNavigationDate = (0, date_time_utilities_1.setMonth)(newNavigationDate, maxDate.getMonth());
|
|
}
|
|
else if (minDate && newNavigationDate < minDate) {
|
|
newNavigationDate = (0, date_time_utilities_1.setMonth)(newNavigationDate, minDate.getMonth());
|
|
}
|
|
onNavigateDate(newNavigationDate, true);
|
|
}
|
|
setIsYearPickerVisible(false);
|
|
};
|
|
var onYearPickerHeaderSelect = function (focus) {
|
|
focusOnNextUpdate();
|
|
setIsYearPickerVisible(false);
|
|
};
|
|
// navigationIcons has a default value in defaultProps, but typescript doesn't recognize this
|
|
var leftNavigationIcon = navigationIcons.leftNavigation;
|
|
var rightNavigationIcon = navigationIcons.rightNavigation;
|
|
var dateFormatter = dateTimeFormatter;
|
|
// determine if previous/next years are in bounds
|
|
var isPrevYearInBounds = minDate ? (0, date_time_utilities_1.compareDatePart)(minDate, (0, date_time_utilities_1.getYearStart)(navigatedDate)) < 0 : true;
|
|
var isNextYearInBounds = maxDate ? (0, date_time_utilities_1.compareDatePart)((0, date_time_utilities_1.getYearEnd)(navigatedDate), maxDate) < 0 : true;
|
|
var classNames = getClassNames(styles, {
|
|
theme: theme,
|
|
className: className,
|
|
hasHeaderClickCallback: !!props.onHeaderSelect || !yearPickerHidden,
|
|
highlightCurrent: highlightCurrentMonth,
|
|
highlightSelected: highlightSelectedMonth,
|
|
animateBackwards: animateBackwards,
|
|
animationDirection: animationDirection,
|
|
});
|
|
if (isYearPickerVisible) {
|
|
var _f = getYearStrings(props), onRenderYear = _f[0], yearStrings = _f[1];
|
|
// use navigated date for the year picker
|
|
return (React.createElement(CalendarYear_1.CalendarYear, { key: 'calendarYear', minYear: minDate ? minDate.getFullYear() : undefined, maxYear: maxDate ? maxDate.getFullYear() : undefined,
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onSelectYear: onSelectYear, navigationIcons: navigationIcons,
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onHeaderSelect: onYearPickerHeaderSelect, selectedYear: selectedDate ? selectedDate.getFullYear() : navigatedDate ? navigatedDate.getFullYear() : undefined, navigatedYear: navigatedDate.getFullYear(), onRenderYear: onRenderYear, strings: yearStrings, componentRef: calendarYearRef, styles: styles, highlightCurrentYear: highlightCurrentMonth, highlightSelectedYear: highlightSelectedMonth, animationDirection: animationDirection }));
|
|
}
|
|
var rowIndexes = [];
|
|
for (var i = 0; i < strings.shortMonths.length / MONTHS_PER_ROW; i++) {
|
|
rowIndexes.push(i);
|
|
}
|
|
var yearString = dateFormatter.formatYear(navigatedDate);
|
|
var headerAriaLabel = strings.monthPickerHeaderAriaLabel
|
|
? (0, utilities_1.format)(strings.monthPickerHeaderAriaLabel, yearString)
|
|
: yearString;
|
|
return (React.createElement("div", { className: classNames.root },
|
|
React.createElement("div", { className: classNames.headerContainer },
|
|
React.createElement("button", { className: classNames.currentItemButton, onClick: onHeaderSelect, onKeyDown: onButtonKeyDown(onHeaderSelect), "aria-label": headerAriaLabel, "data-is-focusable": !!props.onHeaderSelect || !yearPickerHidden, tabIndex: !!props.onHeaderSelect || !yearPickerHidden ? 0 : -1, type: "button" },
|
|
React.createElement("span", { "aria-live": "polite", "aria-atomic": "true" }, yearString)),
|
|
React.createElement("div", { className: classNames.navigationButtonsContainer },
|
|
React.createElement("button", { className: (0, utilities_1.css)(classNames.navigationButton, (_a = {},
|
|
_a[classNames.disabled] = !isPrevYearInBounds,
|
|
_a)), "aria-disabled": !isPrevYearInBounds, tabIndex: isPrevYearInBounds ? undefined : allFocusable ? 0 : -1, onClick: isPrevYearInBounds ? onSelectPrevYear : undefined, onKeyDown: isPrevYearInBounds ? onButtonKeyDown(onSelectPrevYear) : undefined, title: strings.prevYearAriaLabel
|
|
? strings.prevYearAriaLabel + ' ' + dateFormatter.formatYear((0, date_time_utilities_1.addYears)(navigatedDate, -1))
|
|
: undefined, type: "button" },
|
|
React.createElement(Icon_1.Icon, { iconName: (0, utilities_1.getRTL)() ? rightNavigationIcon : leftNavigationIcon })),
|
|
React.createElement("button", { className: (0, utilities_1.css)(classNames.navigationButton, (_b = {},
|
|
_b[classNames.disabled] = !isNextYearInBounds,
|
|
_b)), "aria-disabled": !isNextYearInBounds, tabIndex: isNextYearInBounds ? undefined : allFocusable ? 0 : -1, onClick: isNextYearInBounds ? onSelectNextYear : undefined, onKeyDown: isNextYearInBounds ? onButtonKeyDown(onSelectNextYear) : undefined, title: strings.nextYearAriaLabel
|
|
? strings.nextYearAriaLabel + ' ' + dateFormatter.formatYear((0, date_time_utilities_1.addYears)(navigatedDate, 1))
|
|
: undefined, type: "button" },
|
|
React.createElement(Icon_1.Icon, { iconName: (0, utilities_1.getRTL)() ? leftNavigationIcon : rightNavigationIcon })))),
|
|
React.createElement(FocusZone_1.FocusZone, null,
|
|
React.createElement("div", { className: classNames.gridContainer, role: "grid", "aria-label": yearString }, rowIndexes.map(function (rowNum) {
|
|
var monthsForRow = strings.shortMonths.slice(rowNum * MONTHS_PER_ROW, (rowNum + 1) * MONTHS_PER_ROW);
|
|
return (React.createElement("div", { key: 'monthRow_' + rowNum + navigatedDate.getFullYear(), role: "row", className: classNames.buttonRow }, monthsForRow.map(function (month, index) {
|
|
var _a;
|
|
var monthIndex = rowNum * MONTHS_PER_ROW + index;
|
|
var indexedMonth = (0, date_time_utilities_1.setMonth)(navigatedDate, monthIndex);
|
|
var isNavigatedMonth = navigatedDate.getMonth() === monthIndex;
|
|
var isSelectedMonth = selectedDate.getMonth() === monthIndex;
|
|
var isSelectedYear = selectedDate.getFullYear() === navigatedDate.getFullYear();
|
|
var isInBounds = (minDate ? (0, date_time_utilities_1.compareDatePart)(minDate, (0, date_time_utilities_1.getMonthEnd)(indexedMonth)) < 1 : true) &&
|
|
(maxDate ? (0, date_time_utilities_1.compareDatePart)((0, date_time_utilities_1.getMonthStart)(indexedMonth), maxDate) < 1 : true);
|
|
return (React.createElement("button", { ref: isNavigatedMonth ? navigatedMonthRef : undefined, role: 'gridcell', className: (0, utilities_1.css)(classNames.itemButton, (_a = {},
|
|
_a[classNames.current] = highlightCurrentMonth && isCurrentMonth(monthIndex, navigatedDate.getFullYear(), today),
|
|
_a[classNames.selected] = highlightSelectedMonth && isSelectedMonth && isSelectedYear,
|
|
_a[classNames.disabled] = !isInBounds,
|
|
_a)), disabled: !allFocusable && !isInBounds, key: monthIndex, onClick: isInBounds ? selectMonthCallback(monthIndex) : undefined, onKeyDown: isInBounds ? onButtonKeyDown(selectMonthCallback(monthIndex)) : undefined, "aria-label": dateFormatter.formatMonth(indexedMonth, strings), "aria-selected": isNavigatedMonth, "data-is-focusable": isInBounds ? true : undefined, type: "button" }, month));
|
|
})));
|
|
})))));
|
|
};
|
|
exports.CalendarMonthBase = CalendarMonthBase;
|
|
exports.CalendarMonthBase.displayName = 'CalendarMonthBase';
|
|
function getYearStrings(_a) {
|
|
var strings = _a.strings, navigatedDate = _a.navigatedDate, dateTimeFormatter = _a.dateTimeFormatter;
|
|
var yearToString = function (year) {
|
|
if (dateTimeFormatter) {
|
|
// create a date based on the current nav date
|
|
var yearFormattingDate = new Date(navigatedDate.getTime());
|
|
yearFormattingDate.setFullYear(year);
|
|
return dateTimeFormatter.formatYear(yearFormattingDate);
|
|
}
|
|
return String(year);
|
|
};
|
|
var yearRangeToString = function (yearRange) {
|
|
return "".concat(yearToString(yearRange.fromYear), " - ").concat(yearToString(yearRange.toYear));
|
|
};
|
|
var yearRangeToNextDecadeLabel = function (yearRange) {
|
|
return strings.nextYearRangeAriaLabel ? "".concat(strings.nextYearRangeAriaLabel, " ").concat(yearRangeToString(yearRange)) : '';
|
|
};
|
|
var yearRangeToPrevDecadeLabel = function (yearRange) {
|
|
return strings.prevYearRangeAriaLabel ? "".concat(strings.prevYearRangeAriaLabel, " ").concat(yearRangeToString(yearRange)) : '';
|
|
};
|
|
return [
|
|
yearToString,
|
|
{
|
|
rangeAriaLabel: yearRangeToString,
|
|
prevRangeAriaLabel: yearRangeToPrevDecadeLabel,
|
|
nextRangeAriaLabel: yearRangeToNextDecadeLabel,
|
|
headerAriaLabelFormatString: strings.yearPickerHeaderAriaLabel,
|
|
},
|
|
];
|
|
}
|
|
function isCurrentMonth(month, year, today) {
|
|
return today.getFullYear() === year && today.getMonth() === month;
|
|
}
|
|
function onButtonKeyDown(callback) {
|
|
return function (ev) {
|
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
switch (ev.which) {
|
|
case utilities_1.KeyCodes.enter:
|
|
callback();
|
|
break;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
//# sourceMappingURL=CalendarMonth.base.js.map
|