UNPKG

suomifi-ui-components

Version:
485 lines (479 loc) 19.9 kB
'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