UNPKG

nepali-date-utility

Version:

A beautiful React date picker component with other date utilities for Nepali Bikram Sambat calendar

809 lines (803 loc) 28.4 kB
import { useState, useRef, useEffect } from 'react'; import { jsxs, jsx } from 'react/jsx-runtime'; import { twMerge, twJoin } from 'tailwind-merge'; // Nepali Date Utility- Beautiful React component for Nepali Bikram Sambat calendar // src/data/bs-calendar.ts var bsCalendarData = { 2e3: [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2001: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2002: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2003: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2004: [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2005: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2006: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2007: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2008: [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31], 2009: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2010: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2011: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2012: [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], 2013: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2014: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2015: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2016: [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], 2017: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2018: [31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2019: [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2020: [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], 2021: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2022: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], 2023: [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2024: [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], 2025: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2026: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2027: [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2028: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2029: [31, 31, 32, 31, 32, 30, 30, 29, 30, 29, 30, 30], 2030: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2031: [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2032: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2033: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2034: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2035: [30, 32, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31], 2036: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2037: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2038: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2039: [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], 2040: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2041: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2042: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2043: [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], 2044: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2045: [31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2046: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2047: [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], 2048: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2049: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], 2050: [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2051: [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], 2052: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2053: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], 2054: [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2055: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2056: [31, 31, 32, 31, 32, 30, 30, 29, 30, 29, 30, 30], 2057: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2058: [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2059: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2060: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2061: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2062: [30, 32, 31, 32, 31, 31, 29, 30, 29, 30, 29, 31], 2063: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2064: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2065: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2066: [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31], 2067: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2068: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2069: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2070: [31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], 2071: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2072: [31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], 2073: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2074: [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], 2075: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2076: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], 2077: [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2078: [31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], 2079: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2080: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], 2081: [31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2082: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2083: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2084: [31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], 2085: [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], 2086: [31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], 2087: [31, 31, 32, 31, 31, 31, 30, 30, 29, 30, 30, 30], 2088: [30, 31, 32, 32, 30, 31, 30, 30, 29, 30, 30, 30], 2089: [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], 2090: [30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30] }; var bsMonthsEn = [ "Baishakh", "Jestha", "Ashadh", "Shrawan", "Bhadra", "Ashwin", "Kartik", "Mangsir", "Poush", "Magh", "Falgun", "Chaitra" ]; var bsMonthsNe = [ "\u092C\u0948\u0936\u093E\u0916", "\u091C\u0947\u0937\u094D\u0920", "\u0906\u0937\u093E\u0922", "\u0936\u094D\u0930\u093E\u0935\u0923", "\u092D\u093E\u0926\u094D\u0930", "\u0906\u0936\u094D\u0935\u093F\u0928", "\u0915\u093E\u0930\u094D\u0924\u093F\u0915", "\u092E\u0902\u0938\u093F\u0930", "\u092A\u094C\u0937", "\u092E\u093E\u0918", "\u092B\u093E\u0932\u094D\u0917\u0941\u0928", "\u091A\u0948\u0924\u094D\u0930" ]; var bsDaysEn = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ]; var bsDaysNe = [ "\u0906\u0907\u0924\u092C\u093E\u0930", "\u0938\u094B\u092E\u092C\u093E\u0930", "\u092E\u0902\u0917\u0932\u092C\u093E\u0930", "\u092C\u0941\u0927\u092C\u093E\u0930", "\u092C\u093F\u0939\u093F\u092C\u093E\u0930", "\u0936\u0941\u0915\u094D\u0930\u092C\u093E\u0930", "\u0936\u0928\u093F\u092C\u093E\u0930" ]; var bsDaysShortEn = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; var bsDaysShortNe = [ "\u0906\u0907\u0924", "\u0938\u094B\u092E", "\u092E\u0902\u0917\u0932", "\u092C\u0941\u0927", "\u092C\u093F\u0939\u093F", "\u0936\u0941\u0915\u094D\u0930", "\u0936\u0928\u093F" ]; var nepaliDigits = ["\u0966", "\u0967", "\u0968", "\u0969", "\u096A", "\u096B", "\u096C", "\u096D", "\u096E", "\u096F"]; function toNepaliDigits(num) { return num.toString().split("").map((c) => { if (c >= "0" && c <= "9") { return nepaliDigits[parseInt(c)]; } return c; }).join(""); } // src/utils/converter.ts var bsEpoch = { year: 2e3, month: 1, day: 1 }; var adEpoch = new Date(1943, 3, 14); function daysBetweenDates(d1, d2) { const date1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate()); const date2 = new Date(d2.getFullYear(), d2.getMonth(), d2.getDate()); const msPerDay = 1e3 * 60 * 60 * 24; return Math.round((date2.getTime() - date1.getTime()) / msPerDay); } function convertADToBS(adDate) { const diffDays = daysBetweenDates(adEpoch, adDate); let bsYear = bsEpoch.year; let bsMonth = bsEpoch.month; let bsDay = bsEpoch.day; let remainingDays = diffDays; while (remainingDays > 0) { if (!bsCalendarData[bsYear]) { throw new Error( `Year ${bsYear} is outside the supported range (2000-2090)` ); } const daysInMonth = bsCalendarData[bsYear][bsMonth - 1]; if (typeof daysInMonth !== "number") { throw new Error( `Invalid calendar data for year ${bsYear}, month ${bsMonth}` ); } bsDay++; if (bsDay > daysInMonth) { bsDay = 1; bsMonth++; if (bsMonth > 12) { bsMonth = 1; bsYear++; } } remainingDays--; } return { year: bsYear, month: bsMonth, day: bsDay }; } function convertBSToAD(bsDate) { let bsYear = bsEpoch.year; let bsMonth = bsEpoch.month; let bsDay = bsEpoch.day; let adDate = new Date(adEpoch); while (bsYear !== bsDate.year || bsMonth !== bsDate.month || bsDay !== bsDate.day) { if (!bsCalendarData[bsYear]) { throw new Error( `Year ${bsYear} is outside the supported range (2000-2090)` ); } const daysInMonth = bsCalendarData[bsYear][bsMonth - 1]; if (typeof daysInMonth !== "number") { throw new Error( `Invalid calendar data for year ${bsYear}, month ${bsMonth}` ); } bsDay++; adDate.setDate(adDate.getDate() + 1); if (bsDay > daysInMonth) { bsDay = 1; bsMonth++; if (bsMonth > 12) { bsMonth = 1; bsYear++; } } } return { year: adDate.getFullYear(), month: adDate.getMonth() + 1, // JS months are 0-based, so add 1 day: adDate.getDate() }; } function getTodayBS() { return convertADToBS(/* @__PURE__ */ new Date()); } function getDaysInMonth(year, month) { if (!bsCalendarData[year]) { throw new Error(`Year ${year} is outside the supported range (2000-2090)`); } const daysInMonth = bsCalendarData[year][month - 1]; if (typeof daysInMonth !== "number") { throw new Error(`Invalid calendar data for year ${year}, month ${month}`); } return daysInMonth; } function isValidBsDate(date) { try { const { year, month, day } = date; if (!bsCalendarData[year]) return false; if (month < 1 || month > 12) return false; const daysInMonth = bsCalendarData[year][month - 1]; if (typeof daysInMonth !== "number") return false; if (day < 1 || day > daysInMonth) return false; return true; } catch (error) { return false; } } function isDateInRange(date, minDate, maxDate) { if (!isValidBsDate(date)) return false; if (minDate && compareDates(date, minDate) < 0) return false; if (maxDate && compareDates(date, maxDate) > 0) return false; return true; } function compareDates(a, b) { if (a.year !== b.year) return a.year - b.year; if (a.month !== b.month) return a.month - b.month; return a.day - b.day; } function getFirstDayOfMonth(bsYear, bsMonth) { const bsDate = { year: bsYear, month: bsMonth, day: 1 }; const adDate = convertBSToAD(bsDate); const jsDate = new Date(adDate.year, adDate.month - 1, adDate.day); return jsDate.getDay(); } function addMonths(date, months) { let { year, month, day } = date; month += months; while (month > 12) { month -= 12; year++; } while (month < 1) { month += 12; year--; } const maxDays = getDaysInMonth(year, month); if (day > maxDays) { day = maxDays; } return { year, month, day }; } // src/utils/formatter.ts function formatDate(date, options = {}) { const { format = "YYYY-MM-DD", locale = "en", separator = "-" } = options; if (!date) return ""; const { year, month, day } = date; const yearStr = year.toString(); const monthStr = month < 10 ? `0${month}` : month.toString(); const dayStr = day < 10 ? `0${day}` : day.toString(); let formatted = format.replace("YYYY", yearStr).replace("MM", monthStr).replace("DD", dayStr).replace("M", month.toString()).replace("D", day.toString()); if (format.includes("MMMM")) { const monthNames = locale === "ne" ? bsMonthsNe : bsMonthsEn; formatted = formatted.replace("MMMM", monthNames[month - 1]); } if (locale === "ne") { formatted = formatted.split("").map((char) => { if (char >= "0" && char <= "9") { return nepaliDigits[parseInt(char)]; } return char; }).join(""); } if (separator !== "-" && (format === "YYYY-MM-DD" || format === "DD-MM-YYYY")) { formatted = formatted.replace(/-/g, separator); } return formatted; } function parseDate(dateStr, format = "YYYY-MM-DD") { try { if (format === "YYYY-MM-DD") { const [yearStr, monthStr, dayStr] = dateStr.split("-"); return { year: parseInt(yearStr, 10), month: parseInt(monthStr, 10), day: parseInt(dayStr, 10) }; } if (format === "DD-MM-YYYY") { const [dayStr, monthStr, yearStr] = dateStr.split("-"); return { year: parseInt(yearStr, 10), month: parseInt(monthStr, 10), day: parseInt(dayStr, 10) }; } if (format === "MM/DD/YYYY") { const [monthStr, dayStr, yearStr] = dateStr.split("/"); return { year: parseInt(yearStr, 10), month: parseInt(monthStr, 10), day: parseInt(dayStr, 10) }; } if (format === "YYYY/MM/DD") { const [yearStr, monthStr, dayStr] = dateStr.split("/"); return { year: parseInt(yearStr, 10), month: parseInt(monthStr, 10), day: parseInt(dayStr, 10) }; } return null; } catch (error) { return null; } } var MonthNavigation = ({ viewDate, onViewDateChange, locale = "en" }) => { const [showYearDropdown, setShowYearDropdown] = useState(false); const [showMonthDropdown, setShowMonthDropdown] = useState(false); const monthNames = locale === "ne" ? bsMonthsNe : bsMonthsEn; const handlePrevMonth = () => { onViewDateChange(addMonths(viewDate, -1)); }; const handleNextMonth = () => { onViewDateChange(addMonths(viewDate, 1)); }; const handleYearSelect = (year) => { onViewDateChange({ ...viewDate, year }); setShowYearDropdown(false); }; const handleMonthSelect = (month) => { onViewDateChange({ ...viewDate, month }); setShowMonthDropdown(false); }; const yearOptions = Array.from({ length: 91 }, (_, i) => 2e3 + i); return /* @__PURE__ */ jsxs( "div", { className: `flex items-center justify-between p-2 border-b border-gray-300`, children: [ /* @__PURE__ */ jsx( "button", { type: "button", onClick: handlePrevMonth, className: "p-1 rounded-md hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500", "aria-label": "Previous month", children: /* @__PURE__ */ jsx( "svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", className: "w-5 h-5", children: /* @__PURE__ */ jsx( "path", { fillRule: "evenodd", d: "M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z", clipRule: "evenodd" } ) } ) } ), /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-1", children: [ /* @__PURE__ */ jsxs("div", { className: "relative", children: [ /* @__PURE__ */ jsx( "button", { type: "button", onClick: () => setShowMonthDropdown(!showMonthDropdown), className: "px-2 py-1 rounded-md hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 font-medium", children: monthNames[viewDate.month - 1] } ), showMonthDropdown && /* @__PURE__ */ jsx("div", { className: "absolute z-10 mt-1 w-max bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm", children: monthNames.map((month, index) => /* @__PURE__ */ jsx( "div", { onClick: () => handleMonthSelect(index + 1), className: `cursor-pointer select-none relative py-2 pl-3 pr-9 hover:bg-indigo-200 font-medium ${viewDate.month === index + 1 ? "bg-indigo-500 text-white hover:bg-indigo-500" : ""}`, children: month }, month )) }) ] }), /* @__PURE__ */ jsxs("div", { className: "relative", children: [ /* @__PURE__ */ jsx( "button", { type: "button", onClick: () => setShowYearDropdown(!showYearDropdown), className: "px-2 py-1 rounded-md hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 font-medium", children: locale === "ne" ? toNepaliDigits(viewDate.year) : viewDate.year } ), showYearDropdown && /* @__PURE__ */ jsx("div", { className: "absolute z-10 mt-1 w-max bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm", children: yearOptions.map((year) => /* @__PURE__ */ jsx( "div", { onClick: () => handleYearSelect(year), className: `cursor-pointer select-none relative py-2 pl-3 pr-9 hover:bg-indigo-200 ${viewDate.year === year ? "bg-indigo-500 text-white hover:bg-indigo-500" : ""}`, children: locale === "ne" ? toNepaliDigits(year) : year }, year )) }) ] }) ] }), /* @__PURE__ */ jsx( "button", { type: "button", onClick: handleNextMonth, className: "p-1 rounded-md hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500", "aria-label": "Next month", children: /* @__PURE__ */ jsx( "svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", className: "w-5 h-5", children: /* @__PURE__ */ jsx( "path", { fillRule: "evenodd", d: "M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z", clipRule: "evenodd" } ) } ) } ) ] } ); }; var MonthNavigation_default = MonthNavigation; var Calendar = ({ locale = "en", selectedDate, viewDate, onDateSelect, onViewDateChange, minDate, maxDate, calendarClassName, dayClassName, selectedDayClassName, todayClassName, disabledDayClassName }) => { const firstDayOfMonth = getFirstDayOfMonth(viewDate.year, viewDate.month); const daysInMonth = getDaysInMonth(viewDate.year, viewDate.month); const generateCalendarDays = () => { const days = []; const dayNames = locale === "ne" ? bsDaysShortNe : bsDaysShortEn; days.push( /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 mb-1", children: dayNames.map((day, index) => /* @__PURE__ */ jsx( "div", { className: twMerge( "relative h-8 w-8 flex items-center justify-center text-sm text-gray-800 font-medium hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500", dayClassName ), children: day }, `day-name-${index}` )) }, "day-names") ); const totalCells = Math.ceil((daysInMonth + firstDayOfMonth) / 7) * 7; let cells = []; for (let i = 0; i < totalCells; i++) { const dayOfMonth = i - firstDayOfMonth + 1; const isCurrentMonth = dayOfMonth > 0 && dayOfMonth <= daysInMonth; if (isCurrentMonth) { const date = { year: viewDate.year, month: viewDate.month, day: dayOfMonth }; const isSelected = selectedDate && compareDates(selectedDate, date) === 0; const isToday = compareDates(date, getTodayBS()) === 0; const isInRange = isDateInRange(date, minDate, maxDate); cells.push( /* @__PURE__ */ jsx( "button", { type: "button", disabled: !isInRange, onClick: () => isInRange && onDateSelect(date), className: twJoin( isSelected ? twMerge( "text-white cursor-not-allowed bg-indigo-500", selectedDayClassName ) : twMerge( "relative h-8 w-8 flex items-center justify-center text-sm text-gray-800 font-medium hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500", dayClassName ), isToday && !isSelected ? twMerge( "text-indigo-600 border-2 border-indigo-600 font-bold", todayClassName ) : "", isInRange && !isSelected ? "hover:bg-gray-300" : "", !isInRange ? twMerge( "opacity-50 cursor-not-allowed hover:bg-transparent ", disabledDayClassName ) : "" ), "aria-selected": isSelected ? "true" : "false", children: locale === "ne" ? toNepaliDigits(dayOfMonth) : dayOfMonth }, `day-${i}` ) ); } else { cells.push(/* @__PURE__ */ jsx("div", { className: "h-8 w-8" }, `empty-${i}`)); } } const weeks = []; for (let i = 0; i < cells.length; i += 7) { weeks.push( /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-1", children: cells.slice(i, i + 7) }, `week-${i}`) ); } days.push( /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-1", children: weeks }, "calendar-grid") ); return days; }; return /* @__PURE__ */ jsxs( "div", { className: twMerge( "border border-gray-300 shadow-lg rounded-md bg-white", calendarClassName ), children: [ /* @__PURE__ */ jsx( MonthNavigation_default, { viewDate, onViewDateChange, locale } ), /* @__PURE__ */ jsx("div", { className: "p-2", children: generateCalendarDays() }) ] } ); }; var Calendar_default = Calendar; var DateInput = ({ value, onChange, placeholder = "YYYY-MM-DD", disabled = false, formatOptions = { format: "YYYY-MM-DD" }, className, onFocus, onBlur }) => { const [inputValue, setInputValue] = useState( value ? formatDate(value, formatOptions) : "" ); const inputRef = useRef(null); useEffect(() => { if (value && isValidBsDate(value)) { setInputValue(formatDate(value, formatOptions)); } else if (value === null) { setInputValue(""); } }, [value, formatOptions]); const handleChange = (e) => { const newValue = e.target.value; setInputValue(newValue); if (onChange) { onChange(newValue); } }; const handleFocus = () => { if (onFocus) { onFocus(); } }; const handleBlur = () => { if (onBlur) { onBlur(); } }; return /* @__PURE__ */ jsx( "input", { ref: inputRef, type: "text", value: inputValue, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, placeholder, disabled, className: `${className}` } ); }; var DateInput_default = DateInput; var DatePicker = ({ value, onChange, placeholder = "YYYY-MM-DD", disabled = false, minDate, maxDate, formatOptions = { format: "YYYY-MM-DD" }, className = "", inputClassName = "", calendarClassName = "", dayClassName = "", selectedDayClassName = "", todayClassName = "", disabledDayClassName = "", position = "bottom" }) => { const [isOpen, setIsOpen] = useState(false); const [viewDate, setViewDate] = useState(value || getTodayBS()); const [selectedDate, setSelectedDate] = useState( value || null ); const containerRef = useRef(null); useEffect(() => { if (value) { setSelectedDate(value); setViewDate(value); } }, [value]); useEffect(() => { const handleClickOutside = (event) => { if (containerRef.current && !containerRef.current.contains(event.target)) { setIsOpen(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, []); const handleDateSelect = (date) => { setSelectedDate(date); setIsOpen(false); if (onChange) { onChange(date); } }; const handleInputFocus = () => { if (!disabled) { setIsOpen(true); } }; const handleInputChange = (value2) => { const date = parseDate(value2, formatOptions.format); if (date && isValidBsDate(date)) { setSelectedDate(date); setViewDate(date); if (onChange) { onChange(date); } } }; const getCalendarPosition = () => { switch (position) { case "top": return "bottom-full mb-1"; case "bottom": default: return "top-full mt-1"; } }; return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: `relative inline-block ${className}`, children: [ /* @__PURE__ */ jsxs("div", { className: "relative", children: [ /* @__PURE__ */ jsx( DateInput_default, { value: selectedDate, onChange: handleInputChange, onFocus: handleInputFocus, placeholder, disabled, formatOptions, className: twMerge( "px-3 py-2 rounded-md shadow-sm block w-full border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 pr-10", inputClassName ) } ), /* @__PURE__ */ jsx( "button", { type: "button", onClick: () => !disabled && setIsOpen(!isOpen), className: "absolute inset-y-0 right-0 pr-3 flex items-center text-gray-600 cursor-pointer hover:text-gray-800 disabled:opacity-50 disabled:cursor-not-allowed", disabled, "aria-label": "Toggle calendar", children: /* @__PURE__ */ jsx( "svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", className: "w-5 h-5", children: /* @__PURE__ */ jsx( "path", { fillRule: "evenodd", d: "M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z", clipRule: "evenodd" } ) } ) } ) ] }), isOpen && /* @__PURE__ */ jsx( "div", { className: `absolute z-10 w-72 bg-white rounded-md shadow-lg ${getCalendarPosition()}`, children: /* @__PURE__ */ jsx( Calendar_default, { selectedDate, viewDate, onDateSelect: handleDateSelect, onViewDateChange: setViewDate, minDate, maxDate, locale: formatOptions.locale, calendarClassName, dayClassName, selectedDayClassName, todayClassName, disabledDayClassName } ) } ) ] }); }; var DatePicker_default = DatePicker; export { Calendar_default as Calendar, DateInput_default as DateInput, DatePicker_default as NepaliDatePicker, bsDaysEn, bsDaysNe, bsMonthsEn, bsMonthsNe, convertADToBS, convertBSToAD, formatDate, getDaysInMonth, getTodayBS, isDateInRange, isValidBsDate, parseDate }; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map