UNPKG

react-datetime-picker

Version:
290 lines (289 loc) 17.4 kB
"use strict"; 'use client'; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(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); }; var __rest = (this && this.__rest) || function (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; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var jsx_runtime_1 = require("react/jsx-runtime"); var react_1 = require("react"); var react_dom_1 = require("react-dom"); var make_event_props_1 = __importDefault(require("make-event-props")); var clsx_1 = __importDefault(require("clsx")); var react_calendar_1 = __importDefault(require("react-calendar")); var react_clock_1 = __importDefault(require("react-clock")); var react_fit_1 = __importDefault(require("react-fit")); var DateTimeInput_js_1 = __importDefault(require("./DateTimeInput.js")); var baseClassName = 'react-datetime-picker'; var outsideActionEvents = ['mousedown', 'focusin', 'touchstart']; var allViews = ['hour', 'minute', 'second']; var iconProps = { xmlns: 'http://www.w3.org/2000/svg', width: 19, height: 19, viewBox: '0 0 19 19', stroke: 'black', strokeWidth: 2, }; var CalendarIcon = ((0, jsx_runtime_1.jsxs)("svg", __assign({}, iconProps, { className: "".concat(baseClassName, "__calendar-button__icon ").concat(baseClassName, "__button__icon"), children: [(0, jsx_runtime_1.jsx)("rect", { fill: "none", height: "15", width: "15", x: "2", y: "2" }), (0, jsx_runtime_1.jsx)("line", { x1: "6", x2: "6", y1: "0", y2: "4" }), (0, jsx_runtime_1.jsx)("line", { x1: "13", x2: "13", y1: "0", y2: "4" })] }))); var ClearIcon = ((0, jsx_runtime_1.jsxs)("svg", __assign({}, iconProps, { className: "".concat(baseClassName, "__clear-button__icon ").concat(baseClassName, "__button__icon"), children: [(0, jsx_runtime_1.jsx)("line", { x1: "4", x2: "15", y1: "4", y2: "15" }), (0, jsx_runtime_1.jsx)("line", { x1: "15", x2: "4", y1: "4", y2: "15" })] }))); function DateTimePicker(props) { var amPmAriaLabel = props.amPmAriaLabel, autoFocus = props.autoFocus, calendarAriaLabel = props.calendarAriaLabel, _a = props.calendarIcon, calendarIcon = _a === void 0 ? CalendarIcon : _a, className = props.className, clearAriaLabel = props.clearAriaLabel, _b = props.clearIcon, clearIcon = _b === void 0 ? ClearIcon : _b, _c = props.closeWidgets, shouldCloseWidgetsOnSelect = _c === void 0 ? true : _c, dataTestid = props["data-testid"], dayAriaLabel = props.dayAriaLabel, dayPlaceholder = props.dayPlaceholder, disableCalendar = props.disableCalendar, disableClock = props.disableClock, disabled = props.disabled, format = props.format, hourAriaLabel = props.hourAriaLabel, hourPlaceholder = props.hourPlaceholder, id = props.id, _d = props.isCalendarOpen, isCalendarOpenProps = _d === void 0 ? null : _d, _e = props.isClockOpen, isClockOpenProps = _e === void 0 ? null : _e, locale = props.locale, maxDate = props.maxDate, _f = props.maxDetail, maxDetail = _f === void 0 ? 'minute' : _f, minDate = props.minDate, minuteAriaLabel = props.minuteAriaLabel, minutePlaceholder = props.minutePlaceholder, monthAriaLabel = props.monthAriaLabel, monthPlaceholder = props.monthPlaceholder, _g = props.name, name = _g === void 0 ? 'datetime' : _g, nativeInputAriaLabel = props.nativeInputAriaLabel, onCalendarClose = props.onCalendarClose, onCalendarOpen = props.onCalendarOpen, onChangeProps = props.onChange, onClockClose = props.onClockClose, onClockOpen = props.onClockOpen, onFocusProps = props.onFocus, onInvalidChange = props.onInvalidChange, _h = props.openWidgetsOnFocus, openWidgetsOnFocus = _h === void 0 ? true : _h, required = props.required, secondAriaLabel = props.secondAriaLabel, secondPlaceholder = props.secondPlaceholder, shouldCloseWidgets = props.shouldCloseWidgets, shouldOpenWidgets = props.shouldOpenWidgets, showLeadingZeros = props.showLeadingZeros, value = props.value, yearAriaLabel = props.yearAriaLabel, yearPlaceholder = props.yearPlaceholder, otherProps = __rest(props, ["amPmAriaLabel", "autoFocus", "calendarAriaLabel", "calendarIcon", "className", "clearAriaLabel", "clearIcon", "closeWidgets", 'data-testid', "dayAriaLabel", "dayPlaceholder", "disableCalendar", "disableClock", "disabled", "format", "hourAriaLabel", "hourPlaceholder", "id", "isCalendarOpen", "isClockOpen", "locale", "maxDate", "maxDetail", "minDate", "minuteAriaLabel", "minutePlaceholder", "monthAriaLabel", "monthPlaceholder", "name", "nativeInputAriaLabel", "onCalendarClose", "onCalendarOpen", "onChange", "onClockClose", "onClockOpen", "onFocus", "onInvalidChange", "openWidgetsOnFocus", "required", "secondAriaLabel", "secondPlaceholder", "shouldCloseWidgets", "shouldOpenWidgets", "showLeadingZeros", "value", "yearAriaLabel", "yearPlaceholder"]); var _j = (0, react_1.useState)(isCalendarOpenProps), isCalendarOpen = _j[0], setIsCalendarOpen = _j[1]; var _k = (0, react_1.useState)(isClockOpenProps), isClockOpen = _k[0], setIsClockOpen = _k[1]; var wrapper = (0, react_1.useRef)(null); var calendarWrapper = (0, react_1.useRef)(null); var clockWrapper = (0, react_1.useRef)(null); (0, react_1.useEffect)(function () { setIsCalendarOpen(isCalendarOpenProps); }, [isCalendarOpenProps]); (0, react_1.useEffect)(function () { setIsClockOpen(isClockOpenProps); }, [isClockOpenProps]); function openCalendar(_a) { var reason = _a.reason; if (shouldOpenWidgets) { if (!shouldOpenWidgets({ reason: reason, widget: 'calendar' })) { return; } } setIsClockOpen(isClockOpen ? false : isClockOpen); setIsCalendarOpen(true); if (onCalendarOpen) { onCalendarOpen(); } } var closeCalendar = (0, react_1.useCallback)(function (_a) { var reason = _a.reason; if (shouldCloseWidgets) { if (!shouldCloseWidgets({ reason: reason, widget: 'calendar' })) { return; } } setIsCalendarOpen(false); if (onCalendarClose) { onCalendarClose(); } }, [onCalendarClose, shouldCloseWidgets]); function toggleCalendar() { if (isCalendarOpen) { closeCalendar({ reason: 'buttonClick' }); } else { openCalendar({ reason: 'buttonClick' }); } } function openClock(_a) { var reason = _a.reason; if (shouldOpenWidgets) { if (!shouldOpenWidgets({ reason: reason, widget: 'clock' })) { return; } } setIsCalendarOpen(isCalendarOpen ? false : isCalendarOpen); setIsClockOpen(true); if (onClockOpen) { onClockOpen(); } } var closeClock = (0, react_1.useCallback)(function (_a) { var reason = _a.reason; if (shouldCloseWidgets) { if (!shouldCloseWidgets({ reason: reason, widget: 'clock' })) { return; } } setIsClockOpen(false); if (onClockClose) { onClockClose(); } }, [onClockClose, shouldCloseWidgets]); var closeWidgets = (0, react_1.useCallback)(function (_a) { var reason = _a.reason; closeCalendar({ reason: reason }); closeClock({ reason: reason }); }, [closeCalendar, closeClock]); function onChange(value, shouldCloseWidgets) { if (shouldCloseWidgets === void 0) { shouldCloseWidgets = shouldCloseWidgetsOnSelect; } if (shouldCloseWidgets) { closeWidgets({ reason: 'select' }); } if (onChangeProps) { onChangeProps(value); } } function onDateChange(nextValue, shouldCloseWidgets) { // React-Calendar passes an array of values when selectRange is enabled var nextValueFrom = (Array.isArray(nextValue) ? nextValue : [nextValue])[0]; var valueFrom = (Array.isArray(value) ? value : [value])[0]; if (valueFrom && nextValueFrom) { var valueFromDate = new Date(valueFrom); var nextValueFromWithHour = new Date(nextValueFrom); nextValueFromWithHour.setHours(valueFromDate.getHours(), valueFromDate.getMinutes(), valueFromDate.getSeconds(), valueFromDate.getMilliseconds()); onChange(nextValueFromWithHour, shouldCloseWidgets); } else { onChange(nextValueFrom, shouldCloseWidgets); } } function onFocus(event) { if (onFocusProps) { onFocusProps(event); } if ( // Internet Explorer still fires onFocus on disabled elements disabled || !openWidgetsOnFocus || event.target.dataset.select === 'true') { return; } switch (event.target.name) { case 'day': case 'month': case 'year': { if (isCalendarOpen) { return; } openCalendar({ reason: 'focus' }); break; } case 'hour12': case 'hour24': case 'minute': case 'second': { if (isClockOpen) { return; } openClock({ reason: 'focus' }); break; } default: } } var onKeyDown = (0, react_1.useCallback)(function (event) { if (event.key === 'Escape') { closeWidgets({ reason: 'escape' }); } }, [closeWidgets]); function clear() { onChange(null); } function stopPropagation(event) { event.stopPropagation(); } var onOutsideAction = (0, react_1.useCallback)(function (event) { var wrapperEl = wrapper.current; var calendarWrapperEl = calendarWrapper.current; var clockWrapperEl = clockWrapper.current; // Try event.composedPath first to handle clicks inside a Shadow DOM. var target = ('composedPath' in event ? event.composedPath()[0] : event.target); if (target && wrapperEl && !wrapperEl.contains(target) && (!calendarWrapperEl || !calendarWrapperEl.contains(target)) && (!clockWrapperEl || !clockWrapperEl.contains(target))) { closeWidgets({ reason: 'outsideAction' }); } }, [calendarWrapper, clockWrapper, closeWidgets, wrapper]); var handleOutsideActionListeners = (0, react_1.useCallback)(function (shouldListen) { if (shouldListen === void 0) { shouldListen = isCalendarOpen || isClockOpen; } outsideActionEvents.forEach(function (event) { if (shouldListen) { document.addEventListener(event, onOutsideAction); } else { document.removeEventListener(event, onOutsideAction); } }); if (shouldListen) { document.addEventListener('keydown', onKeyDown); } else { document.removeEventListener('keydown', onKeyDown); } }, [isCalendarOpen, isClockOpen, onOutsideAction, onKeyDown]); (0, react_1.useEffect)(function () { handleOutsideActionListeners(); return function () { handleOutsideActionListeners(false); }; }, [handleOutsideActionListeners]); function renderInputs() { var valueFrom = (Array.isArray(value) ? value : [value])[0]; var ariaLabelProps = { amPmAriaLabel: amPmAriaLabel, dayAriaLabel: dayAriaLabel, hourAriaLabel: hourAriaLabel, minuteAriaLabel: minuteAriaLabel, monthAriaLabel: monthAriaLabel, nativeInputAriaLabel: nativeInputAriaLabel, secondAriaLabel: secondAriaLabel, yearAriaLabel: yearAriaLabel, }; var placeholderProps = { dayPlaceholder: dayPlaceholder, hourPlaceholder: hourPlaceholder, minutePlaceholder: minutePlaceholder, monthPlaceholder: monthPlaceholder, secondPlaceholder: secondPlaceholder, yearPlaceholder: yearPlaceholder, }; return ((0, jsx_runtime_1.jsxs)("div", { className: "".concat(baseClassName, "__wrapper"), children: [(0, jsx_runtime_1.jsx)(DateTimeInput_js_1.default, __assign({}, ariaLabelProps, placeholderProps, { // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus: autoFocus, className: "".concat(baseClassName, "__inputGroup"), disabled: disabled, format: format, isWidgetOpen: isCalendarOpen || isClockOpen, locale: locale, maxDate: maxDate, maxDetail: maxDetail, minDate: minDate, name: name, onChange: onChange, onInvalidChange: onInvalidChange, required: required, showLeadingZeros: showLeadingZeros, value: valueFrom })), clearIcon !== null && ((0, jsx_runtime_1.jsx)("button", { "aria-label": clearAriaLabel, className: "".concat(baseClassName, "__clear-button ").concat(baseClassName, "__button"), disabled: disabled, onClick: clear, onFocus: stopPropagation, type: "button", children: typeof clearIcon === 'function' ? (0, react_1.createElement)(clearIcon) : clearIcon })), calendarIcon !== null && !disableCalendar && ((0, jsx_runtime_1.jsx)("button", { "aria-expanded": isCalendarOpen || false, "aria-label": calendarAriaLabel, className: "".concat(baseClassName, "__calendar-button ").concat(baseClassName, "__button"), disabled: disabled, onClick: toggleCalendar, onFocus: stopPropagation, type: "button", children: typeof calendarIcon === 'function' ? (0, react_1.createElement)(calendarIcon) : calendarIcon }))] })); } function renderCalendar() { if (isCalendarOpen === null || disableCalendar) { return null; } var calendarProps = props.calendarProps, portalContainer = props.portalContainer, value = props.value; var className = "".concat(baseClassName, "__calendar"); var classNames = (0, clsx_1.default)(className, "".concat(className, "--").concat(isCalendarOpen ? 'open' : 'closed')); var calendar = ((0, jsx_runtime_1.jsx)(react_calendar_1.default, __assign({ locale: locale, maxDate: maxDate, minDate: minDate, onChange: function (value) { return onDateChange(value); }, value: value }, calendarProps))); return portalContainer ? ((0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)("div", { ref: calendarWrapper, className: classNames, children: calendar }), portalContainer)) : ((0, jsx_runtime_1.jsx)(react_fit_1.default, { children: (0, jsx_runtime_1.jsx)("div", { ref: function (ref) { if (ref && !isCalendarOpen) { ref.removeAttribute('style'); } }, className: classNames, children: calendar }) })); } function renderClock() { if (isClockOpen === null || disableClock) { return null; } var clockProps = props.clockProps, _a = props.maxDetail, maxDetail = _a === void 0 ? 'minute' : _a, portalContainer = props.portalContainer, value = props.value; var className = "".concat(baseClassName, "__clock"); var classNames = (0, clsx_1.default)(className, "".concat(className, "--").concat(isClockOpen ? 'open' : 'closed')); var valueFrom = (Array.isArray(value) ? value : [value])[0]; var maxDetailIndex = allViews.indexOf(maxDetail); var clock = ((0, jsx_runtime_1.jsx)(react_clock_1.default, __assign({ locale: locale, renderMinuteHand: maxDetailIndex > 0, renderSecondHand: maxDetailIndex > 1, value: valueFrom }, clockProps))); return portalContainer ? ((0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)("div", { ref: clockWrapper, className: classNames, children: clock }), portalContainer)) : ((0, jsx_runtime_1.jsx)(react_fit_1.default, { children: (0, jsx_runtime_1.jsx)("div", { ref: function (ref) { if (ref && !isClockOpen) { ref.removeAttribute('style'); } }, className: classNames, children: clock }) })); } var eventProps = (0, react_1.useMemo)(function () { return (0, make_event_props_1.default)(otherProps); }, [otherProps]); return ((0, jsx_runtime_1.jsxs)("div", __assign({ className: (0, clsx_1.default)(baseClassName, "".concat(baseClassName, "--").concat(isCalendarOpen || isClockOpen ? 'open' : 'closed'), "".concat(baseClassName, "--").concat(disabled ? 'disabled' : 'enabled'), className), "data-testid": dataTestid, id: id }, eventProps, { onFocus: onFocus, ref: wrapper, children: [renderInputs(), renderCalendar(), renderClock()] }))); } exports.default = DateTimePicker;