react-anpicker
Version:
a react date picker for supporting persian dates
152 lines (151 loc) • 9.51 kB
JavaScript
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, popupTargetId, }) => {
var _a;
const inputRef = useRef(null);
const anPickerRef = useRef(null);
const popupRef = useRef(null);
const popupTarget = 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,
});
const adjustPosition = () => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
popupTarget.current = popupTargetId
? document.getElementById(popupTargetId)
: document.body;
const inputRect = (_a = anPickerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
const popupRect = (_b = popupRef.current) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
const parent = popupTargetId
? document.getElementById(popupTargetId)
: null;
const parentRect = (_c = popupTarget.current) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect();
if (!popupRect || !inputRect)
return;
const scrollTop = window.scrollY || document.documentElement.scrollTop;
const scrollLeft = window.scrollX || document.documentElement.scrollLeft;
const inputOffsetTop = (_e = (_d = anPickerRef.current) === null || _d === void 0 ? void 0 : _d.offsetTop) !== null && _e !== void 0 ? _e : 0;
const inputOffsetLeft = (_g = (_f = anPickerRef.current) === null || _f === void 0 ? void 0 : _f.offsetLeft) !== null && _g !== void 0 ? _g : 0;
const topScroll = popupTargetId && popupTarget.current
? popupTarget.current.scrollTop
: scrollTop;
const leftScroll = popupTargetId && popupTarget.current
? popupTarget.current.scrollLeft
: scrollLeft;
const visibleTopOffset = inputOffsetTop - topScroll;
const visibleLeftOffset = inputOffsetLeft + ((_j = (_h = anPickerRef.current) === null || _h === void 0 ? void 0 : _h.clientWidth) !== null && _j !== void 0 ? _j : 0) - leftScroll;
const popupHeight = 230 + (showTodayBottom ? 38 : 0);
const popupWidth = 272 + (showSidebar ? 170 : 0);
//const offsetHeight = popupTargetId && popupTarget.current ? popupTarget.current.offsetHeight - popupTarget.current.clientHeight : 0
const offsetWidth = popupTargetId && popupTarget.current
? popupTarget.current.offsetWidth - popupTarget.current.clientWidth
: 0;
const h = window.innerHeight;
const w = window.innerWidth;
let left = "auto";
let right = "auto";
let top = "auto";
//console.log("top",parentRect,popupTarget.current,scrollTop,topScroll)
if (popupTargetId && parentRect) {
const verticallScrollWidth = parent
? (parent === null || parent === void 0 ? void 0 : parent.offsetWidth) - (parent === null || parent === void 0 ? void 0 : parent.clientWidth)
: 0;
if (visibleLeftOffset >= popupWidth) {
left =
inputOffsetLeft -
offsetWidth +
((_l = (_k = anPickerRef.current) === null || _k === void 0 ? void 0 : _k.clientWidth) !== null && _l !== void 0 ? _l : inputRect.width) -
popupWidth;
right = "auto";
}
else {
left = inputOffsetLeft - verticallScrollWidth;
right = "auto";
}
if (visibleTopOffset >= popupHeight) {
top = inputOffsetTop - popupRect.height;
}
else {
top = inputOffsetTop + inputRect.height;
}
}
else {
if (inputRect.left + scrollLeft + popupRect.width > w) {
left = inputRect.right - popupRect.width;
}
else {
left = inputRect.left + scrollLeft;
}
top =
(inputRect.top + inputRect.height + popupRect.height > h
? inputRect.top - popupRect.height
: inputRect.top + inputRect.height) + scrollTop;
}
setPopupStyles({
top,
left,
right,
position: "absolute",
visibility: "visible",
});
};
useEffect(() => {
if (state.open) {
adjustPosition();
}
}, [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", 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 })))] }))] })), (_a = popupTarget.current) !== null && _a !== void 0 ? _a : document.body)
: null] })));
};