suomifi-ui-components
Version:
Suomi.fi UI component library
485 lines (479 loc) • 19.9 kB
JavaScript
'use strict';
var tslib = require('tslib');
var React = require('react');
var ReactDOM = require('react-dom');
var styled = require('styled-components');
var classnames = require('classnames');
var common = require('../../../../utils/common/common.js');
var SuomifiThemeProvider = require('../../../theme/SuomifiThemeProvider/SuomifiThemeProvider.js');
require('../../../theme/SuomifiTheme/SuomifiTheme.js');
require('../../../theme/SpacingProvider/SpacingProvider.js');
require('../../../../reset/HtmlA/HtmlA.js');
require('../../../../reset/HtmlButton/HtmlButton.js');
var HtmlDiv = require('../../../../reset/HtmlDiv/HtmlDiv.js');
require('../../../../reset/HtmlFieldSet/HtmlFieldSet.js');
require('../../../../reset/HtmlH/HtmlH.js');
require('../../../../reset/HtmlInput/HtmlInput.js');
require('../../../../reset/HtmlLabel/HtmlLabel.js');
require('../../../../reset/HtmlLegend/HtmlLegend.js');
require('../../../../reset/HtmlLi/HtmlLi.js');
require('../../../../reset/HtmlNav/HtmlNav.js');
require('../../../../reset/HtmlOl/HtmlOl.js');
require('../../../../reset/HtmlSpan/HtmlSpan.js');
require('../../../../reset/HtmlTextarea/HtmlTextarea.js');
require('../../../../reset/HtmlUl/HtmlUl.js');
require('../../../../reset/HtmlTable/HtmlTable.js');
require('../../../../reset/HtmlTable/HtmlTableCaption.js');
require('../../../../reset/HtmlTable/HtmlTableHeader.js');
require('../../../../reset/HtmlTable/HtmlTableRow.js');
require('../../../../reset/HtmlTable/HtmlTableBody.js');
require('../../../../reset/HtmlTable/HtmlTableHeaderCell.js');
require('../../../../reset/HtmlTable/HtmlTableCell.js');
var DatePicker_baseStyles = require('./DatePicker.baseStyles.js');
var Button = require('../../../Button/Button.js');
var MonthTable = require('./MonthTable/MonthTable.js');
var DateSelectors = require('./DateSelectors/DateSelectors.js');
var dateUtils = require('../dateUtils.js');
var logger = require('../../../../utils/log/logger.js');
var reactDom = require('@floating-ui/react-dom');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var React__default = /*#__PURE__*/_interopDefault(React);
var ReactDOM__default = /*#__PURE__*/_interopDefault(ReactDOM);
var classnames__default = /*#__PURE__*/_interopDefault(classnames);
var baseClassName = 'fi-date-picker';
var datePickerClassNames = {
baseClassName: baseClassName,
hidden: "".concat(baseClassName, "--hidden"),
smallScreen: "".concat(baseClassName, "--small-screen"),
smallScreenHidden: "".concat(baseClassName, "--small-screen-hidden"),
smallScreenContainer: "".concat(baseClassName, "_small-screen-container"),
smallScreenScroll: "".concat(baseClassName, "_small-screen-container--scroll"),
slideIndicator: "".concat(baseClassName, "_slide-indicator"),
slideIndicatorWrapper: "".concat(baseClassName, "_slide-indicator-wrapper"),
application: "".concat(baseClassName, "_application"),
bottomContainer: "".concat(baseClassName, "_bottom-container"),
floatinguiArrow: "".concat(baseClassName, "_floatingui-arrow")
};
var BaseDatePicker = function BaseDatePicker(props) {
var _a, _b, _c;
var _d, _e, _f;
var openButtonRef = props.openButtonRef,
isOpen = props.isOpen,
onClose = props.onClose,
onChange = props.onChange,
shouldDisableDate = props.shouldDisableDate,
className = props.className,
texts = props.texts,
initialDate = props.initialDate,
inputValue = props.inputValue,
minDate = props.minDate,
maxDate = props.maxDate,
smallScreen = props.smallScreen,
position = props.position,
_g = props.userProps,
userProps = _g === void 0 ? {} : _g;
var _h = React.useState(null),
mountNode = _h[0],
setMountNode = _h[1];
var _j = React.useState(null),
dialogElement = _j[0],
setDialogElement = _j[1];
var _k = React.useState(new Date()),
focusableDate = _k[0],
setFocusableDate = _k[1];
var _l = React.useState(null),
focusedDate = _l[0],
setFocusedDate = _l[1];
var _m = React.useState(null),
selectedDate = _m[0],
setSelectedDate = _m[1];
var _o = React.useState(0),
yearSelectWidth = _o[0],
setYearSelectWidth = _o[1];
var _p = React.useState(0),
monthSelectWidth = _p[0],
setMonthSelectWidth = _p[1];
var _q = React.useState(null),
touchStartX = _q[0],
setTouchStartX = _q[1];
var _r = React.useState(null),
touchStartY = _r[0],
setTouchStartY = _r[1];
var _s = React.useState(0),
dragOffsetY = _s[0],
setDragOffsetY = _s[1];
var _t = React.useState(false),
dragging = _t[0],
setDragging = _t[1];
var _u = React.useState(false),
smallScreenScroll = _u[0],
setSmallScreenScroll = _u[1];
var sliderWrapperRef = React.useRef(null);
var smallScreenAppRef = React.useRef(null);
var yearSelectRef = React.useRef(null);
var monthSelectRef = React.useRef(null);
var closeButtonRef = React.useRef(null);
var dayButtonRef = React.useRef(null);
var arrowRef = React.useRef(null);
common.useEnhancedEffect(function () {
setMountNode(window.document.body);
if (dateUtils.dayIsBefore(focusableDate, minDate)) {
setFocusableDate(minDate);
} else if (dateUtils.dayIsAfter(focusableDate, maxDate)) {
setFocusableDate(maxDate);
}
}, []);
React.useEffect(function () {
if (initialDate) {
if (dateUtils.dayIsInRange(initialDate, minDate, maxDate)) {
setFocusableDate(initialDate);
} else {
logger.getLogger().warn("Initial date \"".concat(initialDate, "\" is not within interval [minDate, maxDate]"));
}
}
}, [initialDate]);
React.useEffect(function () {
if (isOpen) {
document.addEventListener('click', globalClickHandler, {
capture: true
});
document.addEventListener('keydown', globalKeyDownHandler, {
capture: true
});
focusDate();
calculateDropdownWidths();
return function () {
document.removeEventListener('click', globalClickHandler, {
capture: true
});
document.removeEventListener('keydown', globalKeyDownHandler, {
capture: true
});
};
}
}, [isOpen]);
React.useEffect(function () {
if (smallScreen && isOpen && smallScreenAppRef.current) {
smallScreenAppRef.current.style.top = '';
conditionalSmallScreenScroll();
window.addEventListener('resize', conditionalSmallScreenScroll);
return function () {
return window.removeEventListener('resize', conditionalSmallScreenScroll);
};
}
}, [smallScreen, isOpen]);
var conditionalSmallScreenScroll = function conditionalSmallScreenScroll() {
if (smallScreenAppRef.current) {
var _a = smallScreenAppRef.current,
clientHeight = _a.clientHeight,
scrollHeight = _a.scrollHeight;
if (scrollHeight > clientHeight) {
setSmallScreenScroll(true);
} else {
setSmallScreenScroll(false);
}
}
};
var focusDate = function focusDate() {
if (inputValue && dateUtils.dayIsInRange(inputValue, minDate, maxDate)) {
setSelectedDate(inputValue);
setFocusableDate(inputValue);
setFocusedDate(inputValue);
} else {
if (inputValue && !dateUtils.dayIsInRange(inputValue, minDate, maxDate)) {
logger.getLogger().warn("Input value \"".concat(inputValue, "\" is not within interval [minDate, maxDate]"));
}
setFocusedDate(focusableDate);
}
};
var calculateDropdownWidths = function calculateDropdownWidths() {
var _a, _b;
setYearSelectWidth(((_a = yearSelectRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width) || 0);
setMonthSelectWidth(((_b = monthSelectRef.current) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect().width) || 0);
};
var globalClickHandler = function globalClickHandler(nativeEvent) {
var _a, _b;
if (!((_a = smallScreenAppRef === null || smallScreenAppRef === void 0 ? void 0 : smallScreenAppRef.current) === null || _a === void 0 ? void 0 : _a.contains(nativeEvent.target)) && !(dialogElement === null || dialogElement === void 0 ? void 0 : dialogElement.contains(nativeEvent.target)) && !((_b = openButtonRef.current) === null || _b === void 0 ? void 0 : _b.contains(nativeEvent.target))) {
handleClose();
}
};
var globalKeyDownHandler = function globalKeyDownHandler(event) {
var _a, _b;
if (event.key === 'Escape' && !(((_a = yearSelectRef.current) === null || _a === void 0 ? void 0 : _a.getAttribute('aria-expanded')) === 'true') && !(((_b = monthSelectRef.current) === null || _b === void 0 ? void 0 : _b.getAttribute('aria-expanded')) === 'true')) {
event.stopPropagation();
handleClose(true);
}
if (event.key === 'Tab') {
var firstElement = yearSelectRef.current;
var lastElement = closeButtonRef === null || closeButtonRef === void 0 ? void 0 : closeButtonRef.current;
if (event.shiftKey && document.activeElement === firstElement) {
event.preventDefault();
lastElement === null || lastElement === void 0 ? void 0 : lastElement.focus();
} else if (!event.shiftKey && document.activeElement === lastElement) {
event.preventDefault();
firstElement === null || firstElement === void 0 ? void 0 : firstElement.focus();
}
}
};
var handleButtonKeydown = function handleButtonKeydown(event) {
var date;
if (event.key === 'ArrowRight') {
event.preventDefault();
date = dateInRange(dateUtils.moveDays(focusableDate, 1));
}
if (event.key === 'ArrowLeft') {
event.preventDefault();
date = dateInRange(dateUtils.moveDays(focusableDate, -1));
}
if (event.key === 'ArrowDown') {
event.preventDefault();
date = dateInRange(dateUtils.moveDays(focusableDate, 7));
}
if (event.key === 'ArrowUp') {
event.preventDefault();
date = dateInRange(dateUtils.moveDays(focusableDate, -7));
}
if (event.key === 'Home') {
event.preventDefault();
date = dateInRange(dateUtils.firstDayOfWeek(focusableDate));
}
if (event.key === 'End') {
event.preventDefault();
date = dateInRange(dateUtils.lastDayOfWeek(focusableDate));
}
if (event.key === 'PageUp' && event.shiftKey) {
event.preventDefault();
date = dateInRange(dateUtils.moveYears(focusableDate, -1));
}
if (event.key === 'PageDown' && event.shiftKey) {
event.preventDefault();
date = dateInRange(dateUtils.moveYears(focusableDate, 1));
}
if (event.key === 'PageUp' && !event.shiftKey) {
event.preventDefault();
date = dateInRange(dateUtils.moveMonths(focusableDate, -1));
}
if (event.key === 'PageDown' && !event.shiftKey) {
event.preventDefault();
date = dateInRange(dateUtils.moveMonths(focusableDate, 1));
}
if (date) {
setFocusableDate(date);
setFocusedDate(date);
}
};
var dateInRange = function dateInRange(date, start, end) {
if (start === void 0) {
start = minDate;
}
if (end === void 0) {
end = maxDate;
}
if (dateUtils.dayIsInRange(date, start, end)) {
return date;
}
return null;
};
var _v = reactDom.useFloating({
open: isOpen,
middleware: [reactDom.offset(10), reactDom.flip(), reactDom.shift(), reactDom.arrow({
element: arrowRef
})],
whileElementsMounted: reactDom.autoUpdate,
placement: position === 'right' ? 'bottom-start' : position === 'left' ? 'bottom-end' : 'bottom'
}),
floatingUiRefs = _v.refs,
floatingStyles = _v.floatingStyles,
middlewareData = _v.middlewareData;
React.useEffect(function () {
if (openButtonRef.current) {
floatingUiRefs.setReference(openButtonRef.current);
}
}, [floatingUiRefs, openButtonRef]);
React.useEffect(function () {
if (dialogElement) {
floatingUiRefs.setFloating(dialogElement);
}
}, [floatingUiRefs, dialogElement]);
var isSelectOpen = function isSelectOpen(event) {
var _a, _b;
return ((_a = yearSelectRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) && yearSelectRef.current.getAttribute('data-state') === 'expanded' || ((_b = monthSelectRef.current) === null || _b === void 0 ? void 0 : _b.contains(event.target)) && monthSelectRef.current.getAttribute('data-state') === 'expanded' || false;
};
var handleClose = function handleClose(focus) {
if (focus === void 0) {
focus = false;
}
setSelectedDate(null);
setFocusedDate(null);
onClose(focus);
};
var handleDateChange = function handleDateChange(date) {
setFocusableDate(date);
};
var handleDateSelect = function handleDateSelect(date) {
handleClose(true);
onChange(date);
setFocusableDate(date);
};
var handlePointerDown = function handlePointerDown(event) {
var _a, _b;
if ((_a = sliderWrapperRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) {
setDragging(true);
setTouchStartY(event.clientY);
setDragOffsetY(((_b = smallScreenAppRef.current) === null || _b === void 0 ? void 0 : _b.offsetTop) || 0);
sliderWrapperRef.current.style.cursor = 'grabbing';
}
};
var handlePointerMove = function handlePointerMove(event) {
if (!dragging) return;
if (smallScreenAppRef.current) {
var diff = event.clientY - (touchStartY || 0);
if (diff > 0) {
smallScreenAppRef.current.style.top = "".concat(dragOffsetY + diff, "px");
}
}
};
var handlePointerUp = function handlePointerUp(event) {
if (!dragging) return;
var diff = event.clientY - (touchStartY || 0);
if (diff > 100) {
handleClose(true);
} else if (smallScreenAppRef.current) {
smallScreenAppRef.current.style.top = '';
}
if (sliderWrapperRef.current) {
sliderWrapperRef.current.style.cursor = 'grab';
}
setDragging(false);
setTouchStartY(null);
setDragOffsetY(0);
};
var handleTouchStart = function handleTouchStart(event) {
if (isSelectOpen(event)) {
setTouchStartX(null);
setTouchStartY(null);
} else {
setTouchStartX(event.changedTouches[0].clientX);
setTouchStartY(event.changedTouches[0].clientY);
}
};
var handleTouchEnd = function handleTouchEnd(event) {
if (touchStartX === null || touchStartY === null) {
return;
}
var distanceX = event.changedTouches[0].clientX - touchStartX;
var distanceY = event.changedTouches[0].clientY - touchStartY;
var minDistance = 50;
var horizontal = Math.abs(distanceX) > minDistance && distanceY < minDistance;
var date;
if (horizontal && distanceX > 0) {
date = dateInRange(dateUtils.moveMonths(focusableDate, -1));
} else if (horizontal) {
date = dateInRange(dateUtils.moveMonths(focusableDate, 1));
}
if (date) {
setFocusableDate(date);
setFocusedDate(date);
}
};
var application = /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDiv, {
role: "application",
className: datePickerClassNames.application
}, /*#__PURE__*/React__default.default.createElement(DateSelectors.DateSelectors, {
focusableDate: focusableDate,
yearSelect: yearSelectRef,
yearSelectWidth: yearSelectWidth,
monthSelect: monthSelectRef,
monthSelectWidth: monthSelectWidth,
onChange: handleDateChange,
minDate: minDate,
maxDate: maxDate,
texts: texts
}), /*#__PURE__*/React__default.default.createElement(MonthTable.MonthTable, {
focusableDate: focusableDate,
focusedDate: focusedDate,
selectedDate: selectedDate,
onSelect: handleDateSelect,
onKeyDown: handleButtonKeydown,
shouldDisableDate: shouldDisableDate,
dayButtonRef: dayButtonRef,
minDate: minDate,
maxDate: maxDate,
texts: texts
}), /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDiv, {
className: datePickerClassNames.bottomContainer
}, /*#__PURE__*/React__default.default.createElement(Button.Button, {
variant: "secondaryNoBorder",
onClick: function onClick() {
return handleClose(true);
},
forwardedRef: closeButtonRef
}, texts.closeButtonText)));
var customClassName = userProps.className,
passProps = tslib.__rest(userProps, ["className"]);
var dialogClasses = [className, baseClassName, customClassName, (_a = {}, _a[datePickerClassNames.hidden] = !isOpen, _a)];
var defaultDialog = /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDivWithRef, tslib.__assign({
role: "dialog",
"aria-hidden": !isOpen,
className: classnames__default.default.apply(void 0, dialogClasses),
style: floatingStyles,
forwardedRef: setDialogElement
}, passProps), application, /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDivWithRef, {
forwardedRef: arrowRef,
className: datePickerClassNames.floatinguiArrow,
"data-floatingui-placement": (_d = middlewareData === null || middlewareData === void 0 ? void 0 : middlewareData.offset) === null || _d === void 0 ? void 0 : _d.placement,
"aria-hidden": true,
tabIndex: -1,
style: {
left: (_e = middlewareData.arrow) === null || _e === void 0 ? void 0 : _e.x,
top: (_f = middlewareData.arrow) === null || _f === void 0 ? void 0 : _f.y
}
}));
var smallScreenDialog = /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDiv, {
"aria-hidden": !isOpen,
className: classnames__default.default.apply(void 0, tslib.__spreadArray(tslib.__spreadArray([], dialogClasses, false), [datePickerClassNames.smallScreen, (_b = {}, _b[datePickerClassNames.smallScreenHidden] = !isOpen, _b)], false))
}, /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDivWithRef, tslib.__assign({
role: "dialog",
forwardedRef: smallScreenAppRef,
className: classnames__default.default(datePickerClassNames.smallScreenContainer, (_c = {}, _c[datePickerClassNames.smallScreenScroll] = smallScreenScroll, _c)),
onPointerDown: handlePointerDown,
onPointerMove: handlePointerMove,
onPointerUp: handlePointerUp,
onPointerLeave: handlePointerUp,
onTouchStart: handleTouchStart,
onTouchEnd: handleTouchEnd
}, passProps), /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDivWithRef, {
className: datePickerClassNames.slideIndicatorWrapper,
forwardedRef: sliderWrapperRef
}, /*#__PURE__*/React__default.default.createElement("div", {
className: datePickerClassNames.slideIndicator
})), application));
if (!mountNode) {
return null;
}
return /*#__PURE__*/React__default.default.createElement(React__default.default.Fragment, null, /*#__PURE__*/ReactDOM__default.default.createPortal(smallScreen ? smallScreenDialog : defaultDialog, mountNode));
};
var StyledDatePicker = styled.styled(function (_a) {
_a.theme;
var passProps = tslib.__rest(_a, ["theme"]);
return /*#__PURE__*/React__default.default.createElement(BaseDatePicker, tslib.__assign({}, passProps));
}).withConfig({
componentId: "sc-e4ujoe-0"
})(templateObject_1 || (templateObject_1 = tslib.__makeTemplateObject(["\n ", "\n"], ["\n ", "\n"])), function (_a) {
var theme = _a.theme;
return DatePicker_baseStyles.baseStyles(theme);
});
var DatePicker = function DatePicker(props) {
return /*#__PURE__*/React__default.default.createElement(SuomifiThemeProvider.SuomifiThemeConsumer, null, function (_a) {
var suomifiTheme = _a.suomifiTheme;
return /*#__PURE__*/React__default.default.createElement(StyledDatePicker, tslib.__assign({
theme: suomifiTheme
}, props));
});
};
DatePicker.displayName = 'DatePicker';
var templateObject_1;
exports.BaseDatePicker = BaseDatePicker;
exports.DatePicker = DatePicker;
exports.datePickerClassNames = datePickerClassNames;
//# sourceMappingURL=DatePicker.js.map