UNPKG

suomifi-ui-components

Version:
492 lines (486 loc) 19.7 kB
'use strict'; var tslib = require('tslib'); var React = require('react'); var ReactDOM = require('react-dom'); var styledComponents = require('styled-components'); var reactPopper = require('react-popper'); 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'); 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"), popperArrow: "".concat(baseClassName, "_popper-arrow") }; var BaseDatePicker = function BaseDatePicker(props) { var _a, _b, _c; var _d; 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, _e = props.userProps, userProps = _e === void 0 ? {} : _e; var _f = React.useState(null), mountNode = _f[0], setMountNode = _f[1]; var _g = React.useState(null), dialogElement = _g[0], setDialogElement = _g[1]; var _h = React.useState(false), hasPopperEventListeners = _h[0], setHasPopperEventListeners = _h[1]; var _j = React.useState(new Date()), focusableDate = _j[0], setFocusableDate = _j[1]; var _k = React.useState(null), focusedDate = _k[0], setFocusedDate = _k[1]; var _l = React.useState(null), selectedDate = _l[0], setSelectedDate = _l[1]; var _m = React.useState(0), yearSelectWidth = _m[0], setYearSelectWidth = _m[1]; var _o = React.useState(0), monthSelectWidth = _o[0], setMonthSelectWidth = _o[1]; var _p = React.useState(null), touchStartX = _p[0], setTouchStartX = _p[1]; var _q = React.useState(null), touchStartY = _q[0], setTouchStartY = _q[1]; var _r = React.useState(0), dragOffsetY = _r[0], setDragOffsetY = _r[1]; var _s = React.useState(false), dragging = _s[0], setDragging = _s[1]; var _t = React.useState(false), smallScreenScroll = _t[0], setSmallScreenScroll = _t[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); 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) { setHasPopperEventListeners(true); return function () { setHasPopperEventListeners(false); }; } 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 datePickerOffset = props.position === 'right' ? 322 : props.position === 'center' ? 160 : 0; var _u = reactPopper.usePopper(openButtonRef.current, dialogElement, { strategy: 'fixed', modifiers: [{ name: 'eventListeners', enabled: hasPopperEventListeners && !smallScreen }, { name: 'offset', options: { offset: [datePickerOffset, 10] } }, { name: 'flip', options: { fallbackPlacements: ['top-end'] } }, { name: 'preventOverflow', options: { padding: 5 } }], placement: 'bottom-end' }), styles = _u.styles, attributes = _u.attributes; 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: styles.popper, forwardedRef: setDialogElement }, passProps), application, /*#__PURE__*/React__default.default.createElement("div", { className: datePickerClassNames.popperArrow, style: styles.arrow, "data-popper-arrow": true, "data-popper-placement": (_d = attributes.popper) === null || _d === void 0 ? void 0 : _d['data-popper-placement'] })); 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 = styledComponents.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