UNPKG

persian-datepicker-element

Version:

A modern Jalali (Shamsi) Date Picker web component with shadcn-like styling

1 lines 54.4 kB
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.PersianDatePickerElement=e():t.PersianDatePickerElement=e()}("void 0"!=typeof self?self:"void 0"!=typeof window?window:"void 0"!=typeof global?global:this,(()=>(()=>{"use strict";var t={d:(e,i)=>{for(var r in i)t.o(i,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:i[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},e={};t.d(e,{default:()=>l});const i={g_days_in_month:[31,28,31,30,31,30,31,31,30,31,30,31],j_days_in_month:[31,31,31,31,31,31,30,30,30,30,30,29],jalaliToGregorian:function(t,e,i){const r=(t=parseInt(""+t))-979,s=(e=parseInt(""+e))-1,a=(i=parseInt(""+i))-1;let o=365*r+8*Math.floor(r/33)+Math.floor((r%33+3)/4);for(let t=0;t<s;++t)o+=this.j_days_in_month[t];o+=a;let n=o+79,d=1600+400*Math.floor(n/146097);n%=146097;let h=!0;n>=36525&&(n--,d+=100*Math.floor(n/36524),n%=36524,n>=365?n++:h=!1),d+=4*Math.floor(n/1461),n%=1461,n>=366&&(h=!1,n--,d+=Math.floor(n/365),n%=365);let c=0;for(;n>=this.g_days_in_month[c]+(1===c&&h?1:0);c++)n-=this.g_days_in_month[c]+(1===c&&h?1:0);return[d,c+1,n+1]},gregorianToJalali:function(t,e,i){const r=(t=parseInt(""+t))-1600,s=(e=parseInt(""+e))-1,a=(i=parseInt(""+i))-1;let o=365*r+Math.floor((r+3)/4)-Math.floor((r+99)/100)+Math.floor((r+399)/400);for(let t=0;t<s;++t)o+=this.g_days_in_month[t];s>1&&(r%4==0&&r%100!=0||r%400==0)&&o++,o+=a;let n=o-79;const d=Math.floor(n/12053);n%=12053;let h=979+33*d+4*Math.floor(n/1461);n%=1461,n>=366&&(h+=Math.floor((n-1)/365),n=(n-1)%365);let c=0;for(;c<11&&n>=this.j_days_in_month[c];++c)n-=this.j_days_in_month[c];return[h,c+1,n+1]},isLeapJalaliYear:function(t){return[1,5,9,13,17,22,26,30].includes(t%33)},getDaysInMonth:function(t,e){return e<1||e>12?0:e<=6?31:e<=11||this.isLeapJalaliYear(t)?30:29},getMonthName:function(t){return["فروردین","اردیبهشت","خرداد","تیر","مرداد","شهریور","مهر","آبان","آذر","دی","بهمن","اسفند"][t-1]},getDayOfWeek:function(t,e,i){const r=this.jalaliToGregorian(t,e,i);return new Date(r[0],r[1]-1,r[2]).getDay()},getDaysInYear:function(t){return this.isLeapJalaliYear(t)?366:365},isValidDate:function(t,e,i){return!(t<0||e<1||e>12||i<1)&&i<=this.getDaysInMonth(t,e)}};function r(t,e,r){const s=i.jalaliToGregorian(t,e,r);return new Date(s[0],s[1]-1,s[2]).toISOString()}const s=new Date,a=i.gregorianToJalali(s.getFullYear(),s.getMonth()+1,s.getDate())[0],o=[];class n{constructor(){this.mappedEvents=[...o],this.persianCalendarData={"Persian Calendar":[],"Hijri Calendar":[],Source:{name:"Fallback Data",url:""}},this.isLoading=!1,this.lastFetchYear=""[0],this.fetchPromise=""[0],this.isInitialized=!1,this.CACHE_KEY="persian_calendar_events",this.CACHE_EXPIRY_DAYS=7}static getInstance(){return n.instance||(n.instance=new n),n.instance}static isInitialized(){return n.instance?.isInitialized??!1}static async initialize(){if(n.initializationPromise)return n.initializationPromise;n.initializationPromise=n.getInstance().loadEventsData();try{await n.initializationPromise}finally{n.initializationPromise=""[0]}}mapPersianCalendarEvents(){try{let t=[];return this.persianCalendarData&&this.persianCalendarData["Persian Calendar"]&&Array.isArray(this.persianCalendarData["Persian Calendar"])&&(t=this.persianCalendarData["Persian Calendar"].map((t=>{const e=t.month||1,i=t.day||1;return{title:t.title||"",month:e,day:i,type:t.type||"Iran",holiday:t.holiday||!1,isoString:r(a,e,i)}}))),t}catch(t){return[...o]}}saveToCache(t){try{const e={data:t,timestamp:(new Date).getTime(),year:this.lastFetchYear};localStorage.setItem(this.CACHE_KEY,JSON.stringify(e))}catch(t){}}getFromCache(){try{const t=localStorage.getItem(this.CACHE_KEY);if(!t)return""[0];const{data:e,timestamp:i,year:r}=JSON.parse(t);return(new Date).getTime()-i>24*this.CACHE_EXPIRY_DAYS*60*60*1e3||r!==this.lastFetchYear?(localStorage.removeItem(this.CACHE_KEY),""[0]):e}catch(t){return""[0]}}async loadEventsData(){if(this.fetchPromise)return void await this.fetchPromise;const t=new Date,e=i.gregorianToJalali(t.getFullYear(),t.getMonth()+1,t.getDate())[0],r=this.getFromCache();if(r)return this.persianCalendarData=r,this.mappedEvents=this.mapPersianCalendarEvents(),this.lastFetchYear=e,void(this.isInitialized=!0);this.fetchPromise=(async()=>{this.isLoading=!0;try{const t=await this.fetchWithRetry("data/events.json",3);if(!t.ok)throw Error("HTTP error! status:"+t.status);this.persianCalendarData=await t.json(),this.saveToCache(this.persianCalendarData);const i=this.mapPersianCalendarEvents();this.mappedEvents=[...i],this.lastFetchYear=e,this.isInitialized=!0}catch(t){this.mappedEvents=[...o]}finally{this.isLoading=!1}})();try{await this.fetchPromise}finally{this.fetchPromise=""[0]}}async fetchWithRetry(t,e){let i=""[0];for(let r=0;r<e;r++)try{const e=await fetch(t);if(e.ok)return e;throw Error("HTTP error! status:"+e.status)}catch(t){i=t,r<e-1&&await new Promise((t=>setTimeout(t,1e3*Math.pow(2,r))))}throw i||Error("Failed to fetch events data after multiple retries")}getEvents(t,e,i,s=!1){return this.getAllEvents(i,s).filter((i=>i.month===t&&i.day===e)).map((t=>t.isoString?t:{...t,isoString:r(a,t.month,t.day)}))}getEvent(t,e){const i=this.mappedEvents.find((i=>i.month===t&&i.day===e));return i&&!i.isoString?{...i,isoString:r(a,i.month,i.day)}:i}getEventsForMonth(t){return this.mappedEvents.filter((e=>e.month===t)).map((t=>t.isoString?t:{...t,isoString:r(a,t.month,t.day)}))}getEventsForYear(){return this.mappedEvents.map((t=>t.isoString?t:{...t,isoString:r(a,t.month,t.day)}))}isHoliday(t,e,i,r=!1){return this.getEvents(t,e,i,r).some((t=>!0===t.holiday))}getHolidayTitles(t,e,i,r=!1){return this.getEvents(t,e,i,r).filter((t=>!0===t.holiday)).map((t=>t.title))}getAllEventTitles(t,e,i,r=!1){return this.getEvents(t,e,i,r).map((t=>t.title))}getAllEvents(t,e=!1){let i;return i=e?[...this.mappedEvents]:this.mappedEvents.filter((e=>t?.includes(e.type)??!0)),i.map((t=>t.isoString?t:{...t,isoString:r(a,t.month,t.day)}))}getEventsByType(t,e=!1,i=!1){const r=e?this.mappedEvents:this.mappedEvents.filter((e=>e.type===t));return i?r.filter((t=>!0===t.holiday)):r}getAllHolidays(t,e=!1){return this.getAllEvents(t,e).filter((t=>!0===t.holiday))}getEventTypes(){const t=new Set;return this.mappedEvents.forEach((e=>t.add(e.type))),Array.from(t)}getSourceMetadata(){return this.persianCalendarData.Source||{}}async refreshEvents(){if(!this.isLoading){this.fetchPromise=(async()=>{this.isLoading=!0;try{const t=await this.fetchWithRetry("data/events.json",3);if(!t.ok)throw Error("HTTP error! status:"+t.status);this.persianCalendarData=await t.json(),this.saveToCache(this.persianCalendarData);const e=this.mapPersianCalendarEvents();this.mappedEvents=[...e];const r=new Date,s=i.gregorianToJalali(r.getFullYear(),r.getMonth()+1,r.getDate());this.lastFetchYear=s[0]}catch(t){}finally{this.isLoading=!1}})();try{await this.fetchPromise}finally{this.fetchPromise=""[0]}}return[...this.mappedEvents]}}n.instance=""[0],n.initializationPromise=""[0];const d=n,h=["Iran","AncientIran","International"];class c extends HTMLElement{toPersianNum(t){const e=["۰","۱","۲","۳","۴","۵","۶","۷","۸","۹"];return(""+t).replace(/\d/g,(t=>e[parseInt(t)]))}static get observedAttributes(){return["placeholder","rtl","format","show-holidays","holiday-types","event-types","show-events","today-button-text","today-button-class","tomorrow-button-text","tomorrow-button-class","min-date","max-date","disabled-dates","range-mode","show-month-selector","show-year-selector","show-prev-button","show-next-button","show-today-button","show-tomorrow-button"]}constructor(t={}){if(super(),this.jalaliYear=0,this.jalaliMonth=0,this.jalaliDay=0,this.selectedDate=""[0],this.isRangeMode=!1,this.rangeStart=""[0],this.rangeEnd=""[0],this.isSelectingRange=!1,this.showEvents=!0,this.eventTypes=[...h],this.includeAllTypes=!1,this.isTransitioning=!1,this._documentClickHandler=()=>{},this.persianMonths=["فروردین","اردیبهشت","خرداد","تیر","مرداد","شهریور","مهر","آبان","آذر","دی","بهمن","اسفند"],this.holidayTypeLabels={Iran:"ایران",Afghanistan:"افغانستان",AncientIran:"ایران باستان",International:"بین‌المللی"},this.format="YYYY/MM/DD",this.minDate=""[0],this.maxDate=""[0],this.disabledDatesFn=""[0],this.handleInputClick=t=>{t.stopPropagation(),this.toggleCalendar()},this.handleDocumentClick=t=>{this.calendar&&this.calendar.classList.contains("visible")&&(t.composedPath().includes(this)||(this.closeAllDropdowns(),this.toggleCalendar()))},this._touchStartX=0,this._touchStartY=0,this._isDragging=!1,this._isSwiping=!1,this.options=t,this.eventUtils=d.getInstance(),void 0!==t.showEvents&&(this.showEvents=t.showEvents),t.format&&(this.format=t.format),void 0!==t.rtl&&this.style.setProperty("--jdp-direction",t.rtl?"rtl":"ltr"),void 0!==t.rangeMode&&(this.isRangeMode=t.rangeMode),t.rangeStart&&(this.rangeStart=t.rangeStart),t.rangeEnd&&(this.rangeEnd=t.rangeEnd),t.minDate&&(this.minDate=t.minDate),t.maxDate&&(this.maxDate=t.maxDate),t.disabledDates)if("function"==typeof t.disabledDates)this.disabledDatesFn=t.disabledDates;else if("string"==typeof t.disabledDates){const e=window[t.disabledDates];"function"==typeof e&&(this.disabledDatesFn=e)}t.defaultDate&&(this.selectedDate=t.defaultDate,this.jalaliYear=t.defaultDate[0],this.jalaliMonth=t.defaultDate[1],this.jalaliDay=t.defaultDate[2]);const e=this.attachShadow({mode:"open"});this.render(e),t.showEvents&&t.eventTypes&&this.seteventTypes(t.eventTypes)}async connectedCallback(){try{if(!this.shadowRoot)return;this.initializeDomReferences(),this.initializeCurrentDate(),d.isInitialized()||await d.initialize(),this.initializeUIComponents(),this.addEventListeners(),this.initTouchGestures(),this.renderCalendar()}catch(t){}}disconnectedCallback(){if(this._documentClickHandler&&document.removeEventListener("click",this._documentClickHandler),c.openCalendarInstance===this&&(c.openCalendarInstance=""[0]),this.shadowRoot){this.input&&this.input.removeEventListener("click",this.handleInputClick),this.calendar&&this.calendar.removeEventListener("click",(t=>t.stopPropagation())),this.daysContainer&&this.daysContainer.removeEventListener("click",this.handleDayClick.bind(this));const t=this.shadowRoot.getElementById("prev-month"),e=this.shadowRoot.getElementById("next-month"),i=this.shadowRoot.getElementById("today-button"),r=this.shadowRoot.getElementById("tomorrow-button");t&&(t.removeEventListener("click",(()=>this.changeMonth(-1))),t.removeEventListener("touchstart",(t=>t.stopPropagation()))),e&&(e.removeEventListener("click",(()=>this.changeMonth(1))),e.removeEventListener("touchstart",(t=>t.stopPropagation()))),i&&i.removeEventListener("click",(()=>this.goToToday())),r&&r.removeEventListener("click",(()=>this.goToTomorrow())),this.calendar&&(this.calendar.removeEventListener("touchstart",this.handleTouchStart),this.calendar.removeEventListener("touchmove",this.handleTouchMove),this.calendar.removeEventListener("touchend",this.handleTouchEnd),this.calendar.removeEventListener("touchcancel",this.handleTouchCancel))}}attributeChangedCallback(t,e,i){if(e!==i&&this.shadowRoot)switch(t){case"placeholder":this.input&&(this.input.placeholder=i||"");break;case"rtl":this.style.setProperty("--jdp-direction",i!==""[0]&&"!1"!==i?"rtl":"ltr");break;case"show-holidays":case"show-events":this.showEvents=i!==""[0]&&"!1"!==i,this.calendar&&this.renderCalendar();break;case"holiday-types":case"event-types":i?this.seteventTypes(i):(this.eventTypes=[...h],this.includeAllTypes=!1),this.calendar&&this.renderCalendar();break;case"format":i&&this.isValidFormat(i)&&(this.format=i,this.selectedDate&&this.formatAndSetValue());break;case"min-date":if(i)try{const[t,e,r]=JSON.parse(i);this.setMinDate(t,e,r)}catch(t){}else this.minDate=""[0];this.calendar&&this.renderCalendar();break;case"max-date":if(i)try{const[t,e,r]=JSON.parse(i);this.setMaxDate(t,e,r)}catch(t){}else this.maxDate=""[0];this.calendar&&this.renderCalendar();break;case"disabled-dates":if(i){let t=""[0];try{t="function"==typeof i?i:"function"==typeof this[i]?this[i]:window[i]}catch(t){}"function"==typeof t&&(this.disabledDatesFn=t)}else this.disabledDatesFn=""[0];this.calendar&&this.renderCalendar();break;case"today-button-text":case"tomorrow-button-text":this.updateButtonText(t,i);break;case"today-button-class":case"tomorrow-button-class":this.updateButtonClass(t,i);break;case"range-mode":this.isRangeMode=i!==""[0]&&"!1"!==i,this.calendar&&this.renderCalendar();break;case"show-month-selector":case"show-year-selector":case"show-prev-button":case"show-next-button":case"show-today-button":case"show-tomorrow-button":this.shadowRoot&&(this.render(this.shadowRoot),this.initializeDomReferences(),this.initializeUIComponents(),this.addEventListeners(),this.renderCalendar())}}updateButtonText(t,e){if(!this.shadowRoot)return;const i="today-button-text"===t?"امروز":"فردا",r=this.shadowRoot.getElementById("today-button-text"===t?"today-button":"tomorrow-button");r&&(r.textContent=e||i)}updateButtonClass(t,e){if(!this.shadowRoot)return;const i="today-button-class"===t?"today-button":"tomorrow-button",r=this.shadowRoot.getElementById("today-button-class"===t?"today-button":"tomorrow-button");r&&(r.className="date-nav-button "+i,e&&e.split(" ").forEach((t=>{t.trim()&&r.classList.add(t.trim())})))}initializeDomReferences(){if(this.shadowRoot){if(this.input=this.shadowRoot.getElementById("date-input"),this.calendar=this.shadowRoot.getElementById("calendar"),this.daysContainer=this.shadowRoot.getElementById("days-container"),this.dayNamesContainer=this.shadowRoot.getElementById("day-names"),!(this.input&&this.calendar&&this.daysContainer&&this.dayNamesContainer))throw Error("Failed to initialize required elements");if(this.options.placeholder)this.input.placeholder=this.options.placeholder;else{const t=this.getAttribute("placeholder");t&&(this.input.placeholder=t)}}}initializeCurrentDate(){const t=new Date,e=i.gregorianToJalali(t.getFullYear(),t.getMonth()+1,t.getDate());this.jalaliYear=e[0],this.jalaliMonth=e[1],this.jalaliDay=e[2],this.selectedDate=""[0]}initializeUIComponents(){this.initializeDayNames(),this.setupMonthYearSelectors()}initializeDayNames(){this.dayNamesContainer&&(this.dayNamesContainer.innerHTML="",["ش","ی","د","س","چ","پ","ج"].forEach((t=>{const e=document.createElement("div");e.classList.add("day-name"),e.textContent=t,this.dayNamesContainer.appendChild(e)})))}setupMonthYearSelectors(){if(!this.shadowRoot)return;const t=this.shadowRoot.getElementById("month-select-trigger"),e=this.shadowRoot.getElementById("year-select-trigger"),r=this.shadowRoot.getElementById("month-select-value"),s=this.shadowRoot.getElementById("year-select-value"),a=this.shadowRoot.getElementById("month-select-content"),o=this.shadowRoot.getElementById("year-select-content");if(!(t&&e&&r&&s&&a&&o))return;a.innerHTML="",o.innerHTML="";const n=document.createDocumentFragment(),d=document.createDocumentFragment();this.persianMonths.forEach(((t,e)=>{const i=e+1,s=document.createElement("div");s.classList.add("select-item"),s.textContent=t,s.dataset.value=""+i,i===this.jalaliMonth&&(s.classList.add("selected"),r.textContent=t),s.addEventListener("click",(e=>{e.stopPropagation(),this.handleMonthChange(i,t),this.closeAllDropdowns()})),n.appendChild(s)}));const h=new Date,c=i.gregorianToJalali(h.getFullYear(),h.getMonth()+1,h.getDate())[0],l=c+50;for(let t=c-100;t<=l;t++){const e=document.createElement("div");e.classList.add("select-item"),e.textContent=this.toPersianNum(t),e.dataset.value=""+t,t===this.jalaliYear&&(e.classList.add("selected"),s.textContent=this.toPersianNum(t)),e.addEventListener("click",(e=>{e.stopPropagation(),this.handleYearChange(t),this.closeAllDropdowns()})),d.appendChild(e)}a.appendChild(n),o.appendChild(d),t.addEventListener("click",(t=>{t.stopPropagation(),this.toggleDropdown(a)})),e.addEventListener("click",(t=>{t.stopPropagation(),this.toggleDropdown(o)})),a.addEventListener("click",(t=>{t.stopPropagation()})),o.addEventListener("click",(t=>{t.stopPropagation()}))}addEventListeners(){this.shadowRoot&&this.input&&this.calendar&&(this.input.addEventListener("click",this.handleInputClick),this.setupNavigationButtons(),this.calendar.addEventListener("click",(t=>t.stopPropagation())),this.daysContainer.addEventListener("click",this.handleDayClick.bind(this)),this.calendar.addEventListener("click",(t=>{const e=t.target;e.closest(".select-trigger")||e.closest(".select-content")||this.closeAllDropdowns()})),this._documentClickHandler=this.handleDocumentClick.bind(this),document.addEventListener("click",this._documentClickHandler))}handleDayClick(t){const e=t.target.closest(".day");if(!e||e.classList.contains("empty")||e.classList.contains("disabled")||this.isDateDisabled(this.jalaliYear,this.jalaliMonth,parseInt(e.textContent||"0")))return;t.stopPropagation();const i=e.textContent;if(!i)return;const r=this.fromPersianNum(i);isNaN(r)||this.handleRangeSelection(r)}fromPersianNum(t){const e=["۰","۱","۲","۳","۴","۵","۶","۷","۸","۹"];return parseInt(t.replace(/[۰-۹]/g,(t=>""+e.indexOf(t))))}setupNavigationButtons(){if(!this.shadowRoot)return;const t=this.shadowRoot.getElementById("prev-month"),e=this.shadowRoot.getElementById("next-month"),i=this.shadowRoot.getElementById("today-button"),r=this.shadowRoot.getElementById("tomorrow-button"),s=(t,e)=>{t&&t.addEventListener("click",(t=>{t.stopPropagation(),this.closeAllDropdowns(),e()}))};s(t,(()=>this.changeMonth(-1))),s(e,(()=>this.changeMonth(1))),s(i,(()=>this.goToToday())),s(r,(()=>this.goToTomorrow()))}seteventTypes(t){if("string"==typeof t){if("all"===t.toLowerCase())return this.includeAllTypes=!0,void(this.eventTypes=[...this.eventUtils.getEventTypes()]);try{const e=JSON.parse(t);this.eventTypes=Array.isArray(e)?e:t.split(",").map((t=>t.trim())).filter(Boolean)}catch(e){this.eventTypes=t.split(",").map((t=>t.trim())).filter(Boolean)}}else this.eventTypes=Array.isArray(t)?[...t]:[...h];this.includeAllTypes=!1,this.calendar&&this.renderCalendar()}geteventTypes(){return[...this.eventTypes]}isShowingAllTypes(){return this.includeAllTypes}render(t){const e=this.getAttribute("today-button-text")||"امروز",i=this.getAttribute("today-button-class")||"",r=this.getAttribute("tomorrow-button-text")||"فردا",s=this.getAttribute("tomorrow-button-class")||"",a="!1"!==this.getAttribute("show-month-selector"),o="!1"!==this.getAttribute("show-year-selector"),n="!1"!==this.getAttribute("show-prev-button"),d="!1"!==this.getAttribute("show-next-button"),h="!1"!==this.getAttribute("show-today-button"),c="!1"!==this.getAttribute("show-tomorrow-button"),l='<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>';t.innerHTML=`<style>:host{ --jdp-primary:#0891b2;--jdp-primary-hover:#0e7490;--jdp-primary-foreground:#ffffff; --jdp-background:#ffffff;--jdp-foreground:#1e293b;--jdp-muted:#f1f5f9;--jdp-muted-foreground:#64748b;--jdp-border:#e2e8f0;--jdp-ring:#0284c7; --jdp-holiday-color:#ef4444;--jdp-holiday-bg:#fee2e2;--jdp-holiday-hover-bg:#fecaca; --jdp-range-bg:rgba(8, 145, 178, 0.1);--jdp-range-color:var(--jdp-foreground);--jdp-range-start-bg:var(--jdp-primary);--jdp-range-start-color:var(--jdp-primary-foreground);--jdp-range-end-bg:var(--jdp-primary);--jdp-range-end-color:var(--jdp-primary-foreground); --jdp-font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;--jdp-font-size:14px;--jdp-line-height:1.5;--jdp-font-weight:400;--jdp-font-weight-medium:500;--jdp-day-name-font-size:12px;--jdp-day-name-font-weight:400;--jdp-day-font-size:13px;--jdp-day-font-weight:400;--jdp-month-year-font-size:14px;--jdp-month-year-font-weight:500; --jdp-spacing-xs:4px;--jdp-spacing-sm:8px;--jdp-spacing-md:16px;--jdp-spacing-lg:24px; --jdp-input-padding-x:14px;--jdp-input-padding-y:10px;--jdp-input-border-width:1px;--jdp-input-border-color:var(--jdp-border);--jdp-input-border-radius:var(--jdp-border-radius);--jdp-input-focus-ring-width:2px;--jdp-input-focus-ring-color:rgba(2, 132, 199, 0.25); --jdp-calendar-width:280px;--jdp-calendar-padding:var(--jdp-spacing-md);--jdp-calendar-border-width:1px;--jdp-calendar-border-color:var(--jdp-border);--jdp-calendar-border-radius:var(--jdp-border-radius);--jdp-calendar-shadow:0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2);--jdp-calendar-z-index:10; --jdp-nav-button-size:30px;--jdp-nav-button-bg:var(--jdp-muted);--jdp-nav-button-bg-hover:var(--jdp-border);--jdp-nav-button-border-radius:var(--jdp-border-radius);--jdp-nav-arrow-size:8px;--jdp-nav-arrow-thickness:2px;--jdp-nav-arrow-color:var(--jdp-foreground); --jdp-day-cell-size:32px;--jdp-day-cell-margin:1px;--jdp-day-cell-border-radius:var(--jdp-border-radius); --jdp-day-hover-bg:var(--jdp-muted);--jdp-day-selected-bg:var(--jdp-primary);--jdp-day-selected-color:var(--jdp-primary-foreground);--jdp-day-today-border-color:var(--jdp-primary);--jdp-day-today-border-width:1px;--jdp-day-disabled-opacity:0.4; --jdp-transition-duration:0.2s;--jdp-fade-from-y:-4px;--jdp-fade-from-y-reverse:4px;--jdp-month-transition-duration:0.3s; --jdp-border-radius:0.5rem;--jdp-direction:rtl;--jdp-header-gap:var(--jdp-spacing-xs); --jdp-select-container-gap:8px;--jdp-select-trigger-height:var(--jdp-nav-button-size);--jdp-select-trigger-bg:var(--jdp-muted);--jdp-select-trigger-max-width:110px;--jdp-select-month-trigger-max-width:var(--jdp-select-trigger-max-width);--jdp-select-year-trigger-max-width:var(--jdp-select-trigger-max-width);--jdp-select-dropdown-width:auto;--jdp-select-text-overflow:ellipsis; --jdp-scrollbar-width:4px;--jdp-scrollbar-track:transparent;--jdp-scrollbar-thumb:rgba(0, 0, 0, 0.15);--jdp-scrollbar-thumb-hover:rgba(0, 0, 0, 0.25);--jdp-scrollbar-border-radius:4px;}*{box-sizing:border-box;direction:var(--jdp-direction);}.picker-container{position:relative;display:inline-block;width:100%;font-family:var(--jdp-font-family);font-size:var(--jdp-font-size);line-height:var(--jdp-line-height);font-weight:var(--jdp-font-weight);}input{width:100%;padding:var(--jdp-input-padding-y) var(--jdp-input-padding-x);border-radius:var(--jdp-input-border-radius);border:var(--jdp-input-border-width) solid var(--jdp-input-border-color);font-size:var(--jdp-font-size);line-height:var(--jdp-line-height);font-family:inherit;background-color:var(--jdp-background);color:var(--jdp-foreground);cursor:pointer;outline:none;transition:all var(--jdp-transition-duration) ease;text-align:right;}input:focus{border-color:var(--jdp-ring);box-shadow:0 0 0 var(--jdp-input-focus-ring-width) var(--jdp-input-focus-ring-color);}.calendar{display:none;position:absolute;right:0;width:var(--jdp-calendar-width);background:var(--jdp-background);border:var(--jdp-calendar-border-width) solid var(--jdp-calendar-border-color);border-radius:var(--jdp-calendar-border-radius);box-shadow:var(--jdp-calendar-shadow);padding:var(--jdp-calendar-padding);text-align:center;z-index:var(--jdp-calendar-z-index);touch-action:manipulation;-webkit-user-select:none;user-select:none;transform:translateZ(0);will-change:transform;backface-visibility:hidden;contain:layout style;}.calendar.position-bottom{top:calc(100% + 5px);animation:fadeInFromTop var(--jdp-transition-duration) ease;}.calendar.position-top{bottom:calc(100% + 5px);animation:fadeInFromBottom var(--jdp-transition-duration) ease;}.calendar.visible{display:block;}@keyframes fadeInFromTop{from{opacity:0;transform:translateY(var(--jdp-fade-from-y));}to{opacity:1;transform:translateY(0);}}@keyframes fadeInFromBottom{from{opacity:0;transform:translateY(var(--jdp-fade-from-y-reverse));}to{opacity:1;transform:translateY(0);}}.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--jdp-spacing-md);gap:var(--jdp-header-gap, var(--jdp-spacing-xs));}.month-year{font-weight:var(--jdp-month-year-font-weight);font-size:var(--jdp-month-year-font-size);color:var(--jdp-foreground);transition:opacity var(--jdp-transition-duration) ease;}.month-year.fade{opacity:0;}.days-wrapper{position:relative;touch-action:pan-y;overflow:visible;z-index:1;contain:layout;isolation:isolate;}.days{display:grid;grid-template-columns:repeat(7, 1fr);transition:transform var(--jdp-month-transition-duration) ease, opacity var(--jdp-month-transition-duration) ease;will-change:transform, opacity;transform:translateZ(0);backface-visibility:hidden;position:relative;contain:layout;}.days.slide-left{animation:slideInLeft var(--jdp-month-transition-duration) ease;}.days.slide-right{animation:slideInRight var(--jdp-month-transition-duration) ease;}@keyframes slideInLeft{from{opacity:0;transform:translateX(-10%) translateZ(0);pointer-events:none;}to{opacity:1;transform:translateX(0) translateZ(0);pointer-events:auto;}}@keyframes slideInRight{from{opacity:0;transform:translateX(10%) translateZ(0);pointer-events:none;}to{opacity:1;transform:translateX(0) translateZ(0);pointer-events:auto;}}.day{position:relative;z-index:1;touch-action:manipulation;isolation:isolate;}.day:hover{z-index:2;}.nav-button{background:var(--jdp-nav-button-bg);border:none;border-radius:var(--jdp-nav-button-border-radius);width:var(--jdp-nav-button-size);height:var(--jdp-nav-button-size);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all var(--jdp-transition-duration) ease;position:relative;touch-action:manipulation;will-change:transform, background-color;}.nav-button:hover{background:var(--jdp-nav-button-bg-hover);}.nav-button:active{transform:translateY(1px);}.nav-button::before{content:'';display:block;width:var(--jdp-nav-arrow-size);height:var(--jdp-nav-arrow-size);border-top:var(--jdp-nav-arrow-thickness) solid var(--jdp-nav-arrow-color);border-right:var(--jdp-nav-arrow-thickness) solid var(--jdp-nav-arrow-color);position:absolute;}.nav-button.prev::before{transform:rotate(45deg);right:11px;left:auto;}.nav-button.next::before{transform:rotate(225deg);left:11px;right:auto;}.day-names{display:grid;grid-template-columns:repeat(7, 1fr);margin-bottom:var(--jdp-spacing-sm);}.day-name{font-size:var(--jdp-day-name-font-size);font-weight:var(--jdp-day-name-font-weight);color:var(--jdp-muted-foreground);padding:var(--jdp-spacing-xs) 0;text-align:center;}.day{aspect-ratio:1/1;display:flex;align-items:center;justify-content:center;border-radius:var(--jdp-day-cell-border-radius);font-size:var(--jdp-day-font-size);font-weight:var(--jdp-day-font-weight);cursor:pointer;transition:var(--jdp-transition-duration) ease;margin:var(--jdp-day-cell-margin);position:relative;touch-action:manipulation;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none;}.day:hover:not(.empty):not(.disabled){background:var(--jdp-day-hover-bg);}.day.selected{background:var(--jdp-day-selected-bg);color:var(--jdp-day-selected-color);}.day.today:not(.selected){border:var(--jdp-day-today-border-width) solid var(--jdp-day-today-border-color);}.day.empty{cursor:default;}.day.disabled{opacity:var(--jdp-day-disabled-opacity);cursor:not-allowed;} .day.holiday:not(.selected){color:var(--jdp-holiday-color);background-color:var(--jdp-holiday-bg);font-weight:var(--jdp-font-weight-medium);}.day.holiday:hover:not(.selected):not(.disabled){background-color:var(--jdp-holiday-hover-bg);} .day.holiday.in-range{background-color:var(--jdp-range-bg);color:var(--jdp-range-color);}.day.holiday.range-start, .day.holiday.range-end{background-color:var(--jdp-range-start-bg);color:var(--jdp-range-start-color);}.day.friday{color:var(--jdp-holiday-color);}.event-tooltip{position:absolute;background:var(--jdp-background);border:1px solid var(--jdp-border);border-radius:var(--jdp-border-radius);padding:var(--jdp-spacing-sm);width:200px;box-shadow:var(--jdp-calendar-shadow);text-align:right;font-size:12px;opacity:0;visibility:hidden;transition:opacity var(--jdp-transition-duration) ease, visibility var(--jdp-transition-duration) ease;pointer-events:none;bottom:120%;right:0;transform:translateY(-5px);z-index:9999;}.event-tooltip.tooltip-visible{opacity:1;visibility:visible;pointer-events:auto;background:var(--jdp-background);} @media (max-width:768px){.event-tooltip{position:fixed;left:50%;top:50%;transform:translate(-50%, -50%);width:90%;max-width:300px;max-height:80vh;overflow-y:auto;bottom:auto;right:auto;background:var(--jdp-background);z-index:9999;}.event-tooltip::before{content:'';position:fixed;top:0;left:0;right:0;bottom:0;z-index:-1;}}.event-item{margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid var(--jdp-border);color:var(--jdp-foreground);background:var(--jdp-background);}.event-item:last-child{margin-bottom:0;padding-bottom:0;border-bottom:none;}.event-item.holiday{color:var(--jdp-holiday-color);}.event-type-label{display:inline-block;font-size:10px;padding:1px 4px;border-radius:3px;margin-right:4px;background-color:var(--jdp-muted);color:var(--jdp-muted-foreground);} .footer{margin-top:var(--jdp-spacing-md);display:flex;justify-content:space-between;}.date-nav-button{background:var(--jdp-muted);border:none;border-radius:var(--jdp-border-radius);padding:var(--jdp-spacing-xs) var(--jdp-spacing-md);font-family:inherit;font-size:var(--jdp-font-size);color:var(--jdp-foreground);cursor:pointer;transition:all var(--jdp-transition-duration) ease;touch-action:manipulation;-webkit-tap-highlight-color:transparent;}.date-nav-button:hover{background:var(--jdp-nav-button-bg-hover);}.date-nav-button:active{transform:translateY(1px);} :host .selectors-container{display:flex;gap:var(--jdp-select-container-gap, 8px);position:relative;align-items:var(--jdp-select-container-align, center);justify-content:var(--jdp-select-container-justify, space-between);width:100%;max-width:calc(100% - var(--jdp-nav-button-size) * 2 - var(--jdp-spacing-sm));margin:0 var(--jdp-spacing-xs);}:host .custom-select{position:relative;user-select:none;width:100%;margin:0 var(--jdp-spacing-xs, 2px);}:host .month-select{margin-left:var(--jdp-month-select-margin-left, 0);margin-right:var(--jdp-month-select-margin-right, 0);}:host .year-select{margin-left:var(--jdp-year-select-margin-left, 0);margin-right:var(--jdp-year-select-margin-right, 0);}:host .select-trigger{display:flex;align-items:center;justify-content:var(--jdp-select-trigger-justify, center);gap:0 4px;width:100%;height:var(--jdp-select-trigger-height, var(--jdp-nav-button-size));min-height:var(--jdp-nav-button-size);background-color:var(--jdp-select-trigger-bg, var(--jdp-muted));border:var(--jdp-select-trigger-border-width, 1px) solid var(--jdp-select-trigger-border-color, var(--jdp-border));border-radius:var(--jdp-select-trigger-border-radius, var(--jdp-border-radius));color:var(--jdp-select-trigger-color, var(--jdp-foreground));font-family:inherit;font-size:var(--jdp-select-trigger-font-size, var(--jdp-font-size));line-height:1;padding:0 var(--jdp-select-trigger-padding-x, 0);cursor:pointer;transition:all var(--jdp-transition-duration) ease;text-align:var(--jdp-select-trigger-text-align, center);min-width:var(--jdp-select-trigger-min-width, initial);outline:none;font-weight:var(--jdp-select-trigger-font-weight, 500);box-sizing:border-box;max-width:var(--jdp-select-trigger-max-width, 110px);}:host .month-select .select-trigger{max-width:var(--jdp-select-month-trigger-max-width, var(--jdp-select-trigger-max-width));}:host .year-select .select-trigger{max-width:var(--jdp-select-year-trigger-max-width, var(--jdp-select-trigger-max-width));}:host .select-trigger span:first-child{white-space:nowrap;overflow:var(--jdp-select-trigger-overflow, visible);text-overflow:var(--jdp-select-text-overflow, ellipsis);max-width:calc(100% - 24px);display:inline-block;text-align:center;flex:1;}:host .select-trigger:hover{background-color:var(--jdp-select-trigger-bg-hover, rgba(0, 0, 0, 0.05));border-color:var(--jdp-select-trigger-border-hover, var(--jdp-border));}:host .select-trigger:focus-visible{outline:2px solid var(--jdp-select-trigger-focus-ring-color, var(--jdp-ring));outline-offset:var(--jdp-select-trigger-focus-ring-offset, 2px);}:host .select-icon{margin-left:var(--jdp-select-icon-margin, var(--jdp-spacing-xs));display:var(--jdp-select-icon-display, none);justify-content:center;align-items:center;transition:transform 0.2s ease;width:var(--jdp-select-icon-size, 12px);height:var(--jdp-select-icon-size, 12px);opacity:var(--jdp-select-icon-opacity, 0.7);flex-shrink:0;}:host .select-icon svg{width:var(--jdp-select-icon-size, 12px);height:var(--jdp-select-icon-size, 12px);}:host .select-content.open .select-icon{transform:rotate(180deg);}:host .select-content{position:var(--jdp-select-content-position, absolute);top:calc(100% + var(--jdp-select-content-top-offset, 5px));left:0;width:var(--jdp-select-dropdown-width, 100%);min-width:100%;background-color:var(--jdp-select-content-bg, var(--jdp-background));border:var(--jdp-select-content-border-width, 1px) solid var(--jdp-select-content-border-color, var(--jdp-border));border-radius:var(--jdp-select-content-border-radius, var(--jdp-border-radius));box-shadow:var(--jdp-select-content-shadow, 0 4px 8px rgba(0,0,0,0.1));z-index:var(--jdp-select-content-z-index, 20);overflow-y:auto;max-height:var(--jdp-select-content-max-height, 200px);display:none;padding:var(--jdp-select-content-padding-y, 0.25rem) var(--jdp-select-content-padding-x, 0);scroll-behavior:smooth; scrollbar-width:var(--jdp-scrollbar-width-size, none);scrollbar-color:var(--jdp-scrollbar-thumb, rgba(0, 0, 0, 0.15)) var(--jdp-scrollbar-track, transparent);} :host .select-content::-webkit-scrollbar{width:var(--jdp-scrollbar-width, 4px);}:host .select-content::-webkit-scrollbar-track{background:var(--jdp-scrollbar-track, transparent);border-radius:var(--jdp-scrollbar-border-radius, 4px);}:host .select-content::-webkit-scrollbar-thumb{background-color:var(--jdp-scrollbar-thumb, rgba(0, 0, 0, 0.15));border-radius:var(--jdp-scrollbar-border-radius, 4px);}:host .select-content::-webkit-scrollbar-thumb:hover{background-color:var(--jdp-scrollbar-thumb-hover, rgba(0, 0, 0, 0.25));}:host .select-content.open{display:block;animation:fadeInSelect var(--jdp-select-content-animation-duration, var(--jdp-transition-duration)) ease;}:host .month-select-content{width:var(--jdp-select-month-width, var(--jdp-select-dropdown-width, auto));min-width:100%;}:host .year-select-content{width:var(--jdp-select-year-width, var(--jdp-select-dropdown-width, auto));min-width:100%;}:host .select-item{padding:var(--jdp-select-item-padding-y, 0.5rem) var(--jdp-select-item-padding-x, 0.75rem);cursor:pointer;transition:background-color var(--jdp-transition-duration) ease;border-radius:var(--jdp-select-item-border-radius, var(--jdp-select-trigger-border-radius, var(--jdp-border-radius)));margin:var(--jdp-select-item-margin, 0 0.25rem);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:var(--jdp-select-item-max-width, 100%);box-sizing:border-box;text-align:var(--jdp-select-item-text-align, center);}:host .select-item:hover{background-color:var(--jdp-select-item-hover-bg, var(--jdp-day-hover-bg));}:host .select-item.selected{background-color:var(--jdp-select-item-selected-bg, var(--jdp-primary));color:var(--jdp-select-item-selected-color, var(--jdp-primary-foreground));font-weight:var(--jdp-select-item-selected-font-weight, var(--jdp-font-weight-medium));border-radius:var(--jdp-select-item-selected-border-radius, var(--jdp-select-trigger-border-radius, var(--jdp-border-radius)));}@keyframes fadeInSelect{from{opacity:0;transform:translateY(-5px);}to{opacity:1;transform:translateY(0);}} :host([rtl="!0"]) .select-icon, :host([dir="rtl"]) .select-icon{margin-left:0;margin-right:var(--jdp-select-icon-margin, var(--jdp-spacing-xs));}:host([rtl="!0"]) .select-item, :host([dir="rtl"]) .select-item{text-align:var(--jdp-select-item-text-align, right);} @media (prefers-color-scheme:dark){:host{--jdp-scrollbar-thumb:rgba(124, 124, 124, 0.15);--jdp-scrollbar-thumb-hover:rgba(41, 41, 41, 0.25);}} :host(.dark-theme){--jdp-scrollbar-thumb:rgba(124, 124, 124, 0.15);--jdp-scrollbar-thumb-hover:rgba(41, 41, 41, 0.25);} .day.in-range{background-color:var(--jdp-range-bg);color:var(--jdp-range-color);position:relative;z-index:1;border-radius:0;}.day.range-start, .day.range-end{background-color:var(--jdp-range-start-bg);color:var(--jdp-range-start-color);position:relative;z-index:2;}.day.range-start{border-radius:0 var(--jdp-border-radius) var(--jdp-border-radius) 0;}.day.range-end{border-radius:var(--jdp-border-radius) 0 0 var(--jdp-border-radius);} :host([rtl="!0"]) .day.range-start, :host([dir="rtl"]) .day.range-start{border-radius:var(--jdp-border-radius) 0 0 var(--jdp-border-radius);}:host([rtl="!0"]) .day.range-end, :host([dir="rtl"]) .day.range-end{border-radius:0 var(--jdp-border-radius) var(--jdp-border-radius) 0;} .day.range-start.range-end{border-radius:var(--jdp-border-radius);} .day.in-range:not(.range-start):not(.range-end){background-color:var(--jdp-range-bg);color:var(--jdp-range-color);border-radius:0;} .day.disabled.in-range{opacity:0.4;background-color:var(--jdp-range-bg);color:var(--jdp-range-color);border-radius:0;} .day.holiday.in-range:not(.range-start):not(.range-end){background-color:var(--jdp-range-bg);color:var(--jdp-range-color);border-radius:0;}.day.holiday.range-start, .day.holiday.range-end{background-color:var(--jdp-range-start-bg);color:var(--jdp-range-start-color);}</style> <div class="picker-container"> <input type="text" id="date-input" readonly placeholder="انتخاب تاریخ"> <div class="calendar" id="calendar"> <div class="header"> ${n?'<button id="prev-month" type="button" class="nav-button prev"></button>':""}\n <div class="selectors-container">\n ${a?`\n <div class="custom-select month-select" id="month-select-container">\n <button type="button" class="select-trigger" id="month-select-trigger">\n <span id="month-select-value"></span>\n <span class="select-icon">${l}</span>\n </button>\n <div class="select-content month-select-content" id="month-select-content"></div>\n </div>\n `:""}\n ${o?`\n <div class="custom-select year-select" id="year-select-container">\n <button type="button" class="select-trigger" id="year-select-trigger">\n <span id="year-select-value"></span>\n <span class="select-icon">${l}</span>\n </button>\n <div class="select-content year-select-content" id="year-select-content"></div>\n </div>\n `:""}\n </div>\n ${d?'<button id="next-month" type="button" class="nav-button next"></button>':""}\n </div>\n <div class="day-names" id="day-names"></div>\n <div class="days-wrapper">\n <div class="days" id="days-container"></div>\n </div>\n <div class="footer">\n ${h?`<button id="today-button" type="button" class="date-nav-button today-button ${i}">${e}</button>`:""}\n ${c?`<button id="tomorrow-button" type="button" class="date-nav-button tomorrow-button ${s}">${r}</button>`:""}\n </div>\n </div>\n </div>\n `}toggleCalendar(){this.closeAllDropdowns(),this.calendar.classList.contains("visible")?(this.calendar.classList.remove("visible","position-bottom","position-top"),c.openCalendarInstance===this&&(c.openCalendarInstance=""[0])):(c.openCalendarInstance&&c.openCalendarInstance!==this&&c.openCalendarInstance.toggleCalendar(),this.positionCalendar(),this.calendar.classList.add("visible"),c.openCalendarInstance=this)}positionCalendar(){if(!this.input||!this.calendar)return;this.calendar.classList.remove("position-bottom","position-top");const t=this.input.getBoundingClientRect(),e=window.innerHeight;this.calendar.classList.add("position-bottom");const i=this.calendar.style.visibility,r=this.calendar.style.display;this.calendar.style.visibility="hidden",this.calendar.style.display="block";const s=this.calendar.offsetHeight,a=e-t.bottom;if(a<s){const e=t.top;(e>a||e>=s)&&(this.calendar.classList.remove("position-bottom"),this.calendar.classList.add("position-top"))}this.calendar.style.visibility=i,this.calendar.style.display=r}changeMonth(t){if(this.isTransitioning)return;this.isTransitioning=!0;const e=this.daysContainer,i=t>0?"slide-left":"slide-right";e.classList.add(i),this.jalaliMonth=Number(this.jalaliMonth)+t,this.jalaliMonth<1?(this.jalaliMonth=12,this.jalaliYear--):this.jalaliMonth>12&&(this.jalaliMonth=1,this.jalaliYear++),requestAnimationFrame((()=>{setTimeout((()=>{this.updateMonthYearSelectors(),e.innerHTML="",this.renderCalendarContent(),requestAnimationFrame((()=>{e.classList.remove(i),setTimeout((()=>{this.isTransitioning=!1}),50)}))}),200)}))}updateMonthYearSelectors(){if(!this.shadowRoot)return;const t=this.shadowRoot.getElementById("month-select-value"),e=this.shadowRoot.getElementById("year-select-value");t&&(t.textContent=this.persianMonths[this.jalaliMonth-1]),e&&(e.textContent=this.toPersianNum(this.jalaliYear)),this.shadowRoot.querySelectorAll(".month-select-content .select-item").forEach((t=>{t.getAttribute("data-value")===""+this.jalaliMonth?t.classList.add("selected"):t.classList.remove("selected")})),this.shadowRoot.querySelectorAll(".year-select-content .select-item").forEach((t=>{t.getAttribute("data-value")===""+this.jalaliYear?t.classList.add("selected"):t.classList.remove("selected")}))}renderCalendar(){if(this.shadowRoot&&this.daysContainer&&(this.updateMonthYearSelectors(),this.daysContainer.innerHTML="",this.renderCalendarContent(),this.isRangeMode)){const t=this.shadowRoot.querySelector(".footer");t&&t.remove()}}renderCalendarContent(){if(!this.daysContainer)return;const t=i.getDayOfWeek(this.jalaliYear,this.jalaliMonth,1),e=i.getDaysInMonth(this.jalaliYear,this.jalaliMonth),r=new Date,s=i.gregorianToJalali(r.getFullYear(),r.getMonth()+1,r.getDate()),a=(t+1)%7,o=document.createDocumentFragment();for(let t=0;t<a;t++){const t=document.createElement("div");t.classList.add("day","empty"),o.appendChild(t)}for(let t=1;t<=e;t++){const e=document.createElement("div");e.classList.add("day"),e.textContent=this.toPersianNum(t),e.dataset.day=""+t;const i=this.isDateInRange(this.jalaliYear,this.jalaliMonth,t),r=this.isDateDisabled(this.jalaliYear,this.jalaliMonth,t);if(i&&!r||(e.classList.add("disabled"),e.style.opacity="0.4",e.style.cursor="not-allowed"),this.jalaliYear===s[0]&&this.jalaliMonth===s[1]&&t===s[2]&&e.classList.add("today"),this.isRangeMode){const i=[this.jalaliYear,this.jalaliMonth,t];if(e.classList.remove("in-range","range-start","range-end"),this.rangeStart&&this.rangeEnd){const t=this.compareDates(i,this.rangeStart)>=0&&this.compareDates(i,this.rangeEnd)<=0;0===this.compareDates(i,this.rangeStart)?(e.classList.add("range-start"),0===this.compareDates(i,this.rangeEnd)&&e.classList.add("range-end")):0===this.compareDates(i,this.rangeEnd)?e.classList.add("range-end"):t&&e.classList.add("in-range")}else this.rangeStart&&!this.rangeEnd&&0===this.compareDates(i,this.rangeStart)&&e.classList.add("range-start")}else this.selectedDate&&this.jalaliYear===this.selectedDate[0]&&this.jalaliMonth===this.selectedDate[1]&&t===this.selectedDate[2]&&e.classList.add("selected");this.showEvents&&this.addHolidayInfo(e,t),this.setupDayTooltips(e),this.setupDayClickHandler(e,t),o.appendChild(e)}this.daysContainer.appendChild(o)}compareDates(t,e){return t[0]!==e[0]?t[0]-e[0]:t[1]!==e[1]?t[1]-e[1]:t[2]-e[2]}setupDayTooltips(t){t.addEventListener("mouseenter",(()=>{const e=t.querySelector(".event-tooltip");e&&e.classList.add("tooltip-visible")})),t.addEventListener("mouseleave",(()=>{const e=t.querySelector(".event-tooltip");e&&e.classList.remove("tooltip-visible")}))}setupDayClickHandler(t,e){let i=0;t.addEventListener("click",(r=>{r.preventDefault(),r.stopPropagation();const s=(new Date).getTime(),a=s-i;if("ontouchstart"in window||navigator.maxTouchPoints>0)if(a<500&&a>0){const e=t.querySelector(".event-tooltip");if(e){const t=this.shadowRoot?.querySelectorAll(".event-tooltip.tooltip-visible");t?.forEach((t=>t.classList.remove("tooltip-visible"))),e.classList.add("tooltip-visible")}}else this.handleRangeSelection(e);else this.handleRangeSelection(e);i=s}))}addHolidayInfo(t,e){let r=!1;if(5===i.getDayOfWeek(this.jalaliYear,this.jalaliMonth,e)&&(t.classList.add("friday"),r=!0),this.eventUtils.isHoliday(this.jalaliMonth,e,this.eventTypes,this.includeAllTypes)){t.classList.add("holiday"),r=!0;const i=this.eventUtils.getEvents(this.jalaliMonth,e,this.eventTypes,this.includeAllTypes);if(i.length>0){const e=this.createEventTooltip(i);t.appendChild(e)}}return r}createEventTooltip(t){const e=document.createElement("div");return e.classList.add("event-tooltip"),t.forEach((t=>{const i=document.createElement("div");i.classList.add("event-item"),t.holiday&&i.classList.add("holiday");const r=document.createElement("span");r.classList.add("event-type-label"),r.textContent=this.holidayTypeLabels[t.type]||t.type,i.appendChild(r);const s=document.createElement("span");s.textContent=t.title,i.appendChild(s),e.appendChild(i)})),e}navigateToDate(t){const e=i.gregorianToJalali(t.getFullYear(),t.getMonth()+1,t.getDate()),r=this.jalaliYear;this.jalaliYear=e[0],this.jalaliMonth=e[1],r!==this.jalaliYear&&this.eventUtils.refreshEvents(),this.renderCalendar(),this.selectDate(e[2])}goToToday(){this.navigateToDate(new Date)}goToTomorrow(){const t=new Date;t.setDate(t.getDate()+1),this.navigateToDate(t)}selectDate(t){if(this.isDateDisabled(this.jalaliYear,this.jalaliMonth,t)||!this.isDateInRange(this.jalaliYear,this.jalaliMonth,t))return;this.jalaliDay=t,this.selectedDate=[this.jalaliYear,this.jalaliMonth,this.jalaliDay],this.formatAndSetValue();const e=this.eventUtils.getEvents(this.jalaliMonth,t,this.eventTypes,this.includeAllTypes),r=this.formatDate(this.selectedDate,this.format),s=i.jalaliToGregorian(this.jalaliYear,this.jalaliMonth,this.jalaliDay),a=this.jalaliToISOString(this.selectedDate);this.dispatchEvent(new CustomEvent("change",{detail:{jalali:this.selectedDate,gregorian:s,isHoliday:this.eventUtils.isHoliday(this.jalaliMonth,t,this.eventTypes,this.includeAllTypes),events:e,formattedDate:r,isoString:a},bubbles:!0})),this.closeAllDropdowns(),this.toggleCalendar(),this.renderCalendar()}formatAndSetValue(){if(this.isRangeMode){if(!this.rangeStart||!this.rangeEnd)return void(this.input.value="");const t=t=>{const[e,i,r]=t;return this.formatDate(t,this.format)};this.input.value=`${t(this.rangeStart)}- ${t(this.rangeEnd)}`}else this.input.value=this.selectedDate?this.formatDate(this.selectedDate,this.format):""}formatDate(t,e){if(!t)return"";const[i,r,s]=t,a=this.handleSpecialFormat(e,i,r,s);return a!==""[0]?a:this.handleGeneralFormat(e,i,r,s)}handleSpecialFormat(t,e,i,r){const s={"YYYY/MM/DD":()=>`${this.toPersianNum(e)}/${this.toPersianNum((""+i).padStart(2,"0"))}/${this.toPersianNum((""+r).padStart(2,"0"))}`,"YYYY-MM-DD":()=>`${this.toPersianNum(e)}-${this.toPersianNum((""+i).padStart(2,"0"))}-${this.toPersianNum((""+r).padStart(2,"0"))}`,"YYYY/MM/DDth":()=>`${this.toPersianNum(e)}/${this.toPersianNum((""+i).padStart(2,"0"))}/${this.toPersianNum(r)}ام`};return s[t]?.()||""[0]}handleGeneralFormat(t,e,i,r){const s=t.split(/(\s+)/),a=[];for(let t=0;t<s.length;t++){const o=s[t];if(!o.trim()){a.push(o);continue}let n=this.replaceFormatTokens(o,e,i,r);a.push(n),t<s.length-1&&s[t+1].trim()&&a.push(" ")}return a.join("")}replaceFormatTokens(t,e,i,r){let s=t;return s.includes("dddd")&&(s=s.replace("dddd",this.getWeekdayName(e,i,r))),s.includes("MMMM")?s=s.replace("MMMM",this.persianMonths[i-1]):s.includes("MMM")&&(s=s.replace("MMM",this.persianMonths[i-1].substring(0,3))),s=s.replace("YYYY",this.toPersianNum(e)),s=s.replace("MM",this.toPersianNum((""+i).padStart(2,"0"))),s=s.replace("DD",this.toPersianNum((""+r).padStart(2,"0"))),s.includes("th")&&(s=s.replace("th","ام")),s}isValidFormat(t){const e=t.includes("YYYY"),i=t.includes("MM"),r=t.includes("DD"),s=/[^YMD\/\-\. dth]/g.test(t);return"YYYY/MM"===t||"DD/MM"===t||"DD.MM.YYYY"===t||"YYYY/MM/DDth"===t||[e,i,r].filter(Boolean).length>=2&&!s}getWeekdayName(t,e,i){return["شنبه","یکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنج‌شنبه","جمعه"][new Date(t,e-1,i).getDay()]}handleMonthChange(t,e){this.jalaliMonth!==t&&(this.jalaliMonth=t,this.renderCalendar())}handleYearChange(t){if(this.jalaliYear===t)return;const e=this.jalaliYear;this.jalaliYear=t,e!==t&&this.eventUtils.refreshEvents(),this.renderCalendar()}setValue(t,e,i){this.selectedDate=[t,e,i],this.jalaliYear=t,this.jalaliMonth=e,this.jalaliDay=i,this.formatAndSetValue(),this.renderCalendar()}getValue(){return this.selectedDate?[...this.selectedDate]:""[0]}isSelectedDateHoliday(){return!!this.selectedDate&&this.eventUtils.isHoliday(this.selectedDate[1],this.selectedDate[2],this.eventTypes,this.includeAllTypes)}getSelectedDateEvents(){return this.selectedDate?[...this.eventUtils.getEvents(this.selectedDate[1],this.selectedDate[2],this.eventTypes,this.includeAllTypes)]:[]}clear(){this.isRangeMode?(this.rangeStart=""[0],this.rangeEnd=""[0]):this.selectedDate=""[0],this.input.value="",this.renderCalendar()}initTouchGestures(){if(!this.calendar||!this.shadowRoot)return;let t=0,e=0,i=0,r=!1,s=!0;this.calendar.addEventListener("touchstart",(a=>{if(!this.calendar?.classList.contains("visible"))return;const o=a.touches[0];t=o.clientX,e=o.clientY,i=Date.now(),r=!1,s=!0}),{passive:!0}),this.calendar.addEventListener("touchmove",(i=>{if(!this.calendar?.classList.contains("visible"))return;const a=i.touches[0],o=a.clientX-t;if(r||(r=Math.abs(a.clientY-e)>Math.abs(o)),r)s=!1;else if(Math.abs(o)>10&&s)try{i.preventDefault()}catch(t){s=!1}}),{passive:!1}),this.calendar.addEventListener("touchend",(e=>{if(!this.calendar?.classList.contains("visible")||r)return;const s=e.changedTouches[0].clientX-t;if(Date.now()-i<300&&Math.abs(s)>50&&!th