UNPKG

@carbon/react

Version:

React components for the Carbon Design System

133 lines (131 loc) 5.06 kB
/** * Copyright IBM Corp. 2016, 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ const require_keys = require("../../../internal/keyboard/keys.js"); const require_match = require("../../../internal/keyboard/match.js"); //#region src/components/DatePicker/plugins/fixEventsPlugin.ts const fixEventsPlugin = (config) => (fp) => { const { inputFrom, inputTo, lastStartValue, container } = config; let mouseDownInside = false; const getEventPath = (event) => typeof event.composedPath === "function" ? event.composedPath() : []; const isEventInside = (event) => { const path = getEventPath(event); const { target } = event; if (!(target instanceof Node)) return false; return Boolean(container && (path.includes(container) || container.contains(target)) || fp.calendarContainer && (path.includes(fp.calendarContainer) || fp.calendarContainer.contains(target)) || inputFrom && (path.includes(inputFrom) || inputFrom.contains(target)) || inputTo && (path.includes(inputTo) || inputTo.contains(target))); }; /** * Handles `click` outside to close calendar */ const handleClickOutside = (event) => { if (mouseDownInside) { mouseDownInside = false; return; } if (!fp.isOpen || isEventInside(event)) { mouseDownInside = false; return; } mouseDownInside = false; fp.close(); }; /** * Tracks the initial mouse target to avoid closing on click after scroll. */ const handleMouseDown = (event) => { mouseDownInside = isEventInside(event); }; /** * Handles `keydown` event. */ const handleKeydown = (event) => { const { target } = event; if (inputFrom === target || inputTo === target) { if (require_match.match(event, require_keys.Enter)) { mouseDownInside = false; fp.setDate(inputTo ? [inputFrom.value, inputTo.value] : [inputFrom.value], true, fp.config.dateFormat); event.stopPropagation(); if (inputTo === target && fp.config.closeOnSelect) requestAnimationFrame(() => { fp.close(); }); } else if (require_match.match(event, require_keys.ArrowLeft) || require_match.match(event, require_keys.ArrowRight)) event.stopPropagation(); else if (require_match.match(event, require_keys.ArrowDown)) { event.preventDefault(); fp.open(); } else if (!fp.config.allowInput) { event.stopPropagation(); event.preventDefault(); } } }; const parseDateWithFormat = (dateStr) => fp.parseDate(dateStr, fp.config.dateFormat); /** * Handles `blur` event. * * For whatever reason, manual changes within the `to` input do not update the * calendar on blur. If a manual change is made within the input, this block will * set the date again, triggering the calendar to update. */ const handleBlur = (event) => { const { target } = event; if (!inputTo) return; if (inputTo === target && fp.selectedDates[1]) { const withoutTime = (date) => date?.setHours(0, 0, 0, 0); const selectedToDate = withoutTime(new Date(fp.selectedDates[1])); const currentValueToDate = withoutTime(parseDateWithFormat(inputTo.value)); if (selectedToDate && currentValueToDate && selectedToDate !== currentValueToDate) fp.setDate([inputFrom.value, inputTo.value], true, fp.config.dateFormat); } const isValidDate = (date) => date?.toString() !== "Invalid Date"; if (inputTo === target && fp.selectedDates.length === 1 && inputTo.value) { if (isValidDate(parseDateWithFormat(inputTo.value))) fp.setDate([inputFrom.value, inputTo.value], true, fp.config.dateFormat); } if (inputTo === target && !inputFrom.value && lastStartValue.current) { if (isValidDate(parseDateWithFormat(lastStartValue.current))) { inputFrom.value = lastStartValue.current; if (inputTo.value) fp.setDate([inputFrom.value, inputTo.value], true, fp.config.dateFormat); } } }; /** * Releases event listeners used in this Flatpickr plugin. */ const release = () => { const { inputFrom, inputTo } = config; if (inputTo) { inputTo.removeEventListener("keydown", handleKeydown, true); inputTo.removeEventListener("blur", handleBlur, true); } inputFrom.removeEventListener("keydown", handleKeydown, true); document.removeEventListener("mousedown", handleMouseDown, true); document.removeEventListener("click", handleClickOutside, true); }; /** * Sets up event listeners used for this Flatpickr plugin. */ const init = () => { release(); const { inputFrom, inputTo } = config; inputFrom.addEventListener("keydown", handleKeydown, true); if (inputTo) { inputTo.addEventListener("keydown", handleKeydown, true); inputTo.addEventListener("blur", handleBlur, true); } document.addEventListener("mousedown", handleMouseDown, true); document.addEventListener("click", handleClickOutside, true); }; /** * Registers this Flatpickr plugin. */ const register = () => { fp.loadedPlugins.push("carbonFlatpickrFixEventsPlugin"); }; return { onReady: [register, init], onDestroy: [release] }; }; //#endregion exports.default = fixEventsPlugin;