UNPKG

react-anpicker

Version:

a react date picker for supporting persian dates

211 lines (210 loc) 10.8 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useRef, useEffect } from "react"; import Days from "./days"; import { getMonthName } from "./helpers"; import { Modes } from "./Models/MainProps"; import faLocale from "./Locales/faLocale"; import Years from "./Years"; import Monthes from "./Monthes"; import Sidebar from "./Sidebar"; import ChevronIcon from "./ChevronIcon"; import { createPortal } from "react-dom"; import useControl from "./Hooks/useControl"; // function isMobile() { // if ( // ("navigator" in window && window.navigator.userAgent.match(/Android/i)) || // window.navigator.userAgent.match(/webOS/i) || // window.navigator.userAgent.match(/iPhone/i) || // window.navigator.userAgent.match(/iPad/i) || // window.navigator.userAgent.match(/iPod/i) || // window.navigator.userAgent.match(/BlackBerry/i) || // window.navigator.userAgent.match(/Windows Phone/i) // ) { // return true; // } else { // return false; // } // } export const AnPicker = ({ className = "", onChange, value = "", showTodayBottom = true, locale = faLocale, showSidebar = true, inputControl: Input, popupParentRef, popupVPosition, popupHPosition, }) => { const inputRef = useRef(null); const anPickerRef = useRef(null); const popupRef = useRef(null); const { state, tempValue, toggle, handleFocus, handleBlure, setPopupStyles, handleChange, setMode, nextYear, prevYear, nextMonth, prevMonth, onSelectYear, onSelectMonth, onSelectDay, setToday, } = useControl({ anPickerRef, inputRef: inputRef, locale: locale, value: value, onChange, }); // function getRelativeTop(child: HTMLElement, ancestor: HTMLElement) { // const childRect = child.getBoundingClientRect(); // const ancestorRect = ancestor.getBoundingClientRect(); // return childRect.top - ancestorRect.top + ancestor.scrollTop; // } const adjustPosition = () => { const popupParent = popupParentRef ? popupParentRef.current : null; const inputEl = anPickerRef.current; const popupEl = popupRef.current; if (!inputEl || !popupEl) return; const inputRect = inputEl.getBoundingClientRect(); const mobileMode = document.documentElement.clientWidth < 1200; const popupHeight = 268 - (showTodayBottom ? 6 : 0); const popupWidth = mobileMode ? 272 : 422; //const scrollTop = window.scrollY || document.documentElement.scrollTop; const scrollLeft = window.scrollX || document.documentElement.scrollLeft; let spaceAbove; let spaceBelow; let parentRect; if (popupParent) { parentRect = popupParent.getBoundingClientRect(); spaceAbove = inputRect.top - parentRect.top; spaceBelow = parentRect.bottom - inputRect.bottom; } else { spaceAbove = inputRect.top; spaceBelow = window.innerHeight - inputRect.bottom; } const showAbove = typeof popupVPosition !== "undefined" ? popupVPosition === "top" : spaceBelow < popupHeight && spaceAbove > popupHeight; let top = "auto"; let bottom = "auto"; if (popupParent) { const relativeTop = inputRect.top - parentRect.top + popupParent.scrollTop; if (showAbove) { bottom = parentRect.bottom - inputRect.top; } else { top = relativeTop + inputEl.offsetHeight; } } else { if (showAbove) { bottom = window.innerHeight - inputRect.top; } else { top = inputRect.bottom; } } //=== H position let left = "auto"; let right = "auto"; let spaceOnLeft; let spaceOnRight; if (popupParent) { spaceOnLeft = inputRect.right - parentRect.left; spaceOnRight = parentRect.right - inputRect.left; // console.log({ // spaceOnLeft, // spaceOnRight, // parentRect: { // width: parentRect!.width, // left: parentRect!.left, // right: parentRect!.right, // }, // }); } else { spaceOnLeft = inputRect.right; spaceOnRight = window.innerWidth - inputRect.left; } // console.log({ // spaceOnLeft, // spaceOnRight, // }); const showRight = typeof popupHPosition !== "undefined" ? popupHPosition === "left" : spaceOnRight > popupWidth && spaceOnLeft < popupWidth; console.log("showRight", showRight); // const showOnLeft = if (popupParent) { if (!showRight) { right = parentRect.right - inputRect.right; } else { left = inputRect.left - parentRect.left; } } else { //const spaceOnLeft = inputRect.right; if (!showRight) { right = document.documentElement.clientWidth - inputRect.right; } else { left = inputRect.left + scrollLeft; } } setPopupStyles({ top, bottom, left, right, visibility: "visible", }); }; useEffect(() => { if (!state.open) return; // Initial adjustment adjustPosition(); const observer = new IntersectionObserver((entries) => { const entry = entries[0]; if (entry && entry.isIntersecting) { adjustPosition(); } }, { root: null, threshold: 0.1, }); const inputEl = anPickerRef.current; if (inputEl) observer.observe(inputEl); const scrollableParents = []; // Find scrollable ancestors and attach scroll event listeners let parent = inputEl === null || inputEl === void 0 ? void 0 : inputEl.parentElement; while (parent) { const overflowY = window.getComputedStyle(parent).overflowY; if (overflowY === "scroll" || overflowY === "auto") { scrollableParents.push(parent); parent.addEventListener("scroll", adjustPosition); } parent = parent.parentElement; } // Also listen to window scroll window.addEventListener("scroll", adjustPosition, true); return () => { if (inputEl) observer.unobserve(inputEl); scrollableParents.forEach((p) => { p.removeEventListener("scroll", adjustPosition); }); window.removeEventListener("scroll", adjustPosition, true); }; }, [state.open]); useEffect(() => { const handleClickOutside = (e) => { var _a, _b; if (!((_a = anPickerRef.current) === null || _a === void 0 ? void 0 : _a.contains(e.target)) && !((_b = popupRef.current) === null || _b === void 0 ? void 0 : _b.contains(e.target))) { toggle(false); } }; // const onScrolled = function () { // if (isMobile()) adjustPosition(); // else { // toggle(false); // handleBlure(); // } // }; // document.addEventListener("scroll", onScrolled); document.addEventListener("click", handleClickOutside); return () => { //document.removeEventListener("scroll", onScrolled); document.removeEventListener("click", handleClickOutside); }; }, []); return (_jsxs("div", Object.assign({ className: `anpicker ${className}`, ref: anPickerRef, dir: locale.rtl ? "rtl" : "ltr" }, { children: [Input ? (_jsx(Input, { ref: inputRef, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlure, value: tempValue !== null && tempValue !== void 0 ? tempValue : "" })) : (_jsx("input", { ref: inputRef, value: tempValue !== null && tempValue !== void 0 ? tempValue : "", onChange: handleChange, onFocus: handleFocus, onBlur: handleBlure })), state.open ? createPortal(_jsxs("div", Object.assign({ className: `anpicker-popup${popupParentRef ? "" : " fixed"}`, ref: popupRef, style: state.popupStyle, dir: locale.rtl ? "rtl" : "ltr" }, { children: [showSidebar ? (_jsx(Sidebar, { locale: locale, localYear: state.year, localMonth: state.month, localDay: state.day })) : null, _jsxs("div", Object.assign({ className: "main" }, { children: [_jsxs("div", Object.assign({ className: "selector-heading" }, { children: [_jsxs("div", Object.assign({ className: "monthes" }, { children: [_jsx("a", Object.assign({ className: "next", onClick: nextMonth, role: "button" }, { children: _jsx(ChevronIcon, { type: "next", rtl: locale.rtl }) })), _jsx("a", Object.assign({ role: "button", onClick: () => setMode(Modes.monthes) }, { children: getMonthName(locale.convertToDate(state.year, state.month, state.day), locale.name) })), _jsx("a", Object.assign({ className: "prev", onClick: prevMonth, role: "button" }, { children: _jsx(ChevronIcon, { type: "prev", rtl: locale.rtl }) }))] })), _jsxs("div", Object.assign({ className: "years" }, { children: [_jsx("a", Object.assign({ className: "next", onClick: nextYear, role: "button" }, { children: _jsx(ChevronIcon, { type: "next", rtl: locale.rtl }) })), _jsx("a", Object.assign({ role: "button", onClick: () => setMode(Modes.years) }, { children: state.year })), _jsx("a", Object.assign({ className: "prev", onClick: prevYear, role: "button" }, { children: _jsx(ChevronIcon, { type: "prev", rtl: locale.rtl }) }))] }))] })), _jsx(Years, { hidden: state.mode !== Modes.years, locale: locale, pageNumber: state.yearPageNumber, onSelectYear: onSelectYear, localYear: state.year }), _jsx(Monthes, { hidden: state.mode !== Modes.monthes, locale: locale, onSelect: onSelectMonth, localMonth: state.month }), _jsx(Days, { hidden: state.mode !== Modes.days, locale: locale, localYear: state.year, localMonth: state.month, localDay: state.day, onSelect: onSelectDay }), showTodayBottom && (_jsx("button", Object.assign({ className: "today-button", onClick: setToday }, { children: locale.todayButtonText })))] }))] })), (popupParentRef === null || popupParentRef === void 0 ? void 0 : popupParentRef.current) ? popupParentRef.current : document.body) : null] }))); };