@forcecalendar/interface 1.0.61 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/force-calendar-interface.esm.js +1669 -2151
- package/dist/force-calendar-interface.esm.js.map +1 -1
- package/dist/force-calendar-interface.umd.js +141 -119
- package/dist/force-calendar-interface.umd.js.map +1 -1
- package/package.json +11 -5
- package/src/components/ForceCalendar.js +21 -4
- package/src/renderers/BaseViewRenderer.js +39 -5
- package/src/renderers/MonthViewRenderer.js +140 -4
- package/types/components/EventForm.d.ts +42 -0
- package/types/components/ForceCalendar.d.ts +78 -0
- package/types/core/BaseComponent.d.ts +68 -0
- package/types/core/EventBus.d.ts +71 -0
- package/types/core/StateManager.d.ts +112 -0
- package/types/index.d.ts +17 -0
- package/types/renderers/BaseViewRenderer.d.ts +122 -0
- package/types/renderers/DayViewRenderer.d.ts +28 -0
- package/types/renderers/MonthViewRenderer.d.ts +28 -0
- package/types/renderers/WeekViewRenderer.d.ts +21 -0
- package/types/renderers/index.d.ts +10 -0
- package/types/utils/DOMUtils.d.ts +121 -0
- package/types/utils/DateUtils.d.ts +61 -0
- package/types/utils/StyleUtils.d.ts +146 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("@forcecalendar/core")):typeof define==`function`&&define.amd?define([`exports`,`@forcecalendar/core`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ForceCalendarInterface={},e.ForceCalendarCore))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:`open`}),this._listeners=[],this._state=null,this._props=new Map,this._initialized=!1}connectedCallback(){this._initialized||=(this.initialize(),!0),this.mount()}disconnectedCallback(){this.unmount(),this.cleanup(),this._styleEl=null,this._contentWrapper=null}initialize(){}mount(){this.render()}unmount(){}cleanup(){this._listeners.forEach(({element:e,event:t,handler:n})=>{e.removeEventListener(t,n)}),this._listeners=[]}setState(e){let t=this._state;this._state={...this._state,...e},this.stateChanged(t,this._state),this.render()}getState(){return this._state}stateChanged(e,t){}setProp(e,t){let n=this._props.get(e);this._props.set(e,t),this.propChanged(e,n,t)}getProp(e){return this._props.get(e)}propChanged(e,t,n){}addListener(e,t,n){if(!e||!t||!n){console.warn(`addListener called with invalid parameters`,{element:e,event:t,handler:n});return}let r=n.bind(this);e.addEventListener(t,r),this._listeners.push({element:e,event:t,handler:r})}emit(e,t={}){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}getStyles(){return``}getBaseStyles(){return`
|
|
2
2
|
:host {
|
|
3
3
|
display: block;
|
|
4
4
|
box-sizing: border-box;
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
*, *::before, *::after {
|
|
8
8
|
box-sizing: inherit;
|
|
9
9
|
}
|
|
10
|
-
`}render(){this.cleanup();
|
|
11
|
-
`+this.getStyles();const e=this._saveScrollPositions(),r=this._getActiveElementSelector();this._contentWrapper.innerHTML=t,this._restoreScrollPositions(e),this._restoreFocus(r),this.afterRender()}_saveScrollPositions(){const t=new Map;return this._contentWrapper&&this._contentWrapper.querySelectorAll("[id]").forEach(r=>{(r.scrollTop!==0||r.scrollLeft!==0)&&t.set(r.id,{top:r.scrollTop,left:r.scrollLeft})}),t}_restoreScrollPositions(t){if(!this._contentWrapper||t.size===0)return;const e=typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape:r=>String(r).replace(/["\\]/g,"\\$&");t.forEach((r,i)=>{const s=this._contentWrapper.querySelector(`[id="${e(i)}"]`);s&&(s.scrollTop=r.top,s.scrollLeft=r.left)})}_getActiveElementSelector(){const t=this.shadowRoot.activeElement;return!t||t===this._contentWrapper?null:t.id?`[id="${CSS.escape(t.id)}"]`:t.dataset&&t.dataset.action?`[data-action="${CSS.escape(t.dataset.action)}"]`:t.dataset&&t.dataset.view?`[data-view="${CSS.escape(t.dataset.view)}"]`:t.tagName?t.tagName.toLowerCase():null}_restoreFocus(t){if(!(!t||!this._contentWrapper))try{const e=this._contentWrapper.querySelector(t);e&&typeof e.focus=="function"&&e.focus()}catch{}}template(){return""}afterRender(){}$(t){return this.shadowRoot.querySelector(t)}$$(t){return this.shadowRoot.querySelectorAll(t)}static get observedAttributes(){return[]}attributeChangedCallback(t,e,r){this.setProp(t,r),this._initialized&&this.render()}}class M{constructor(){this.events=new Map,this.wildcardHandlers=new Set}on(t,e,r={}){const{once:i=!1,priority:s=0}=r;if(t.includes("*")){const o={pattern:t,handler:e,once:i,priority:s};return this.wildcardHandlers.add(o),()=>this.wildcardHandlers.delete(o)}this.events.has(t)||this.events.set(t,[]);const n={handler:e,once:i,priority:s},a=this.events.get(t);return a.push(n),a.sort((o,c)=>c.priority-o.priority),()=>{const o=a.indexOf(n);o>-1&&a.splice(o,1)}}once(t,e,r={}){return this.on(t,e,{...r,once:!0})}off(t,e){if(t.includes("*")){for(const s of this.wildcardHandlers)if(s.pattern===t&&s.handler===e){this.wildcardHandlers.delete(s);return}return}if(!this.events.has(t))return;const r=this.events.get(t),i=r.findIndex(s=>s.handler===e);i>-1&&r.splice(i,1),r.length===0&&this.events.delete(t)}offWildcard(t){for(const e of[...this.wildcardHandlers])e.pattern===t&&this.wildcardHandlers.delete(e)}offAll(t){for(const[e,r]of this.events){const i=r.findIndex(s=>s.handler===t);i>-1&&r.splice(i,1),r.length===0&&this.events.delete(e)}for(const e of[...this.wildcardHandlers])e.handler===t&&this.wildcardHandlers.delete(e)}emit(t,e){if(this.events.has(t)){const i=[...this.events.get(t)];for(const s of i){const{handler:n,once:a}=s;a&&this.off(t,n);try{n(e,t)}catch(o){console.error(`Error in event handler for ${t}:`,o)}}}const r=[];for(const i of[...this.wildcardHandlers])if(this.matchesPattern(t,i.pattern)){const{handler:s,once:n}=i;n&&r.push(i);try{s(e,t)}catch(a){console.error(`Error in wildcard handler for ${t}:`,a)}}r.forEach(i=>this.wildcardHandlers.delete(i))}matchesPattern(t,e){const r=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&");return new RegExp("^"+r.replace(/\*/g,".*")+"$").test(t)}clear(){this.events.clear(),this.wildcardHandlers.clear()}getEventNames(){return Array.from(this.events.keys())}getHandlerCount(t){return this.events.has(t)?this.events.get(t).length:0}getWildcardHandlerCount(){return this.wildcardHandlers.size}getTotalHandlerCount(){let t=this.wildcardHandlers.size;for(const e of this.events.values())t+=e.length;return t}}const I=new M;class T{constructor(t={}){this.eventBus=new M,this.calendar=new f.Calendar({view:t.view||"month",date:t.date||new Date,weekStartsOn:t.weekStartsOn??0,locale:t.locale||"en-US",timeZone:t.timeZone||Intl.DateTimeFormat().resolvedOptions().timeZone,...t}),this.state={view:this.calendar.getView(),currentDate:this.calendar.getCurrentDate(),events:[],selectedEvent:null,selectedDate:null,loading:!1,error:null,config:{...t}},this.subscribers=new Set,this.subscribe=this.subscribe.bind(this),this.unsubscribe=this.unsubscribe.bind(this),this.setState=this.setState.bind(this),this._syncEventsFromCore({silent:!0})}_syncEventsFromCore(t={}){const{force:e=!1}=t,r=this.calendar.getEvents()||[];return(e||this.state.events.length!==r.length||!this._eventsMatch(this.state.events,r))&&this.setState({events:[...r]},t),r}_eventsMatch(t,e){if(t.length!==e.length)return!1;const r=new Set(t.map(i=>i.id));return e.every(i=>r.has(i.id))}getState(){return{...this.state,config:{...this.state.config},events:[...this.state.events]}}setState(t,e={}){const{silent:r=!1}=e,i={...this.state};return this.state={...this.state,...t},r||(this.notifySubscribers(i,this.state),this.emitStateChange(i,this.state)),this.state}subscribe(t,e=null){return this.subscribers.add(t),e&&(this._subscriberIds||(this._subscriberIds=new Map),this._subscriberIds.set(e,t)),()=>this.unsubscribe(t,e)}unsubscribe(t,e=null){this.subscribers.delete(t),e&&this._subscriberIds&&this._subscriberIds.delete(e)}unsubscribeById(t){if(!this._subscriberIds)return!1;const e=this._subscriberIds.get(t);return e?(this.subscribers.delete(e),this._subscriberIds.delete(t),!0):!1}getSubscriberCount(){return this.subscribers.size}notifySubscribers(t,e){this.subscribers.forEach(r=>{try{r(e,t)}catch(i){console.error("Error in state subscriber:",i)}})}emitStateChange(t,e){const r=Object.keys(e).filter(i=>t[i]!==e[i]);r.forEach(i=>{this.eventBus.emit(`state:${i}:changed`,{oldValue:t[i],newValue:e[i],state:e})}),r.length>0&&this.eventBus.emit("state:changed",{oldState:t,newState:e,changedKeys:r})}setView(t){this.calendar.setView(t),this.setState({view:t}),this.eventBus.emit("view:changed",{view:t})}getView(){return this.state.view}setDate(t){this.calendar.goToDate(t),this.setState({currentDate:this.calendar.getCurrentDate()}),this.eventBus.emit("date:changed",{date:this.state.currentDate})}getCurrentDate(){return this.state.currentDate}next(){this.calendar.next(),this.setState({currentDate:this.calendar.getCurrentDate()}),this.eventBus.emit("navigation:next",{date:this.state.currentDate})}previous(){this.calendar.previous(),this.setState({currentDate:this.calendar.getCurrentDate()}),this.eventBus.emit("navigation:previous",{date:this.state.currentDate})}today(){this.calendar.today(),this.setState({currentDate:this.calendar.getCurrentDate()}),this.eventBus.emit("navigation:today",{date:this.state.currentDate})}goToDate(t){this.calendar.goToDate(t),this.setState({currentDate:this.calendar.getCurrentDate()}),this.eventBus.emit("navigation:goto",{date:this.state.currentDate})}addEvent(t){const e=this.calendar.addEvent(t);return e?(this._syncEventsFromCore(),this.eventBus.emit("event:add",{event:e}),this.eventBus.emit("event:added",{event:e}),e):(console.error("Failed to add event to calendar"),this.eventBus.emit("event:error",{action:"add",event:t,error:"Failed to add event"}),null)}updateEvent(t,e){this._syncEventsFromCore({silent:!0});const r=this.calendar.updateEvent(t,e);return r?(this._syncEventsFromCore({force:!0}),this.eventBus.emit("event:update",{event:r}),this.eventBus.emit("event:updated",{event:r}),r):(console.error(`Failed to update event: ${t}`),this.eventBus.emit("event:error",{action:"update",eventId:t,updates:e,error:"Event not found in calendar"}),null)}deleteEvent(t){return this._syncEventsFromCore({silent:!0}),this.calendar.removeEvent(t)?(this._syncEventsFromCore(),this.eventBus.emit("event:remove",{eventId:t}),this.eventBus.emit("event:deleted",{eventId:t}),!0):(console.error(`Failed to delete event: ${t}`),this.eventBus.emit("event:error",{action:"delete",eventId:t,error:"Event not found"}),!1)}getEvents(){return this.calendar.getEvents()||[]}syncEvents(){return this._syncEventsFromCore()}getEventsForDate(t){return this.calendar.getEventsForDate(t)}getEventsInRange(t,e){return this.calendar.getEventsInRange(t,e)}getViewData(){const t=this.calendar.getViewData();return this.enrichViewData(t)}enrichViewData(t){var i;const e={...t},r=(i=this.state.selectedDate)==null?void 0:i.toDateString();if(e.weeks&&(e.weeks=e.weeks.map(s=>({...s,days:s.days.map(n=>{const a=new Date(n.date);return{...n,isSelected:a.toDateString()===r,events:n.events||this.getEventsForDate(a)}})}))),e.days&&(e.days=e.days.map(s=>{const n=new Date(s.date);return{...s,isSelected:n.toDateString()===r,events:s.events||this.getEventsForDate(n)}})),e.date&&!e.days&&!e.weeks){const s=new Date(e.date);e.isSelected=s.toDateString()===r,e.events=e.events||this.getEventsForDate(s)}return e}selectEvent(t){this.setState({selectedEvent:t}),this.eventBus.emit("event:selected",{event:t})}selectEventById(t){const e=this.state.events.find(r=>r.id===t);e&&this.selectEvent(e)}deselectEvent(){this.setState({selectedEvent:null}),this.eventBus.emit("event:deselected",{})}selectDate(t){this.setState({selectedDate:t}),this.eventBus.emit("date:selected",{date:t})}deselectDate(){this.setState({selectedDate:null}),this.eventBus.emit("date:deselected",{})}isToday(t){const e=new Date;return t.toDateString()===e.toDateString()}isSelectedDate(t){return this.state.selectedDate&&t.toDateString()===this.state.selectedDate.toDateString()}isWeekend(t){const e=t.getDay();return e===0||e===6}setLoading(t){this.setState({loading:t})}setError(t){this.setState({error:t}),t&&this.eventBus.emit("error",{error:t})}clearError(){this.setState({error:null})}updateConfig(t){this.setState({config:{...this.state.config,...t}}),t.weekStartsOn!==void 0&&this.calendar.setWeekStartsOn(t.weekStartsOn),t.locale!==void 0&&this.calendar.setLocale(t.locale),t.timeZone!==void 0&&this.calendar.setTimezone(t.timeZone)}destroy(){this.subscribers.clear(),this._subscriberIds&&(this._subscriberIds.clear(),this._subscriberIds=null),this.eventBus&&(this.eventBus.clear(),this.eventBus=null),this.state=null,this.calendar=null}}class p extends f.DateUtils{static formatDate(t,e="default",r="en-US"){if(!t)return"";const i={default:{year:"numeric",month:"long",day:"numeric"},short:{year:"numeric",month:"short",day:"numeric"},long:{weekday:"long",year:"numeric",month:"long",day:"numeric"},month:{year:"numeric",month:"long"},monthShort:{year:"numeric",month:"short"},day:{weekday:"long",day:"numeric"},dayShort:{weekday:"short",day:"numeric"},time:{hour:"numeric",minute:"2-digit"},timeShort:{hour:"numeric"},datetime:{year:"numeric",month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}},s=i[e]||i.default;return new Intl.DateTimeFormat(r,s).format(t)}static formatTime(t,e=!0,r=!1,i="en-US"){if(!t)return"";const s={hour:"numeric",minute:e?"2-digit":void 0,hour12:!r};return new Intl.DateTimeFormat(i,s).format(t)}static formatDateRange(t,e,r="en-US"){if(!t)return"";if(!e||this.isSameDay(t,e))return this.formatDate(t,"default",r);const i=this.isSameYear(t,e)?"short":"default";return`${this.formatDate(t,i,r)} - ${this.formatDate(e,"default",r)}`}static formatTimeRange(t,e,r="en-US"){if(!t)return"";const i=this.formatTime(t,!0,!1,r);if(!e)return i;const s=this.formatTime(e,!0,!1,r);return`${i} - ${s}`}static getRelativeTime(t,e=new Date,r="en-US"){const i=new Intl.RelativeTimeFormat(r,{numeric:"auto"}),s=t-e,n=Math.floor(s/1e3),a=Math.floor(n/60),o=Math.floor(a/60),c=Math.floor(o/24),l=Math.floor(c/7),h=Math.floor(c/30),b=Math.floor(c/365);return Math.abs(n)<60?i.format(n,"second"):Math.abs(a)<60?i.format(a,"minute"):Math.abs(o)<24?i.format(o,"hour"):Math.abs(c)<7?i.format(c,"day"):Math.abs(l)<4?i.format(l,"week"):Math.abs(h)<12?i.format(h,"month"):i.format(b,"year")}static isToday(t){const e=new Date;return this.isSameDay(t,e)}static isPast(t){return t<new Date}static isFuture(t){return t>new Date}static getWeekNumber(t){const e=new Date(t.getFullYear(),0,1),r=(t-e)/864e5;return Math.ceil((r+e.getDay()+1)/7)}static getDayAbbreviation(t,e="en-US"){const r=new Date(2024,0,7+t);return new Intl.DateTimeFormat(e,{weekday:"short"}).format(r)}static getDayName(t,e="en-US"){const r=new Date(2024,0,7+t);return new Intl.DateTimeFormat(e,{weekday:"long"}).format(r)}static getMonthName(t,e="long",r="en-US"){const i=new Date(2024,t,1);return new Intl.DateTimeFormat(r,{month:e}).format(i)}static parseTimeString(t,e=new Date){const r=new Date(e),[i,s]=t.split(/\s+/),[n,a]=i.split(":").map(Number);let o=n;return s&&(s.toLowerCase()==="pm"&&n<12?o=n+12:s.toLowerCase()==="am"&&n===12&&(o=0)),r.setHours(o,a||0,0,0),r}}class m{static createElement(t,e={},r=[]){const i=document.createElement(t);return Object.entries(e).forEach(([s,n])=>{if(s==="className")i.className=n;else if(s==="style"&&typeof n=="object")Object.assign(i.style,n);else if(s.startsWith("data-"))i.setAttribute(s,n);else if(s.startsWith("on")&&typeof n=="function"){const a=s.slice(2).toLowerCase();i.addEventListener(a,n)}else i[s]=n}),r.forEach(s=>{typeof s=="string"?i.appendChild(document.createTextNode(s)):s instanceof Node&&i.appendChild(s)}),i}static addEventListeners(t,e){return Object.entries(e).forEach(([r,i])=>{t.addEventListener(r,i)}),()=>{Object.entries(e).forEach(([r,i])=>{t.removeEventListener(r,i)})}}static delegate(t,e,r,i){const s=n=>{const a=n.target.closest(e);a&&t.contains(a)&&i.call(a,n)};return t.addEventListener(r,s),()=>t.removeEventListener(r,s)}static getPosition(t){const e=t.getBoundingClientRect();return{top:e.top+window.scrollY,left:e.left+window.scrollX,bottom:e.bottom+window.scrollY,right:e.right+window.scrollX,width:e.width,height:e.height}}static isInViewport(t,e=0){const r=t.getBoundingClientRect();return r.top>=-e&&r.left>=-e&&r.bottom<=(window.innerHeight||document.documentElement.clientHeight)+e&&r.right<=(window.innerWidth||document.documentElement.clientWidth)+e}static scrollToElement(t,e={}){const{behavior:r="smooth",block:i="start",inline:s="nearest"}=e;t.scrollIntoView({behavior:r,block:i,inline:s})}static getStyle(t,e){return window.getComputedStyle(t).getPropertyValue(e)}static setStyles(t,e){Object.assign(t.style,e)}static async animateClass(t,e,r=300){t.classList.add(e),await this.wait(r),t.classList.remove(e)}static waitForAnimation(t,e="animationend",r=3e3){return new Promise(i=>{let s=null;const n=()=>{s!==null&&clearTimeout(s),t.removeEventListener(e,n),i()};t.addEventListener(e,n),r>0&&(s=setTimeout(n,r))})}static wait(t){return new Promise(e=>setTimeout(e,t))}static parseHTML(t,{sanitize:e=!0}={}){const r=document.createElement("template");return r.innerHTML=t.trim(),e&&this._sanitizeNode(r.content),r.content.firstChild}static _sanitizeNode(t){t.querySelectorAll("script, iframe, object, embed, link, meta, base").forEach(s=>s.remove());const r=document.createTreeWalker(t,NodeFilter.SHOW_ELEMENT);let i=r.nextNode();for(;i;){for(const s of Array.from(i.attributes)){const n=s.name.toLowerCase(),a=s.value.replace(/[\u0000-\u0020]/g,"").toLowerCase();(n.startsWith("on")||a.startsWith("javascript:")||a.startsWith("data:text/html"))&&i.removeAttribute(s.name)}i=r.nextNode()}}static escapeHTML(t){const e=document.createElement("div");return e.textContent=t,e.innerHTML}static debounce(t,e=250){let r;return function(...s){clearTimeout(r),r=setTimeout(()=>t.apply(this,s),e)}}static throttle(t,e=250){let r;return function(...i){r||(t.apply(this,i),r=!0,setTimeout(()=>r=!1,e))}}static closest(t,e){return t.closest(e)}static parents(t,e){const r=[];let i=t.parentElement;for(;i;)i.matches(e)&&r.push(i),i=i.parentElement;return r}static getOuterDimensions(t){const e=window.getComputedStyle(t),r={top:parseInt(e.marginTop),right:parseInt(e.marginRight),bottom:parseInt(e.marginBottom),left:parseInt(e.marginLeft)};return{width:t.offsetWidth+r.left+r.right,height:t.offsetHeight+r.top+r.bottom,margin:r}}static cloneWithEvents(t,e=!0){return t.cloneNode(e)}static trapFocus(t){const e=t.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');if(e.length===0)return t.setAttribute("tabindex","-1"),t.focus(),()=>t.removeAttribute("tabindex");const r=e[0],i=e[e.length-1],s=n=>{if(n.key!=="Tab")return;const o=t.getRootNode().activeElement??document.activeElement;n.shiftKey?o===r&&(i==null||i.focus(),n.preventDefault()):o===i&&(r==null||r.focus(),n.preventDefault())};return t.addEventListener("keydown",s),r==null||r.focus(),()=>t.removeEventListener("keydown",s)}}class u{static getCSSVariable(t,e=document.documentElement){return getComputedStyle(e).getPropertyValue(t).trim()}static setCSSVariables(t,e=document.documentElement){Object.entries(t).forEach(([r,i])=>{e.style.setProperty(r,i)})}static getBaseStyles(){return`
|
|
10
|
+
`}render(){this.cleanup();let e=this.template();this._styleEl||(this._styleEl=document.createElement(`style`),this.shadowRoot.appendChild(this._styleEl),this._contentWrapper=document.createElement(`div`),this._contentWrapper.setAttribute(`id`,`fc-root`),this._contentWrapper.style.display=`contents`,this.shadowRoot.appendChild(this._contentWrapper)),this._styleEl.textContent=this.getBaseStyles()+`
|
|
11
|
+
`+this.getStyles();let t=this._saveScrollPositions(),n=this._getActiveElementSelector();this._contentWrapper.innerHTML=e,this._restoreScrollPositions(t),this._restoreFocus(n),this.afterRender()}_saveScrollPositions(){let e=new Map;return this._contentWrapper&&this._contentWrapper.querySelectorAll(`[id]`).forEach(t=>{(t.scrollTop!==0||t.scrollLeft!==0)&&e.set(t.id,{top:t.scrollTop,left:t.scrollLeft})}),e}_restoreScrollPositions(e){if(!this._contentWrapper||e.size===0)return;let t=typeof CSS<`u`&&typeof CSS.escape==`function`?CSS.escape:e=>String(e).replace(/["\\]/g,`\\$&`);e.forEach((e,n)=>{let r=this._contentWrapper.querySelector(`[id="${t(n)}"]`);r&&(r.scrollTop=e.top,r.scrollLeft=e.left)})}_getActiveElementSelector(){let e=this.shadowRoot.activeElement;return!e||e===this._contentWrapper?null:e.id?`[id="${CSS.escape(e.id)}"]`:e.dataset&&e.dataset.action?`[data-action="${CSS.escape(e.dataset.action)}"]`:e.dataset&&e.dataset.view?`[data-view="${CSS.escape(e.dataset.view)}"]`:e.tagName?e.tagName.toLowerCase():null}_restoreFocus(e){if(!(!e||!this._contentWrapper))try{let t=this._contentWrapper.querySelector(e);t&&typeof t.focus==`function`&&t.focus()}catch{}}template(){return``}afterRender(){}$(e){return this.shadowRoot.querySelector(e)}$$(e){return this.shadowRoot.querySelectorAll(e)}static get observedAttributes(){return[]}attributeChangedCallback(e,t,n){this.setProp(e,n),this._initialized&&this.render()}},r=class{constructor(){this.events=new Map,this.wildcardHandlers=new Set}on(e,t,n={}){let{once:r=!1,priority:i=0}=n;if(e.includes(`*`)){let n={pattern:e,handler:t,once:r,priority:i};return this.wildcardHandlers.add(n),()=>this.wildcardHandlers.delete(n)}this.events.has(e)||this.events.set(e,[]);let a={handler:t,once:r,priority:i},o=this.events.get(e);return o.push(a),o.sort((e,t)=>t.priority-e.priority),()=>{let e=o.indexOf(a);e>-1&&o.splice(e,1)}}once(e,t,n={}){return this.on(e,t,{...n,once:!0})}off(e,t){if(e.includes(`*`)){for(let n of this.wildcardHandlers)if(n.pattern===e&&n.handler===t){this.wildcardHandlers.delete(n);return}return}if(!this.events.has(e))return;let n=this.events.get(e),r=n.findIndex(e=>e.handler===t);r>-1&&n.splice(r,1),n.length===0&&this.events.delete(e)}offWildcard(e){for(let t of[...this.wildcardHandlers])t.pattern===e&&this.wildcardHandlers.delete(t)}offAll(e){for(let[t,n]of this.events){let r=n.findIndex(t=>t.handler===e);r>-1&&n.splice(r,1),n.length===0&&this.events.delete(t)}for(let t of[...this.wildcardHandlers])t.handler===e&&this.wildcardHandlers.delete(t)}emit(e,t){if(this.events.has(e)){let n=[...this.events.get(e)];for(let r of n){let{handler:n,once:i}=r;i&&this.off(e,n);try{n(t,e)}catch(t){console.error(`Error in event handler for ${e}:`,t)}}}let n=[];for(let r of[...this.wildcardHandlers])if(this.matchesPattern(e,r.pattern)){let{handler:i,once:a}=r;a&&n.push(r);try{i(t,e)}catch(t){console.error(`Error in wildcard handler for ${e}:`,t)}}n.forEach(e=>this.wildcardHandlers.delete(e))}matchesPattern(e,t){let n=t.replace(/[.+?^${}()|[\]\\]/g,`\\$&`);return RegExp(`^`+n.replace(/\*/g,`.*`)+`$`).test(e)}clear(){this.events.clear(),this.wildcardHandlers.clear()}getEventNames(){return Array.from(this.events.keys())}getHandlerCount(e){return this.events.has(e)?this.events.get(e).length:0}getWildcardHandlerCount(){return this.wildcardHandlers.size}getTotalHandlerCount(){let e=this.wildcardHandlers.size;for(let t of this.events.values())e+=t.length;return e}},i=new r,a=class{constructor(e={}){this.eventBus=new r,this.calendar=new t.Calendar({view:e.view||`month`,date:e.date||new Date,weekStartsOn:e.weekStartsOn??0,locale:e.locale||`en-US`,timeZone:e.timeZone||Intl.DateTimeFormat().resolvedOptions().timeZone,...e}),this.state={view:this.calendar.getView(),currentDate:this.calendar.getCurrentDate(),events:[],selectedEvent:null,selectedDate:null,loading:!1,error:null,config:{...e}},this.subscribers=new Set,this.subscribe=this.subscribe.bind(this),this.unsubscribe=this.unsubscribe.bind(this),this.setState=this.setState.bind(this),this._syncEventsFromCore({silent:!0})}_syncEventsFromCore(e={}){let{force:t=!1}=e,n=this.calendar.getEvents()||[];return(t||this.state.events.length!==n.length||!this._eventsMatch(this.state.events,n))&&this.setState({events:[...n]},e),n}_eventsMatch(e,t){if(e.length!==t.length)return!1;let n=new Set(e.map(e=>e.id));return t.every(e=>n.has(e.id))}getState(){return{...this.state,config:{...this.state.config},events:[...this.state.events]}}setState(e,t={}){let{silent:n=!1}=t,r={...this.state};return this.state={...this.state,...e},n||(this.notifySubscribers(r,this.state),this.emitStateChange(r,this.state)),this.state}subscribe(e,t=null){return this.subscribers.add(e),t&&(this._subscriberIds||=new Map,this._subscriberIds.set(t,e)),()=>this.unsubscribe(e,t)}unsubscribe(e,t=null){this.subscribers.delete(e),t&&this._subscriberIds&&this._subscriberIds.delete(t)}unsubscribeById(e){if(!this._subscriberIds)return!1;let t=this._subscriberIds.get(e);return t?(this.subscribers.delete(t),this._subscriberIds.delete(e),!0):!1}getSubscriberCount(){return this.subscribers.size}notifySubscribers(e,t){this.subscribers.forEach(n=>{try{n(t,e)}catch(e){console.error(`Error in state subscriber:`,e)}})}emitStateChange(e,t){let n=Object.keys(t).filter(n=>e[n]!==t[n]);n.forEach(n=>{this.eventBus.emit(`state:${n}:changed`,{oldValue:e[n],newValue:t[n],state:t})}),n.length>0&&this.eventBus.emit(`state:changed`,{oldState:e,newState:t,changedKeys:n})}setView(e){this.calendar.setView(e),this.setState({view:e}),this.eventBus.emit(`view:changed`,{view:e})}getView(){return this.state.view}setDate(e){this.calendar.goToDate(e),this.setState({currentDate:this.calendar.getCurrentDate()}),this.eventBus.emit(`date:changed`,{date:this.state.currentDate})}getCurrentDate(){return this.state.currentDate}next(){this.calendar.next(),this.setState({currentDate:this.calendar.getCurrentDate()}),this.eventBus.emit(`navigation:next`,{date:this.state.currentDate})}previous(){this.calendar.previous(),this.setState({currentDate:this.calendar.getCurrentDate()}),this.eventBus.emit(`navigation:previous`,{date:this.state.currentDate})}today(){this.calendar.today(),this.setState({currentDate:this.calendar.getCurrentDate()}),this.eventBus.emit(`navigation:today`,{date:this.state.currentDate})}goToDate(e){this.calendar.goToDate(e),this.setState({currentDate:this.calendar.getCurrentDate()}),this.eventBus.emit(`navigation:goto`,{date:this.state.currentDate})}addEvent(e){let t=this.calendar.addEvent(e);return t?(this._syncEventsFromCore(),this.eventBus.emit(`event:add`,{event:t}),this.eventBus.emit(`event:added`,{event:t}),t):(console.error(`Failed to add event to calendar`),this.eventBus.emit(`event:error`,{action:`add`,event:e,error:`Failed to add event`}),null)}updateEvent(e,t){this._syncEventsFromCore({silent:!0});let n=this.calendar.updateEvent(e,t);return n?(this._syncEventsFromCore({force:!0}),this.eventBus.emit(`event:update`,{event:n}),this.eventBus.emit(`event:updated`,{event:n}),n):(console.error(`Failed to update event: ${e}`),this.eventBus.emit(`event:error`,{action:`update`,eventId:e,updates:t,error:`Event not found in calendar`}),null)}deleteEvent(e){return this._syncEventsFromCore({silent:!0}),this.calendar.removeEvent(e)?(this._syncEventsFromCore(),this.eventBus.emit(`event:remove`,{eventId:e}),this.eventBus.emit(`event:deleted`,{eventId:e}),!0):(console.error(`Failed to delete event: ${e}`),this.eventBus.emit(`event:error`,{action:`delete`,eventId:e,error:`Event not found`}),!1)}getEvents(){return this.calendar.getEvents()||[]}syncEvents(){return this._syncEventsFromCore()}getEventsForDate(e){return this.calendar.getEventsForDate(e)}getEventsInRange(e,t){return this.calendar.getEventsInRange(e,t)}getViewData(){let e=this.calendar.getViewData();return this.enrichViewData(e)}enrichViewData(e){let t={...e},n=this.state.selectedDate?.toDateString();if(t.weeks&&=t.weeks.map(e=>({...e,days:e.days.map(e=>{let t=new Date(e.date);return{...e,isSelected:t.toDateString()===n,events:e.events||this.getEventsForDate(t)}})})),t.days&&=t.days.map(e=>{let t=new Date(e.date);return{...e,isSelected:t.toDateString()===n,events:e.events||this.getEventsForDate(t)}}),t.date&&!t.days&&!t.weeks){let e=new Date(t.date);t.isSelected=e.toDateString()===n,t.events=t.events||this.getEventsForDate(e)}return t}selectEvent(e){this.setState({selectedEvent:e}),this.eventBus.emit(`event:selected`,{event:e})}selectEventById(e){let t=this.state.events.find(t=>t.id===e);t&&this.selectEvent(t)}deselectEvent(){this.setState({selectedEvent:null}),this.eventBus.emit(`event:deselected`,{})}selectDate(e){this.setState({selectedDate:e}),this.eventBus.emit(`date:selected`,{date:e})}deselectDate(){this.setState({selectedDate:null}),this.eventBus.emit(`date:deselected`,{})}isToday(e){let t=new Date;return e.toDateString()===t.toDateString()}isSelectedDate(e){return this.state.selectedDate&&e.toDateString()===this.state.selectedDate.toDateString()}isWeekend(e){let t=e.getDay();return t===0||t===6}setLoading(e){this.setState({loading:e})}setError(e){this.setState({error:e}),e&&this.eventBus.emit(`error`,{error:e})}clearError(){this.setState({error:null})}updateConfig(e){this.setState({config:{...this.state.config,...e}}),e.weekStartsOn!==void 0&&this.calendar.setWeekStartsOn(e.weekStartsOn),e.locale!==void 0&&this.calendar.setLocale(e.locale),e.timeZone!==void 0&&this.calendar.setTimezone(e.timeZone)}destroy(){this.subscribers.clear(),this._subscriberIds&&=(this._subscriberIds.clear(),null),this.eventBus&&=(this.eventBus.clear(),null),this.state=null,this.calendar=null}},o=class extends t.DateUtils{static formatDate(e,t=`default`,n=`en-US`){if(!e)return``;let r={default:{year:`numeric`,month:`long`,day:`numeric`},short:{year:`numeric`,month:`short`,day:`numeric`},long:{weekday:`long`,year:`numeric`,month:`long`,day:`numeric`},month:{year:`numeric`,month:`long`},monthShort:{year:`numeric`,month:`short`},day:{weekday:`long`,day:`numeric`},dayShort:{weekday:`short`,day:`numeric`},time:{hour:`numeric`,minute:`2-digit`},timeShort:{hour:`numeric`},datetime:{year:`numeric`,month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`}},i=r[t]||r.default;return new Intl.DateTimeFormat(n,i).format(e)}static formatTime(e,t=!0,n=!1,r=`en-US`){if(!e)return``;let i={hour:`numeric`,minute:t?`2-digit`:void 0,hour12:!n};return new Intl.DateTimeFormat(r,i).format(e)}static formatDateRange(e,t,n=`en-US`){if(!e)return``;if(!t||this.isSameDay(e,t))return this.formatDate(e,`default`,n);let r=this.isSameYear(e,t)?`short`:`default`;return`${this.formatDate(e,r,n)} - ${this.formatDate(t,`default`,n)}`}static formatTimeRange(e,t,n=`en-US`){if(!e)return``;let r=this.formatTime(e,!0,!1,n);return t?`${r} - ${this.formatTime(t,!0,!1,n)}`:r}static getRelativeTime(e,t=new Date,n=`en-US`){let r=new Intl.RelativeTimeFormat(n,{numeric:`auto`}),i=e-t,a=Math.floor(i/1e3),o=Math.floor(a/60),s=Math.floor(o/60),c=Math.floor(s/24),l=Math.floor(c/7),u=Math.floor(c/30),d=Math.floor(c/365);return Math.abs(a)<60?r.format(a,`second`):Math.abs(o)<60?r.format(o,`minute`):Math.abs(s)<24?r.format(s,`hour`):Math.abs(c)<7?r.format(c,`day`):Math.abs(l)<4?r.format(l,`week`):Math.abs(u)<12?r.format(u,`month`):r.format(d,`year`)}static isToday(e){let t=new Date;return this.isSameDay(e,t)}static isPast(e){return e<new Date}static isFuture(e){return e>new Date}static getWeekNumber(e){let t=new Date(e.getFullYear(),0,1),n=(e-t)/864e5;return Math.ceil((n+t.getDay()+1)/7)}static getDayAbbreviation(e,t=`en-US`){let n=new Date(2024,0,7+e);return new Intl.DateTimeFormat(t,{weekday:`short`}).format(n)}static getDayName(e,t=`en-US`){let n=new Date(2024,0,7+e);return new Intl.DateTimeFormat(t,{weekday:`long`}).format(n)}static getMonthName(e,t=`long`,n=`en-US`){let r=new Date(2024,e,1);return new Intl.DateTimeFormat(n,{month:t}).format(r)}static parseTimeString(e,t=new Date){let n=new Date(t),[r,i]=e.split(/\s+/),[a,o]=r.split(`:`).map(Number),s=a;return i&&(i.toLowerCase()===`pm`&&a<12?s=a+12:i.toLowerCase()===`am`&&a===12&&(s=0)),n.setHours(s,o||0,0,0),n}},s=class{static createElement(e,t={},n=[]){let r=document.createElement(e);return Object.entries(t).forEach(([e,t])=>{if(e===`className`)r.className=t;else if(e===`style`&&typeof t==`object`)Object.assign(r.style,t);else if(e.startsWith(`data-`))r.setAttribute(e,t);else if(e.startsWith(`on`)&&typeof t==`function`){let n=e.slice(2).toLowerCase();r.addEventListener(n,t)}else r[e]=t}),n.forEach(e=>{typeof e==`string`?r.appendChild(document.createTextNode(e)):e instanceof Node&&r.appendChild(e)}),r}static addEventListeners(e,t){return Object.entries(t).forEach(([t,n])=>{e.addEventListener(t,n)}),()=>{Object.entries(t).forEach(([t,n])=>{e.removeEventListener(t,n)})}}static delegate(e,t,n,r){let i=n=>{let i=n.target.closest(t);i&&e.contains(i)&&r.call(i,n)};return e.addEventListener(n,i),()=>e.removeEventListener(n,i)}static getPosition(e){let t=e.getBoundingClientRect();return{top:t.top+window.scrollY,left:t.left+window.scrollX,bottom:t.bottom+window.scrollY,right:t.right+window.scrollX,width:t.width,height:t.height}}static isInViewport(e,t=0){let n=e.getBoundingClientRect();return n.top>=-t&&n.left>=-t&&n.bottom<=(window.innerHeight||document.documentElement.clientHeight)+t&&n.right<=(window.innerWidth||document.documentElement.clientWidth)+t}static scrollToElement(e,t={}){let{behavior:n=`smooth`,block:r=`start`,inline:i=`nearest`}=t;e.scrollIntoView({behavior:n,block:r,inline:i})}static getStyle(e,t){return window.getComputedStyle(e).getPropertyValue(t)}static setStyles(e,t){Object.assign(e.style,t)}static async animateClass(e,t,n=300){e.classList.add(t),await this.wait(n),e.classList.remove(t)}static waitForAnimation(e,t=`animationend`,n=3e3){return new Promise(r=>{let i=null,a=()=>{i!==null&&clearTimeout(i),e.removeEventListener(t,a),r()};e.addEventListener(t,a),n>0&&(i=setTimeout(a,n))})}static wait(e){return new Promise(t=>setTimeout(t,e))}static parseHTML(e,{sanitize:t=!0}={}){let n=document.createElement(`template`);return n.innerHTML=e.trim(),t&&this._sanitizeNode(n.content),n.content.firstChild}static _sanitizeNode(e){e.querySelectorAll(`script, iframe, object, embed, link, meta, base`).forEach(e=>e.remove());let t=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT),n=t.nextNode();for(;n;){for(let e of Array.from(n.attributes)){let t=e.name.toLowerCase(),r=e.value.replace(/[\u0000-\u0020]/g,``).toLowerCase();(t.startsWith(`on`)||r.startsWith(`javascript:`)||r.startsWith(`data:text/html`))&&n.removeAttribute(e.name)}n=t.nextNode()}}static escapeHTML(e){let t=document.createElement(`div`);return t.textContent=e,t.innerHTML}static debounce(e,t=250){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>e.apply(this,r),t)}}static throttle(e,t=250){let n;return function(...r){n||(e.apply(this,r),n=!0,setTimeout(()=>n=!1,t))}}static closest(e,t){return e.closest(t)}static parents(e,t){let n=[],r=e.parentElement;for(;r;)r.matches(t)&&n.push(r),r=r.parentElement;return n}static getOuterDimensions(e){let t=window.getComputedStyle(e),n={top:parseInt(t.marginTop),right:parseInt(t.marginRight),bottom:parseInt(t.marginBottom),left:parseInt(t.marginLeft)};return{width:e.offsetWidth+n.left+n.right,height:e.offsetHeight+n.top+n.bottom,margin:n}}static cloneWithEvents(e,t=!0){return e.cloneNode(t)}static trapFocus(e){let t=e.querySelectorAll(`button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])`);if(t.length===0)return e.setAttribute(`tabindex`,`-1`),e.focus(),()=>e.removeAttribute(`tabindex`);let n=t[0],r=t[t.length-1],i=t=>{if(t.key!==`Tab`)return;let i=e.getRootNode().activeElement??document.activeElement;t.shiftKey?i===n&&(r?.focus(),t.preventDefault()):i===r&&(n?.focus(),t.preventDefault())};return e.addEventListener(`keydown`,i),n?.focus(),()=>e.removeEventListener(`keydown`,i)}},c=class{static colors={primary:`#3B82F6`,secondary:`#64748B`,accent:`#F59E0B`,danger:`#EF4444`,warning:`#F97316`,info:`#06B6D4`,success:`#22C55E`,light:`#F8FAFC`,dark:`#0F172A`,white:`#FFFFFF`,gray:{50:`#F8FAFC`,100:`#F1F5F9`,200:`#E2E8F0`,300:`#CBD5E1`,400:`#94A3B8`,500:`#64748B`,600:`#475569`,700:`#334155`,800:`#1E293B`,900:`#0F172A`}};static cssVariables={"--fc-primary-color":`#2563EB`,"--fc-primary-hover":`#1D4ED8`,"--fc-primary-light":`#EFF6FF`,"--fc-text-color":`#111827`,"--fc-text-secondary":`#6B7280`,"--fc-text-light":`#9CA3AF`,"--fc-border-color":`#E5E7EB`,"--fc-border-color-hover":`#D1D5DB`,"--fc-background":`#FFFFFF`,"--fc-background-alt":`#FAFAFA`,"--fc-background-hover":`#F3F4F6`,"--fc-background-active":`#E5E7EB`,"--fc-accent-color":`#F59E0B`,"--fc-danger-color":`#EF4444`,"--fc-success-color":`#10B981`,"--fc-font-family":`Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`,"--fc-font-size-xs":`11px`,"--fc-font-size-sm":`12px`,"--fc-font-size-base":`13px`,"--fc-font-size-lg":`15px`,"--fc-font-size-xl":`18px`,"--fc-font-size-2xl":`24px`,"--fc-line-height":`1.4`,"--fc-font-weight-normal":`400`,"--fc-font-weight-medium":`500`,"--fc-font-weight-semibold":`600`,"--fc-font-weight-bold":`700`,"--fc-spacing-xs":`2px`,"--fc-spacing-sm":`6px`,"--fc-spacing-md":`10px`,"--fc-spacing-lg":`14px`,"--fc-spacing-xl":`20px`,"--fc-spacing-2xl":`28px`,"--fc-border-width":`1px`,"--fc-border-radius-sm":`3px`,"--fc-border-radius":`5px`,"--fc-border-radius-lg":`8px`,"--fc-border-radius-full":`9999px`,"--fc-shadow-sm":`0 1px 1px rgba(0,0,0,0.05)`,"--fc-shadow":`0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06)`,"--fc-shadow-md":`0 4px 6px -1px rgba(0, 0, 0, 0.1)`,"--fc-shadow-lg":`0 10px 15px -3px rgba(0, 0, 0, 0.1)`,"--fc-transition-fast":`100ms ease-out`,"--fc-transition":`150ms ease-out`,"--fc-transition-slow":`250ms ease-out`,"--fc-z-dropdown":`1000`,"--fc-z-modal":`2000`,"--fc-z-tooltip":`3000`};static getCSSVariable(e,t=document.documentElement){return getComputedStyle(t).getPropertyValue(e).trim()}static setCSSVariables(e,t=document.documentElement){Object.entries(e).forEach(([e,n])=>{t.style.setProperty(e,n)})}static getBaseStyles(){return`
|
|
12
12
|
:host {
|
|
13
13
|
/* Apply CSS variables */
|
|
14
|
-
${Object.entries(this.cssVariables).map(([t
|
|
14
|
+
${Object.entries(this.cssVariables).map(([e,t])=>`${e}: ${t};`).join(`
|
|
15
15
|
`)}
|
|
16
16
|
|
|
17
17
|
/* Base styles */
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
padding: 0;
|
|
146
146
|
border-radius: var(--fc-border-radius-full);
|
|
147
147
|
}
|
|
148
|
-
`}static darken(t
|
|
148
|
+
`}static darken(e,t){let n=parseInt(e.replace(`#`,``),16),r=Math.round(2.55*t),i=(n>>16)-r,a=(n>>8&255)-r,o=(n&255)-r;return`#`+(16777216+(i<255?i<1?0:i:255)*65536+(a<255?a<1?0:a:255)*256+(o<255?o<1?0:o:255)).toString(16).slice(1)}static lighten(e,t){let n=parseInt(e.replace(`#`,``),16),r=Math.round(2.55*t),i=(n>>16)+r,a=(n>>8&255)+r,o=(n&255)+r;return`#`+(16777216+(i<255?i<1?0:i:255)*65536+(a<255?a<1?0:a:255)*256+(o<255?o<1?0:o:255)).toString(16).slice(1)}static getContrastColor(e){let t=e.replace(`#`,``),n=parseInt(t.substring(0,2),16),r=parseInt(t.substring(2,4),16),i=parseInt(t.substring(4,6),16);return(n*299+r*587+i*114)/1e3>=128?`#000000`:`#FFFFFF`}static sanitizeColor(e,t=`var(--fc-primary-color)`){if(!e||typeof e!=`string`)return t;let n=e.trim();return/[;{}()<>\"\'\\]/.test(n)?t:/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(n)||/^var\(--[a-zA-Z0-9-]+\)$/.test(n)||/^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(,\s*(0|1|0?\.\d+))?\s*\)$/.test(n)||[`transparent`,`currentColor`,`inherit`,`black`,`white`,`red`,`green`,`blue`,`yellow`,`orange`,`purple`,`pink`,`brown`,`gray`,`grey`,`cyan`,`magenta`,`lime`,`navy`,`teal`,`aqua`,`maroon`,`olive`,`silver`,`fuchsia`].includes(n.toLowerCase())?n:t}static hexToRgba(e,t=1){let n=e.replace(`#`,``);return`rgba(${parseInt(n.substring(0,2),16)}, ${parseInt(n.substring(2,4),16)}, ${parseInt(n.substring(4,6),16)}, ${t})`}static getGridStyles(){return`
|
|
149
149
|
.fc-grid {
|
|
150
150
|
display: grid;
|
|
151
151
|
gap: 1px;
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
text-transform: uppercase;
|
|
177
177
|
letter-spacing: 0.5px;
|
|
178
178
|
}
|
|
179
|
-
`}static mediaQuery(t
|
|
179
|
+
`}static breakpoints={xs:`320px`,sm:`576px`,md:`768px`,lg:`992px`,xl:`1200px`,"2xl":`1400px`};static mediaQuery(e,t){let n=this.breakpoints[e];return n?`@media (min-width: ${n}) { ${t} }`:``}static getAnimations(){return`
|
|
180
180
|
@keyframes fc-fade-in {
|
|
181
181
|
from { opacity: 0; }
|
|
182
182
|
to { opacity: 1; }
|
|
@@ -231,167 +231,172 @@
|
|
|
231
231
|
.fc-scale-in {
|
|
232
232
|
animation: fc-scale-in var(--fc-transition);
|
|
233
233
|
}
|
|
234
|
-
`}}
|
|
235
|
-
<div class="fc-event fc-timed-event" data-event-id="${this.escapeHTML(
|
|
236
|
-
style="position: absolute; top: ${
|
|
237
|
-
left: ${
|
|
238
|
-
background-color: ${c}; border-radius: ${
|
|
239
|
-
padding: ${
|
|
234
|
+
`}},l=class{constructor(e,t){this.container=e,this.stateManager=t,this._listeners=[],this._scrolled=!1,this._nowIndicatorTimer=null}render(){throw Error(`render() must be implemented by subclass`)}cleanup(){this._listeners.forEach(({element:e,event:t,handler:n})=>{e.removeEventListener(t,n)}),this._listeners=[],this._nowIndicatorTimer&&=(clearInterval(this._nowIndicatorTimer),null)}addListener(e,t,n){let r=n.bind(this);e.addEventListener(t,r),this._listeners.push({element:e,event:t,handler:r})}escapeHTML(e){return e==null?``:s.escapeHTML(String(e))}isToday(e){let t=new Date;return e.getDate()===t.getDate()&&e.getMonth()===t.getMonth()&&e.getFullYear()===t.getFullYear()}isSameDay(e,t){return e.getDate()===t.getDate()&&e.getMonth()===t.getMonth()&&e.getFullYear()===t.getFullYear()}formatHour(e){let t=e>=12?`PM`:`AM`;return`${e%12||12} ${t}`}formatTime(e){let t=e.getHours(),n=e.getMinutes(),r=t>=12?`PM`:`AM`,i=t%12||12;return n===0?`${i} ${r}`:`${i}:${n.toString().padStart(2,`0`)} ${r}`}getContrastingTextColor(e){return!e||typeof e!=`string`||e.charAt(0)!==`#`?`white`:c.getContrastColor(e)}renderNowIndicator(){let e=new Date;return`<div class="fc-now-indicator" style="position: absolute; left: 0; right: 0; top: ${e.getHours()*60+e.getMinutes()}px; height: 2px; background: var(--fc-danger-color); z-index: 15; pointer-events: none;"></div>`}startNowIndicatorTimer(){this._nowIndicatorTimer&&clearInterval(this._nowIndicatorTimer),this._nowIndicatorTimer=setInterval(()=>{let e=this.container.querySelector(`.fc-now-indicator`);if(e){let t=new Date;e.style.top=`${t.getHours()*60+t.getMinutes()}px`}},6e4)}computeOverlapLayout(e){if(!e||e.length===0)return new Map;let t=e.map(e=>{let t=new Date(e.start),n=new Date(e.end),r=t.getHours()*60+t.getMinutes(),i=Math.max(r+1,n.getHours()*60+n.getMinutes());return{id:e.id,startMin:r,endMin:i}});t.sort((e,t)=>e.startMin-t.startMin||t.endMin-t.startMin-(e.endMin-e.startMin));let n=[],r=new Map;for(let e of t){let t=!1;for(let i=0;i<n.length;i++)if(n[i]<=e.startMin){n[i]=e.endMin,r.set(e.id,{column:i,totalColumns:0}),t=!0;break}t||(r.set(e.id,{column:n.length,totalColumns:0}),n.push(e.endMin))}let i=[],a=[],o=0;for(let e of t)a.length===0||e.startMin<o?(a.push(e),o=Math.max(o,e.endMin)):(i.push(a),a=[e],o=e.endMin);a.length>0&&i.push(a);for(let e of i){let t=Math.max(...e.map(e=>r.get(e.id).column))+1;for(let n of e)r.get(n.id).totalColumns=t}return r}renderTimedEvent(e,t={}){let{compact:n=!0,overlapLayout:r=null}=t,i=new Date(e.start),a=new Date(e.end),o=i.getHours()*60+i.getMinutes(),s=Math.max((a-i)/(1e3*60),n?20:30),c=this.getEventColor(e),l=this.getContrastingTextColor(c),u=n?`4px 8px`:`8px 12px`,d=n?`11px`:`13px`,f=n?2:12,p=n?2:24,m=n?`4px`:`6px`,h,g;if(r&&r.has(e.id)){let{column:t,totalColumns:n}=r.get(e.id),i=`(100% - ${f+p}px)`;h=`calc(${f}px + ${t} * ${i} / ${n})`,g=`calc(${i} / ${n})`}else h=`${f}px`,g=`calc(100% - ${f+p}px)`;return`
|
|
235
|
+
<div class="fc-event fc-timed-event" data-event-id="${this.escapeHTML(e.id)}"
|
|
236
|
+
style="position: absolute; top: ${o}px; height: ${s}px;
|
|
237
|
+
left: ${h}; width: ${g};
|
|
238
|
+
background-color: ${c}; border-radius: ${m};
|
|
239
|
+
padding: ${u}; font-size: ${d};
|
|
240
240
|
font-weight: 500; color: ${l}; overflow: hidden;
|
|
241
241
|
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
|
|
242
242
|
cursor: pointer; z-index: 5;">
|
|
243
243
|
<div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
|
|
244
|
-
${this.escapeHTML(
|
|
244
|
+
${this.escapeHTML(e.title)}
|
|
245
245
|
</div>
|
|
246
|
-
<div style="font-size: ${
|
|
247
|
-
${this.formatTime(
|
|
246
|
+
<div style="font-size: ${n?`10px`:`11px`}; opacity: 0.9;">
|
|
247
|
+
${this.formatTime(i)}${n?``:` - `+this.formatTime(a)}
|
|
248
248
|
</div>
|
|
249
249
|
</div>
|
|
250
|
-
`}getEventColor(
|
|
251
|
-
<div class="fc-month-view" style="display: flex; flex-direction: column; height: 100%; min-height: 400px; background: var(--fc-background); border: 1px solid var(--fc-border-color);">
|
|
252
|
-
<div class="fc-month-header" style="display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--fc-border-color); background: var(--fc-background-alt);">
|
|
253
|
-
${
|
|
250
|
+
`}getEventColor(e){return c.sanitizeColor(e?.backgroundColor,`#2563eb`)}attachCommonEventHandlers(){this.addListener(this.container,`click`,e=>{let t=e.target.closest(`.fc-event`);!t||!this.container.contains(t)||(e.stopPropagation(),this._selectEventFromElement(t))}),this.addListener(this.container,`keydown`,e=>{if(e.key!==`Enter`&&e.key!==` `)return;let t=e.target.closest(`.fc-event`);!t||!this.container.contains(t)||(e.preventDefault(),e.stopPropagation(),this._selectEventFromElement(t))}),this._enhanceEventAccessibility()}_selectEventFromElement(e){let t=e.dataset.eventId,n=this.stateManager.getEvents().find(e=>e.id===t);n&&this.stateManager.selectEvent(n)}_enhanceEventAccessibility(){for(let e of this.container.querySelectorAll(`.fc-event`))if(e.setAttribute(`role`,`button`),e.setAttribute(`tabindex`,`0`),!e.hasAttribute(`aria-label`)){let t=(e.getAttribute(`title`)||e.textContent||``).trim();t&&e.setAttribute(`aria-label`,`Event: ${t}`)}}},u=class extends l{constructor(e,t){super(e,t),this.maxEventsToShow=3}render(){if(!this.container||!this.stateManager)return;let e=this.stateManager.getViewData();if(!e||!e.weeks){this.container.innerHTML=`<div style="padding: 20px; text-align: center; color: var(--fc-text-secondary);">No data available for month view.</div>`;return}this.cleanup();let t=this.stateManager.getState().config,n=this._renderMonthView(e,t);this.container.innerHTML=n,this._attachEventHandlers();let r=this._applyRovingTabindex(this._pendingFocusMs??null);this._pendingFocusMs!=null&&(this._pendingFocusMs=null,r&&r.focus())}_renderMonthView(e,t){let n=t.weekStartsOn||0,r=this._getDayNames(n),i=t.locale||`en-US`;this._dayLabelFormatter=new Intl.DateTimeFormat(i,{weekday:`long`,year:`numeric`,month:`long`,day:`numeric`});let a=this.stateManager.getState().currentDate,o=new Intl.DateTimeFormat(i,{month:`long`,year:`numeric`}).format(a||new Date),s=`
|
|
251
|
+
<div class="fc-month-view" role="grid" aria-label="${this.escapeHTML(o)}" style="display: flex; flex-direction: column; height: 100%; min-height: 400px; background: var(--fc-background); border: 1px solid var(--fc-border-color);">
|
|
252
|
+
<div class="fc-month-header" role="row" style="display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--fc-border-color); background: var(--fc-background-alt);">
|
|
253
|
+
${r.map(e=>`<div class="fc-month-header-cell" role="columnheader" style="padding: 12px 8px; text-align: center; font-size: 11px; font-weight: 600; color: var(--fc-text-light); text-transform: uppercase;">${this.escapeHTML(e)}</div>`).join(``)}
|
|
254
254
|
</div>
|
|
255
255
|
<div class="fc-month-body" style="display: flex; flex-direction: column; flex: 1;">
|
|
256
|
-
`;return
|
|
257
|
-
<div class="fc-month-day" data-date="${this.escapeHTML(
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
256
|
+
`;return e.weeks.forEach(e=>{s+=this._renderWeek(e)}),s+=`</div></div>`,s}_getDayNames(e){let t=this.stateManager.getState().config.locale||`en-US`,n=[];for(let r=0;r<7;r++){let i=(e+r)%7;n.push(o.getDayAbbreviation(i,t))}return n}_renderWeek(e){let t=`<div class="fc-month-week" role="row" style="display: grid; grid-template-columns: repeat(7, 1fr); flex: 1; min-height: 80px;">`;return e.days.forEach(e=>{t+=this._renderDay(e)}),t+=`</div>`,t}_renderDay(e){let t=!e.isCurrentMonth,n=e.isToday,r=t?`var(--fc-background-hover)`:`var(--fc-background)`,i=t?`var(--fc-text-light)`:`var(--fc-text-color)`,a=n?`background: var(--fc-primary-color); color: white; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;`:``,o=e.events||[],s=o.slice(0,this.maxEventsToShow),c=o.length-this.maxEventsToShow,l=this._dayLabelFormatter?this._dayLabelFormatter.format(new Date(e.date)):e.date;return o.length>0&&(l+=`, ${o.length} ${o.length===1?`event`:`events`}`),`
|
|
257
|
+
<div class="fc-month-day" data-date="${this.escapeHTML(e.date)}"
|
|
258
|
+
role="gridcell" tabindex="-1"
|
|
259
|
+
aria-selected="${e.isSelected?`true`:`false`}"
|
|
260
|
+
${n?`aria-current="date"`:``}
|
|
261
|
+
${t?`data-other-month="true"`:``}
|
|
262
|
+
aria-label="${this.escapeHTML(l)}"
|
|
263
|
+
style="background: ${r}; border-right: 1px solid var(--fc-border-color); border-bottom: 1px solid var(--fc-border-color); padding: 4px; min-height: 80px; cursor: pointer; display: flex; flex-direction: column;">
|
|
264
|
+
<div class="fc-day-number" style="font-size: 13px; font-weight: 500; color: ${i}; padding: 2px 4px; margin-bottom: 4px; ${a}">
|
|
265
|
+
${this.escapeHTML(String(e.dayOfMonth))}
|
|
261
266
|
</div>
|
|
262
267
|
<div class="fc-day-events" style="display: flex; flex-direction: column; gap: 2px; flex: 1; overflow: hidden;">
|
|
263
|
-
${
|
|
264
|
-
${c>0?`<div class="fc-more-events" style="font-size: 10px; color: var(--fc-text-light); padding: 2px 4px; font-weight: 500;">+${c} more</div
|
|
268
|
+
${s.map(e=>this._renderEvent(e)).join(``)}
|
|
269
|
+
${c>0?`<div class="fc-more-events" style="font-size: 10px; color: var(--fc-text-light); padding: 2px 4px; font-weight: 500;">+${c} more</div>`:``}
|
|
265
270
|
</div>
|
|
266
271
|
</div>
|
|
267
|
-
`}_renderEvent(
|
|
268
|
-
<div class="fc-event" data-event-id="${this.escapeHTML(
|
|
269
|
-
style="background-color: ${
|
|
270
|
-
${this.escapeHTML(
|
|
272
|
+
`}_renderEvent(e){let t=this.getEventColor(e),n=this.getContrastingTextColor(t);return`
|
|
273
|
+
<div class="fc-event" data-event-id="${this.escapeHTML(e.id)}"
|
|
274
|
+
style="background-color: ${t}; font-size: 11px; padding: 2px 6px; border-radius: 3px; color: ${n}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;">
|
|
275
|
+
${this.escapeHTML(e.title)}
|
|
271
276
|
</div>
|
|
272
|
-
`}_attachEventHandlers(){this.addListener(this.container
|
|
277
|
+
`}_attachEventHandlers(){this.addListener(this.container,`click`,e=>{let t=e.target.closest(`.fc-month-day`);if(!t||!this.container.contains(t)||e.target.closest(`.fc-event`))return;let n=new Date(t.dataset.date);this.stateManager.selectDate(n)}),this.addListener(this.container,`keydown`,e=>{if(e.target.closest(`.fc-event`))return;let t=e.target.closest(`.fc-month-day`);if(!t||!this.container.contains(t))return;let n=Array.from(this.container.querySelectorAll(`.fc-month-day`)),r=n.indexOf(t),i;switch(e.key){case`ArrowRight`:i=r+1;break;case`ArrowLeft`:i=r-1;break;case`ArrowDown`:i=r+7;break;case`ArrowUp`:i=r-7;break;case`Home`:i=r-r%7;break;case`End`:i=r-r%7+6;break;case`PageUp`:case`PageDown`:{e.preventDefault();let n=new Date(t.dataset.date);n.setMonth(n.getMonth()+(e.key===`PageDown`?1:-1)),this._pendingFocusMs=n.getTime(),e.key===`PageDown`?this.stateManager.next():this.stateManager.previous();return}case`Enter`:case` `:{e.preventDefault();let n=new Date(t.dataset.date);this._pendingFocusMs=n.getTime(),this.stateManager.selectDate(n);return}default:return}if(e.preventDefault(),i>=0&&i<n.length)this._applyRovingTabindex(new Date(n[i].dataset.date).getTime()),n[i].focus();else{let e=new Date(t.dataset.date);e.setDate(e.getDate()+(i-r)),this._pendingFocusMs=e.getTime(),i<0?this.stateManager.previous():this.stateManager.next()}}),this.attachCommonEventHandlers()}_applyRovingTabindex(e=null){let t=Array.from(this.container.querySelectorAll(`.fc-month-day`));if(t.length===0)return null;let n=null;e!=null&&(n=t.find(t=>new Date(t.dataset.date).getTime()===e)),n||=t.find(e=>e.getAttribute(`aria-selected`)===`true`),n||=t.find(e=>e.hasAttribute(`aria-current`)),n||=t.find(e=>!e.dataset.otherMonth)||t[0];for(let e of t)e.setAttribute(`tabindex`,e===n?`0`:`-1`);return n}},d=class extends l{constructor(e,t){super(e,t),this.hourHeight=60,this.totalHeight=24*this.hourHeight}render(){if(!this.container||!this.stateManager)return;let e=this.stateManager.getViewData();if(!e||!e.days||e.days.length===0){this.container.innerHTML=`<div style="padding: 20px; text-align: center; color: var(--fc-text-secondary);">No data available for week view.</div>`;return}this.cleanup(),this._scrolled=!1;let t=this.stateManager.getState().config,n=this._renderWeekView(e,t);this.container.innerHTML=n,this._attachEventHandlers(),this._scrollToCurrentTime(),this.startNowIndicatorTimer()}_renderWeekView(e,t){let n=e.days,r=this.stateManager.getState().config.locale||`en-US`,i=Array.from({length:24},(e,t)=>t),a=n.map(e=>{let t=new Date(e.date),n=e.events||[];return{...e,date:t,dayName:o.getDayAbbreviation(t.getDay(),r),dayOfMonth:t.getDate(),isToday:this.isToday(t),timedEvents:n.filter(e=>!e.allDay),allDayEvents:n.filter(e=>e.allDay)}});return`
|
|
273
278
|
<div class="fc-week-view" style="display: flex; flex-direction: column; height: 100%; background: var(--fc-background); overflow: hidden;">
|
|
274
|
-
${this._renderHeader(
|
|
275
|
-
${this._renderAllDayRow(
|
|
276
|
-
${this._renderTimeGrid(
|
|
279
|
+
${this._renderHeader(a)}
|
|
280
|
+
${this._renderAllDayRow(a)}
|
|
281
|
+
${this._renderTimeGrid(a,i)}
|
|
277
282
|
</div>
|
|
278
|
-
`}_renderHeader(
|
|
283
|
+
`}_renderHeader(e){return`
|
|
279
284
|
<div class="fc-week-header" style="display: grid; grid-template-columns: 60px repeat(7, 1fr); border-bottom: 1px solid var(--fc-border-color); background: var(--fc-background-alt); flex-shrink: 0;">
|
|
280
285
|
<div style="border-right: 1px solid var(--fc-border-color);"></div>
|
|
281
|
-
${
|
|
286
|
+
${e.map(e=>`
|
|
282
287
|
<div style="padding: 12px 8px; text-align: center; border-right: 1px solid var(--fc-border-color);">
|
|
283
288
|
<div style="font-size: 10px; font-weight: 700; color: var(--fc-text-light); text-transform: uppercase; letter-spacing: 0.1em;">
|
|
284
289
|
${this.escapeHTML(e.dayName)}
|
|
285
290
|
</div>
|
|
286
|
-
<div style="font-size: 16px; font-weight: 500; margin-top: 4px; ${e.isToday
|
|
291
|
+
<div style="font-size: 16px; font-weight: 500; margin-top: 4px; ${e.isToday?`background: var(--fc-danger-color); color: white; border-radius: 50%; width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;`:`color: var(--fc-text-color);`}">
|
|
287
292
|
${this.escapeHTML(String(e.dayOfMonth))}
|
|
288
293
|
</div>
|
|
289
294
|
</div>
|
|
290
|
-
`).join(
|
|
295
|
+
`).join(``)}
|
|
291
296
|
</div>
|
|
292
|
-
`}_renderAllDayRow(
|
|
297
|
+
`}_renderAllDayRow(e){return`
|
|
293
298
|
<div class="fc-all-day-row" style="display: grid; grid-template-columns: 60px repeat(7, 1fr); border-bottom: 1px solid var(--fc-border-color); background: var(--fc-background-alt); min-height: 32px; flex-shrink: 0;">
|
|
294
299
|
<div style="font-size: 9px; color: var(--fc-text-light); display: flex; align-items: center; justify-content: center; border-right: 1px solid var(--fc-border-color); text-transform: uppercase; font-weight: 700;">
|
|
295
300
|
All day
|
|
296
301
|
</div>
|
|
297
|
-
${
|
|
302
|
+
${e.map(e=>`
|
|
298
303
|
<div class="fc-all-day-cell" data-date="${e.date.toISOString()}" style="border-right: 1px solid var(--fc-border-color); padding: 4px; display: flex; flex-direction: column; gap: 2px;">
|
|
299
|
-
${e.allDayEvents.map(
|
|
300
|
-
<div class="fc-event fc-all-day-event" data-event-id="${this.escapeHTML(
|
|
301
|
-
style="background-color: ${this.getEventColor(
|
|
302
|
-
${this.escapeHTML(
|
|
304
|
+
${e.allDayEvents.map(e=>`
|
|
305
|
+
<div class="fc-event fc-all-day-event" data-event-id="${this.escapeHTML(e.id)}"
|
|
306
|
+
style="background-color: ${this.getEventColor(e)}; font-size: 10px; padding: 2px 4px; border-radius: 2px; color: white; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
|
|
307
|
+
${this.escapeHTML(e.title)}
|
|
303
308
|
</div>
|
|
304
|
-
`).join(
|
|
309
|
+
`).join(``)}
|
|
305
310
|
</div>
|
|
306
|
-
`).join(
|
|
311
|
+
`).join(``)}
|
|
307
312
|
</div>
|
|
308
|
-
`}_renderTimeGrid(t
|
|
313
|
+
`}_renderTimeGrid(e,t){return`
|
|
309
314
|
<div id="week-scroll-container" class="fc-time-grid-container" style="flex: 1; overflow-y: auto; overflow-x: hidden; position: relative;">
|
|
310
315
|
<div class="fc-time-grid" style="display: grid; grid-template-columns: 60px repeat(7, 1fr); position: relative; height: ${this.totalHeight}px;">
|
|
311
|
-
${this._renderTimeGutter(
|
|
312
|
-
${
|
|
316
|
+
${this._renderTimeGutter(t)}
|
|
317
|
+
${e.map(e=>this._renderDayColumn(e,t)).join(``)}
|
|
313
318
|
</div>
|
|
314
319
|
</div>
|
|
315
|
-
`}_renderTimeGutter(
|
|
320
|
+
`}_renderTimeGutter(e){return`
|
|
316
321
|
<div class="fc-time-gutter" style="border-right: 1px solid var(--fc-border-color); background: var(--fc-background-alt);">
|
|
317
|
-
${
|
|
322
|
+
${e.map(e=>`
|
|
318
323
|
<div style="height: ${this.hourHeight}px; font-size: 10px; color: var(--fc-text-light); text-align: right; padding-right: 8px; font-weight: 500;">
|
|
319
|
-
${e===0
|
|
324
|
+
${e===0?``:this.formatHour(e)}
|
|
320
325
|
</div>
|
|
321
|
-
`).join(
|
|
326
|
+
`).join(``)}
|
|
322
327
|
</div>
|
|
323
|
-
`}_renderDayColumn(t
|
|
324
|
-
<div class="fc-week-day-column" data-date="${
|
|
328
|
+
`}_renderDayColumn(e,t){return`
|
|
329
|
+
<div class="fc-week-day-column" data-date="${e.date.toISOString()}" style="border-right: 1px solid var(--fc-border-color); position: relative; cursor: pointer;">
|
|
325
330
|
<!-- Hour grid lines -->
|
|
326
|
-
${
|
|
331
|
+
${t.map(()=>`<div style="height: ${this.hourHeight}px; border-bottom: 1px solid var(--fc-background-hover);"></div>`).join(``)}
|
|
327
332
|
|
|
328
333
|
<!-- Now indicator for today -->
|
|
329
|
-
${
|
|
334
|
+
${e.isToday?this.renderNowIndicator():``}
|
|
330
335
|
|
|
331
336
|
<!-- Timed events -->
|
|
332
|
-
${(()=>{
|
|
337
|
+
${(()=>{let t=this.computeOverlapLayout(e.timedEvents);return e.timedEvents.map(e=>this.renderTimedEvent(e,{compact:!0,overlapLayout:t})).join(``)})()}
|
|
333
338
|
</div>
|
|
334
|
-
`}_attachEventHandlers(){this.addListener(this.container
|
|
339
|
+
`}_attachEventHandlers(){this.addListener(this.container,`click`,e=>{let t=e.target.closest(`.fc-week-day-column`);if(!t||!this.container.contains(t)||e.target.closest(`.fc-event`))return;let n=new Date(t.dataset.date),r=this.container.querySelector(`#week-scroll-container`),i=t.offsetTop,a=e.clientY-t.getBoundingClientRect().top+(r?r.scrollTop:0)-i,o=Math.max(0,Math.min(a+i,this.totalHeight));n.setHours(Math.floor(o/this.hourHeight),Math.floor(o%this.hourHeight/(this.hourHeight/60)),0,0),this.stateManager.selectDate(n)}),this.attachCommonEventHandlers()}_scrollToCurrentTime(){if(this._scrolled)return;let e=this.container.querySelector(`#week-scroll-container`);e&&(e.scrollTop=8*this.hourHeight-50,this._scrolled=!0)}},f=class extends l{constructor(e,t){super(e,t),this.hourHeight=60,this.totalHeight=24*this.hourHeight}render(){if(!this.container||!this.stateManager)return;let e=this.stateManager.getViewData();if(!e){this.container.innerHTML=`<div style="padding: 20px; text-align: center; color: var(--fc-text-secondary);">No data available for day view.</div>`;return}this.cleanup(),this._scrolled=!1;let t=this.stateManager.getState().config,n=this._renderDayView(e,t);this.container.innerHTML=n,this._attachEventHandlers(),this._scrollToCurrentTime(),this.startNowIndicatorTimer()}_renderDayView(e,t){let n=this.stateManager?.getState()?.currentDate||new Date,r=this._extractDayData(e,n);if(!r)return`<div style="padding: 20px; text-align: center; color: var(--fc-text-secondary);">No data available for day view.</div>`;let{dayDate:i,dayName:a,isToday:o,allDayEvents:s,timedEvents:c}=r,l=Array.from({length:24},(e,t)=>t);return`
|
|
335
340
|
<div class="fc-day-view" style="display: flex; flex-direction: column; height: 100%; background: var(--fc-background); overflow: hidden;">
|
|
336
|
-
${this._renderHeader(
|
|
337
|
-
${this._renderAllDayRow(
|
|
338
|
-
${this._renderTimeGrid(c,
|
|
341
|
+
${this._renderHeader(i,a,o)}
|
|
342
|
+
${this._renderAllDayRow(s,i)}
|
|
343
|
+
${this._renderTimeGrid(c,o,i,l)}
|
|
339
344
|
</div>
|
|
340
|
-
`}_extractDayData(t
|
|
345
|
+
`}_extractDayData(e,t){let n,r,i,a,s,c=this.stateManager.getState().config.locale||`en-US`;if(e.type===`day`&&e.date)if(n=new Date(e.date),r=e.dayName||o.getDayName(n.getDay(),c),i=e.isToday===void 0?this.isToday(n):e.isToday,a=e.allDayEvents||[],e.hours&&Array.isArray(e.hours)){let t=new Map;e.hours.forEach(e=>{(e.events||[]).forEach(e=>{t.has(e.id)||t.set(e.id,e)})}),s=Array.from(t.values())}else s=[];else if(e.days&&e.days.length>0){let l=e.days.find(e=>this.isSameDay(new Date(e.date),t))||e.days[0];n=new Date(l.date),r=o.getDayName(n.getDay(),c),i=this.isToday(n);let u=l.events||[];a=u.filter(e=>e.allDay),s=u.filter(e=>!e.allDay)}else return null;return{dayDate:n,dayName:r,isToday:i,allDayEvents:a,timedEvents:s}}_renderHeader(e,t,n){return`
|
|
341
346
|
<div class="fc-day-header" style="display: grid; grid-template-columns: 60px 1fr; border-bottom: 1px solid var(--fc-border-color); background: var(--fc-background-alt); flex-shrink: 0;">
|
|
342
347
|
<div style="border-right: 1px solid var(--fc-border-color);"></div>
|
|
343
348
|
<div style="padding: 16px 24px;">
|
|
344
349
|
<div style="font-size: 12px; font-weight: 700; color: var(--fc-text-light); text-transform: uppercase; letter-spacing: 0.1em;">
|
|
345
|
-
${this.escapeHTML(
|
|
350
|
+
${this.escapeHTML(t)}
|
|
346
351
|
</div>
|
|
347
|
-
<div style="font-size: 24px; font-weight: 600; margin-top: 4px; ${
|
|
348
|
-
${this.escapeHTML(String(
|
|
352
|
+
<div style="font-size: 24px; font-weight: 600; margin-top: 4px; ${n?`color: var(--fc-danger-color);`:`color: var(--fc-text-color);`}">
|
|
353
|
+
${this.escapeHTML(String(e.getDate()))}
|
|
349
354
|
</div>
|
|
350
355
|
</div>
|
|
351
356
|
</div>
|
|
352
|
-
`}_renderAllDayRow(t
|
|
357
|
+
`}_renderAllDayRow(e,t){return`
|
|
353
358
|
<div class="fc-all-day-row" style="display: grid; grid-template-columns: 60px 1fr; border-bottom: 1px solid var(--fc-border-color); background: var(--fc-background-alt); min-height: 36px; flex-shrink: 0;">
|
|
354
359
|
<div style="font-size: 9px; color: var(--fc-text-light); display: flex; align-items: center; justify-content: center; border-right: 1px solid var(--fc-border-color); text-transform: uppercase; font-weight: 700;">
|
|
355
360
|
All day
|
|
356
361
|
</div>
|
|
357
|
-
<div class="fc-all-day-cell" data-date="${
|
|
358
|
-
${
|
|
359
|
-
<div class="fc-event fc-all-day-event" data-event-id="${this.escapeHTML(
|
|
360
|
-
style="background-color: ${this.getEventColor(
|
|
361
|
-
${this.escapeHTML(
|
|
362
|
+
<div class="fc-all-day-cell" data-date="${t.toISOString()}" style="padding: 6px 12px; display: flex; flex-wrap: wrap; gap: 4px;">
|
|
363
|
+
${e.map(e=>`
|
|
364
|
+
<div class="fc-event fc-all-day-event" data-event-id="${this.escapeHTML(e.id)}"
|
|
365
|
+
style="background-color: ${this.getEventColor(e)}; font-size: 12px; padding: 4px 8px; border-radius: 4px; color: white; cursor: pointer; font-weight: 500;">
|
|
366
|
+
${this.escapeHTML(e.title)}
|
|
362
367
|
</div>
|
|
363
|
-
`).join(
|
|
368
|
+
`).join(``)}
|
|
364
369
|
</div>
|
|
365
370
|
</div>
|
|
366
|
-
`}_renderTimeGrid(t,
|
|
371
|
+
`}_renderTimeGrid(e,t,n,r){return`
|
|
367
372
|
<div id="day-scroll-container" class="fc-time-grid-container" style="flex: 1; overflow-y: auto; overflow-x: hidden; position: relative;">
|
|
368
373
|
<div class="fc-time-grid" style="display: grid; grid-template-columns: 60px 1fr; position: relative; height: ${this.totalHeight}px;">
|
|
369
|
-
${this._renderTimeGutter(
|
|
370
|
-
${this._renderDayColumn(t,
|
|
374
|
+
${this._renderTimeGutter(r)}
|
|
375
|
+
${this._renderDayColumn(e,t,n,r)}
|
|
371
376
|
</div>
|
|
372
377
|
</div>
|
|
373
|
-
`}_renderTimeGutter(
|
|
378
|
+
`}_renderTimeGutter(e){return`
|
|
374
379
|
<div class="fc-time-gutter" style="border-right: 1px solid var(--fc-border-color); background: var(--fc-background-alt);">
|
|
375
|
-
${
|
|
380
|
+
${e.map(e=>`
|
|
376
381
|
<div style="height: ${this.hourHeight}px; font-size: 11px; color: var(--fc-text-light); text-align: right; padding-right: 12px; font-weight: 500;">
|
|
377
|
-
${e===0
|
|
382
|
+
${e===0?``:this.formatHour(e)}
|
|
378
383
|
</div>
|
|
379
|
-
`).join(
|
|
384
|
+
`).join(``)}
|
|
380
385
|
</div>
|
|
381
|
-
`}_renderDayColumn(t,
|
|
382
|
-
<div class="fc-day-column" data-date="${
|
|
386
|
+
`}_renderDayColumn(e,t,n,r){return`
|
|
387
|
+
<div class="fc-day-column" data-date="${n.toISOString()}" style="position: relative; cursor: pointer;">
|
|
383
388
|
<!-- Hour grid lines -->
|
|
384
|
-
${
|
|
389
|
+
${r.map(()=>`<div style="height: ${this.hourHeight}px; border-bottom: 1px solid var(--fc-background-hover);"></div>`).join(``)}
|
|
385
390
|
|
|
386
391
|
<!-- Now indicator for today -->
|
|
387
|
-
${
|
|
392
|
+
${t?this.renderNowIndicator():``}
|
|
388
393
|
|
|
389
394
|
<!-- Timed events -->
|
|
390
|
-
${(()=>{
|
|
395
|
+
${(()=>{let t=this.computeOverlapLayout(e);return e.map(e=>this.renderTimedEvent(e,{compact:!1,overlapLayout:t})).join(``)})()}
|
|
391
396
|
</div>
|
|
392
|
-
`}_attachEventHandlers(){this.addListener(this.container
|
|
393
|
-
${
|
|
394
|
-
${
|
|
397
|
+
`}_attachEventHandlers(){this.addListener(this.container,`click`,e=>{let t=e.target.closest(`.fc-day-column`);if(!t||!this.container.contains(t)||e.target.closest(`.fc-event`))return;let n=new Date(t.dataset.date),r=this.container.querySelector(`#day-scroll-container`),i=t.offsetTop,a=e.clientY-t.getBoundingClientRect().top+(r?r.scrollTop:0)-i,o=Math.max(0,Math.min(a+i,this.totalHeight));n.setHours(Math.floor(o/this.hourHeight),Math.floor(o%this.hourHeight/(this.hourHeight/60)),0,0),this.stateManager.selectDate(n)}),this.attachCommonEventHandlers()}_scrollToCurrentTime(){if(this._scrolled)return;let e=this.container.querySelector(`#day-scroll-container`);e&&(e.scrollTop=8*this.hourHeight-50,this._scrolled=!0)}},p=class extends n{constructor(){super(),this._isVisible=!1,this._cleanupFocusTrap=null,this.config={title:`New Event`,defaultDuration:60,colors:[{color:`#2563EB`,label:`Blue`},{color:`#10B981`,label:`Green`},{color:`#F59E0B`,label:`Amber`},{color:`#EF4444`,label:`Red`},{color:`#8B5CF6`,label:`Purple`},{color:`#6B7280`,label:`Gray`}]},this._formData={title:``,start:new Date,end:new Date,allDay:!1,color:this.config.colors[0].color}}static get observedAttributes(){return[`open`]}attributeChangedCallback(e,t,n){e===`open`&&(n===null?this.close():this.open())}getStyles(){return`
|
|
398
|
+
${c.getBaseStyles()}
|
|
399
|
+
${c.getButtonStyles()}
|
|
395
400
|
|
|
396
401
|
:host {
|
|
397
402
|
display: none;
|
|
@@ -592,16 +597,16 @@
|
|
|
592
597
|
<div class="form-group">
|
|
593
598
|
<label id="color-label">Color</label>
|
|
594
599
|
<div class="color-options" id="color-picker" role="radiogroup" aria-labelledby="color-label">
|
|
595
|
-
${this.config.colors.map(
|
|
600
|
+
${this.config.colors.map(e=>`
|
|
596
601
|
<button type="button"
|
|
597
|
-
class="color-btn ${
|
|
598
|
-
style="background-color: ${
|
|
599
|
-
data-color="${
|
|
600
|
-
title="${
|
|
601
|
-
aria-label="${
|
|
602
|
-
aria-checked="${
|
|
602
|
+
class="color-btn ${e.color===this._formData.color?`selected`:``}"
|
|
603
|
+
style="background-color: ${c.sanitizeColor(e.color)}"
|
|
604
|
+
data-color="${s.escapeHTML(e.color)}"
|
|
605
|
+
title="${s.escapeHTML(e.label)}"
|
|
606
|
+
aria-label="${s.escapeHTML(e.label)}"
|
|
607
|
+
aria-checked="${e.color===this._formData.color?`true`:`false`}"
|
|
603
608
|
role="radio"></button>
|
|
604
|
-
`).join(
|
|
609
|
+
`).join(``)}
|
|
605
610
|
</div>
|
|
606
611
|
</div>
|
|
607
612
|
</div>
|
|
@@ -611,14 +616,14 @@
|
|
|
611
616
|
<button class="fc-btn fc-btn-primary" id="save-btn">Save Event</button>
|
|
612
617
|
</footer>
|
|
613
618
|
</div>
|
|
614
|
-
`}afterRender(){this.modalContent=this.$(
|
|
615
|
-
${
|
|
616
|
-
${
|
|
617
|
-
${
|
|
618
|
-
${
|
|
619
|
+
`}afterRender(){this.modalContent=this.$(`.modal-content`),this.titleInput=this.$(`#event-title`),this.startInput=this.$(`#event-start`),this.endInput=this.$(`#event-end`),this.colorContainer=this.$(`#color-picker`),this.titleGroup=this.$(`#title-group`),this.endGroup=this.$(`#end-group`),this.addListener(this.$(`#close-x`),`click`,()=>this.close()),this.addListener(this.$(`#cancel-btn`),`click`,()=>this.close()),this.addListener(this.$(`#save-btn`),`click`,()=>this.save()),this.colorContainer.querySelectorAll(`.color-btn`).forEach(e=>{this.addListener(e,`click`,e=>{this._formData.color=e.currentTarget.dataset.color,this.updateColorSelection()})}),this.addListener(this,`click`,e=>{e.target===this&&this.close()}),this._keydownListenerAdded||=(this._handleKeyDown=e=>{e.key===`Escape`&&this.hasAttribute(`open`)&&this.close()},window.addEventListener(`keydown`,this._handleKeyDown),!0)}updateColorSelection(){this.colorContainer.querySelectorAll(`.color-btn`).forEach(e=>{let t=e.dataset.color===this._formData.color;e.classList.toggle(`selected`,t),e.setAttribute(`aria-checked`,t?`true`:`false`)})}open(e=new Date){this.hasAttribute(`open`)||this.setAttribute(`open`,``),this.titleGroup.classList.remove(`has-error`),this.endGroup.classList.remove(`has-error`),this._formData.start=e,this._formData.end=new Date(e.getTime()+this.config.defaultDuration*60*1e3),this._formData.title=``,this._formData.color=this.config.colors[0].color,this.startInput&&(this.titleInput.value=``,this.startInput.value=this.formatDateForInput(this._formData.start),this.endInput.value=this.formatDateForInput(this._formData.end),this.updateColorSelection(),this._cleanupFocusTrap&&this._cleanupFocusTrap(),this._cleanupFocusTrap=s.trapFocus(this.modalContent))}close(){this.removeAttribute(`open`),this._cleanupFocusTrap&&=(this._cleanupFocusTrap(),null)}validate(){let e=!0;this.titleGroup.classList.remove(`has-error`),this.endGroup.classList.remove(`has-error`),this.titleInput.value.trim()||(this.titleGroup.classList.add(`has-error`),e=!1);let t=new Date(this.startInput.value);return new Date(this.endInput.value)<=t&&(this.endGroup.classList.add(`has-error`),e=!1),e}save(){if(!this.validate())return;let e={title:this.titleInput.value.trim(),start:new Date(this.startInput.value),end:new Date(this.endInput.value),backgroundColor:this._formData.color};this.emit(`save`,e),this.close()}formatDateForInput(e){let t=e=>String(e).padStart(2,`0`);return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}T${t(e.getHours())}:${t(e.getMinutes())}`}unmount(){this._cleanupFocusTrap&&this._cleanupFocusTrap(),this._handleKeyDown&&(window.removeEventListener(`keydown`,this._handleKeyDown),this._handleKeyDown=null,this._keydownListenerAdded=!1)}};customElements.get(`forcecal-event-form`)||customElements.define(`forcecal-event-form`,p);var m=class e extends n{static RENDERERS={month:u,week:d,day:f};static get observedAttributes(){return[`view`,`date`,`locale`,`timezone`,`week-starts-on`,`height`]}constructor(){super(),this.stateManager=null,this.currentView=null,this._hasRendered=!1,this._busUnsubscribers=[]}propChanged(e,t,n){if(!(!this.stateManager||t===n))switch(e){case`view`:n&&this.stateManager.setView(n);break;case`date`:{let e=n?new Date(n):null;e&&!isNaN(e.getTime())&&this.stateManager.setDate(e);break}case`locale`:n&&this.stateManager.updateConfig({locale:n});break;case`timezone`:n&&this.stateManager.updateConfig({timeZone:n});break;case`week-starts-on`:{let e=parseInt(n,10);Number.isNaN(e)||this.stateManager.updateConfig({weekStartsOn:e});break}}}initialize(){let e={view:this.getAttribute(`view`)||`month`,date:this.getAttribute(`date`)?new Date(this.getAttribute(`date`)):new Date,locale:this.getAttribute(`locale`)||`en-US`,timeZone:this.getAttribute(`timezone`)||Intl.DateTimeFormat().resolvedOptions().timeZone,weekStartsOn:parseInt(this.getAttribute(`week-starts-on`)||`0`)};this.stateManager=new a(e),this._stateUnsubscribe=this.stateManager.subscribe(this.handleStateChange.bind(this)),this.setupEventListeners()}setupEventListeners(){this._busUnsubscribers.forEach(e=>e()),this._busUnsubscribers=[];let e=this.stateManager.eventBus;this._busUnsubscribers.push(e.on(`navigation:*`,(e,t)=>{this.emit(`calendar-navigate`,{action:t.split(`:`)[1],...e})})),this._busUnsubscribers.push(e.on(`view:changed`,e=>{this.emit(`calendar-view-change`,e)}));let t=(e,t)=>{this.emit(`calendar-event-${e}`,t)};this._busUnsubscribers.push(e.on(`event:add`,e=>{t(`add`,e)})),this._busUnsubscribers.push(e.on(`event:update`,e=>{t(`update`,e)})),this._busUnsubscribers.push(e.on(`event:remove`,e=>{t(`remove`,e)})),this._busUnsubscribers.push(e.on(`event:added`,e=>{this.emit(`calendar-event-added`,e)})),this._busUnsubscribers.push(e.on(`event:updated`,e=>{this.emit(`calendar-event-updated`,e)})),this._busUnsubscribers.push(e.on(`event:deleted`,e=>{this.emit(`calendar-event-deleted`,e)})),this._busUnsubscribers.push(e.on(`date:selected`,e=>{this.emit(`calendar-date-select`,e)}))}handleStateChange(e,t){if(!this._hasRendered)return;let n=e.view!==t?.view,r=e.currentDate?.getTime()!==t?.currentDate?.getTime(),i=e.events!==t?.events,a=e.loading!==t?.loading;if(e.error!==t?.error){this.render();return}if(a){this._updateLoadingState(e.loading);return}n&&(this.currentView=e.view),n?(this._updateTitle(),this._updateViewButtons(),this._switchView()):r?(this._updateTitle(),this._updateViewContent()):i&&this._updateViewContent()}_updateTitle(){let e=this.$(`.fc-title`);if(e){let t=this.stateManager.getState();e.textContent=this.getTitle(t.currentDate,t.view)}}_updateViewButtons(){let e=this.stateManager.getState();this.$$(`[data-view]`).forEach(t=>{let n=t.dataset.view===e.view;t.classList.toggle(`active`,n)})}_switchView(){let t=this.$(`#calendar-view-container`);if(t){this._currentViewInstance&&this._currentViewInstance.cleanup&&this._currentViewInstance.cleanup();try{let n=new(e.RENDERERS[this.currentView]||u)(t,this.stateManager);n._viewType=this.currentView,this._currentViewInstance=n,n.render()}catch(e){console.error(`[ForceCalendar] Error switching view:`,e)}}}_updateViewContent(){this._currentViewInstance&&this._currentViewInstance.render&&this._currentViewInstance.render()}_updateLoadingState(e){let t=this.$(`.fc-loading`),n=this.$(`.fc-view-container`);t&&(t.style.display=e?`flex`:`none`),n&&(n.style.display=e?`none`:`flex`)}mount(){this.currentView=this.stateManager.getView(),super.mount()}loadView(e){!e||this.currentView===e||(this.currentView=e,this._switchView(),this._updateViewButtons(),this._updateTitle())}getStyles(){let e=this.getAttribute(`height`)||`800px`;return`
|
|
620
|
+
${c.getBaseStyles()}
|
|
621
|
+
${c.getButtonStyles()}
|
|
622
|
+
${c.getGridStyles()}
|
|
623
|
+
${c.getAnimations()}
|
|
619
624
|
|
|
620
625
|
:host {
|
|
621
|
-
--calendar-height: ${
|
|
626
|
+
--calendar-height: ${e};
|
|
622
627
|
display: block;
|
|
623
628
|
font-family: var(--fc-font-family);
|
|
624
629
|
}
|
|
@@ -716,6 +721,20 @@
|
|
|
716
721
|
padding: 0;
|
|
717
722
|
}
|
|
718
723
|
|
|
724
|
+
.fc-month-day:focus-visible,
|
|
725
|
+
.fc-event:focus-visible {
|
|
726
|
+
outline: 2px solid var(--fc-primary-color);
|
|
727
|
+
outline-offset: -2px;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
.fc-nav-arrow:focus-visible,
|
|
731
|
+
.fc-btn:focus-visible,
|
|
732
|
+
.fc-btn-today:focus-visible,
|
|
733
|
+
.fc-view-button:focus-visible {
|
|
734
|
+
outline: 2px solid var(--fc-primary-color);
|
|
735
|
+
outline-offset: 2px;
|
|
736
|
+
}
|
|
737
|
+
|
|
719
738
|
.fc-nav-arrow:hover {
|
|
720
739
|
background: var(--fc-background-hover);
|
|
721
740
|
color: var(--fc-text-color);
|
|
@@ -996,13 +1015,13 @@
|
|
|
996
1015
|
height: 100%;
|
|
997
1016
|
background: var(--fc-background);
|
|
998
1017
|
}
|
|
999
|
-
`}template(){
|
|
1018
|
+
`}template(){let{currentDate:e,view:t,loading:n,error:r}=this.stateManager.getState();if(r)return`
|
|
1000
1019
|
<div class="force-calendar">
|
|
1001
1020
|
<div class="fc-error">
|
|
1002
|
-
<p><strong>Error:</strong> ${
|
|
1021
|
+
<p><strong>Error:</strong> ${s.escapeHTML(r.message||`An error occurred`)}</p>
|
|
1003
1022
|
</div>
|
|
1004
1023
|
</div>
|
|
1005
|
-
`;
|
|
1024
|
+
`;let i=this.getTitle(e,t);return`
|
|
1006
1025
|
<div class="force-calendar">
|
|
1007
1026
|
<header class="fc-header">
|
|
1008
1027
|
<div class="fc-header-left">
|
|
@@ -1012,12 +1031,12 @@
|
|
|
1012
1031
|
</div>
|
|
1013
1032
|
|
|
1014
1033
|
<div class="fc-header-center">
|
|
1015
|
-
<button class="fc-nav-arrow" data-action="previous" title="Previous">
|
|
1016
|
-
${this.getIcon(
|
|
1034
|
+
<button class="fc-nav-arrow" data-action="previous" title="Previous" aria-label="Previous ${t}">
|
|
1035
|
+
${this.getIcon(`chevron-left`)}
|
|
1017
1036
|
</button>
|
|
1018
|
-
<h2 class="fc-title">${
|
|
1019
|
-
<button class="fc-nav-arrow" data-action="next" title="Next">
|
|
1020
|
-
${this.getIcon(
|
|
1037
|
+
<h2 class="fc-title" aria-live="polite">${s.escapeHTML(i)}</h2>
|
|
1038
|
+
<button class="fc-nav-arrow" data-action="next" title="Next" aria-label="Next ${t}">
|
|
1039
|
+
${this.getIcon(`chevron-right`)}
|
|
1021
1040
|
</button>
|
|
1022
1041
|
</div>
|
|
1023
1042
|
|
|
@@ -1025,30 +1044,33 @@
|
|
|
1025
1044
|
<button class="fc-btn fc-btn-primary" id="create-event-btn" style="height: 28px; padding: 0 12px; font-size: 12px;">
|
|
1026
1045
|
+ New Event
|
|
1027
1046
|
</button>
|
|
1028
|
-
<div class="fc-view-buttons" role="group">
|
|
1029
|
-
<button class="fc-view-button ${
|
|
1047
|
+
<div class="fc-view-buttons" role="group" aria-label="Calendar view">
|
|
1048
|
+
<button class="fc-view-button ${t===`month`?`active`:``}"
|
|
1049
|
+
aria-pressed="${t===`month`?`true`:`false`}"
|
|
1030
1050
|
data-view="month">Month</button>
|
|
1031
|
-
<button class="fc-view-button ${
|
|
1051
|
+
<button class="fc-view-button ${t===`week`?`active`:``}"
|
|
1052
|
+
aria-pressed="${t===`week`?`true`:`false`}"
|
|
1032
1053
|
data-view="week">Week</button>
|
|
1033
|
-
<button class="fc-view-button ${
|
|
1054
|
+
<button class="fc-view-button ${t===`day`?`active`:``}"
|
|
1055
|
+
aria-pressed="${t===`day`?`true`:`false`}"
|
|
1034
1056
|
data-view="day">Day</button>
|
|
1035
1057
|
</div>
|
|
1036
1058
|
</div>
|
|
1037
1059
|
</header>
|
|
1038
1060
|
|
|
1039
1061
|
<div class="fc-body">
|
|
1040
|
-
<div class="fc-loading" style="display: ${
|
|
1062
|
+
<div class="fc-loading" style="display: ${n?`flex`:`none`};">
|
|
1041
1063
|
<div class="fc-spinner"></div>
|
|
1042
1064
|
<span>Loading...</span>
|
|
1043
1065
|
</div>
|
|
1044
|
-
<div class="fc-view-container" style="display: ${
|
|
1066
|
+
<div class="fc-view-container" style="display: ${n?`none`:`flex`};">
|
|
1045
1067
|
${this.renderView()}
|
|
1046
1068
|
</div>
|
|
1047
1069
|
</div>
|
|
1048
1070
|
|
|
1049
1071
|
<forcecal-event-form id="event-modal"></forcecal-event-form>
|
|
1050
1072
|
</div>
|
|
1051
|
-
`}renderView(){return
|
|
1073
|
+
`}renderView(){return`<div id="calendar-view-container"></div>`}afterRender(){let t=this.$(`#calendar-view-container`);if(t&&this.stateManager&&this.currentView){if(this._currentViewInstance&&this._currentViewInstance._viewType===this.currentView&&t.children.length>0)return;this._currentViewInstance&&(this._currentViewInstance.cleanup&&this._currentViewInstance.cleanup(),this._viewUnsubscribe&&=(this._viewUnsubscribe(),null));try{let n=new(e.RENDERERS[this.currentView]||u)(t,this.stateManager);n._viewType=this.currentView,this._currentViewInstance=n,n.render()}catch(e){console.error(`[ForceCalendar] Error creating/rendering view:`,e)}}this.$$(`[data-action]`).forEach(e=>{this.addListener(e,`click`,this.handleNavigation)}),this.$$(`[data-view]`).forEach(e=>{this.addListener(e,`click`,this.handleViewChange)});let n=this.$(`#event-modal`),r=this.$(`#create-event-btn`);r&&n&&this.addListener(r,`click`,()=>{n.open(new Date)}),this.addListener(this.shadowRoot,`day-click`,e=>{n&&n.open(e.detail.date)}),n&&this.addListener(n,`save`,e=>{let t=e.detail,n=window.crypto&&typeof window.crypto.randomUUID==`function`?window.crypto.randomUUID():Math.random().toString(36).substring(2,15);this.stateManager.addEvent({id:n,...t})}),this._hasRendered=!0}handleNavigation(e){switch(e.currentTarget.dataset.action){case`today`:this.stateManager.today();break;case`previous`:this.stateManager.previous();break;case`next`:this.stateManager.next();break}}handleViewChange(e){let t=e.currentTarget.dataset.view;this.stateManager.setView(t)}getTitle(e,t){let n=this.stateManager.getState().config.locale;switch(t){case`month`:return o.formatDate(e,`month`,n);case`week`:{let t=o.startOfWeek(e),r=o.endOfWeek(e);return o.formatDateRange(t,r,n)}case`day`:return o.formatDate(e,`long`,n);default:return o.formatDate(e,`month`,n)}}getIcon(e){return{"chevron-left":`
|
|
1052
1074
|
<svg class="fc-icon" viewBox="0 0 24 24">
|
|
1053
1075
|
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
|
|
1054
1076
|
</svg>
|
|
@@ -1060,5 +1082,5 @@
|
|
|
1060
1082
|
<svg class="fc-icon" viewBox="0 0 24 24">
|
|
1061
1083
|
<path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/>
|
|
1062
1084
|
</svg>
|
|
1063
|
-
`}[
|
|
1064
|
-
//# sourceMappingURL=force-calendar-interface.umd.js.map
|
|
1085
|
+
`}[e]||``}addEvent(e){return this.stateManager.addEvent(e)}updateEvent(e,t){return this.stateManager.updateEvent(e,t)}deleteEvent(e){return this.stateManager.deleteEvent(e)}getEvents(){return this.stateManager.getEvents()}setView(e){this.stateManager.setView(e)}setDate(e){this.stateManager.setDate(e)}next(){this.stateManager.next()}previous(){this.stateManager.previous()}today(){this.stateManager.today()}unmount(){this.destroy()}destroy(){this._busUnsubscribers.forEach(e=>e()),this._busUnsubscribers=[],this._stateUnsubscribe&&=(this._stateUnsubscribe(),null),this._currentViewInstance&&this._currentViewInstance.cleanup&&(this._currentViewInstance.cleanup(),this._currentViewInstance=null),this.stateManager&&this.stateManager.destroy(),super.cleanup()}};customElements.get(`forcecal-main`)||customElements.define(`forcecal-main`,m),e.BaseComponent=n,e.BaseViewRenderer=l,e.DOMUtils=s,e.DateUtils=o,e.DayViewRenderer=f,e.EventBus=r,e.ForceCalendar=m,e.MonthViewRenderer=u,e.StateManager=a,e.StyleUtils=c,e.WeekViewRenderer=d,e.eventBus=i});
|
|
1086
|
+
//# sourceMappingURL=force-calendar-interface.umd.js.map
|