@forcecalendar/interface 1.2.0 → 1.4.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.
@@ -247,7 +247,7 @@
247
247
  ${this.formatTime(i)}${n?``:` - `+this.formatTime(a)}
248
248
  </div>
249
249
  </div>
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=`
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)}_enhanceTimeGridAccessibility(e,t){let n=this.container.querySelector(`.fc-time-grid`);if(!n)return;n.setAttribute(`role`,`grid`),n.setAttribute(`aria-label`,t);let r=this.container.querySelector(`.fc-time-gutter`);r&&r.setAttribute(`aria-hidden`,`true`);let i=this.stateManager.getState().config.locale||`en-US`,a=new Intl.DateTimeFormat(i,{weekday:`long`,month:`long`,day:`numeric`}),o=Array.from(this.container.querySelectorAll(e));for(let e of o){e.setAttribute(`role`,`row`);let t=new Date(e.dataset.date),n=a.format(t);e.setAttribute(`aria-label`,n);for(let t of e.querySelectorAll(`.fc-hour-slot`))t.setAttribute(`role`,`gridcell`),t.setAttribute(`tabindex`,`-1`),t.setAttribute(`aria-label`,`${n}, ${this.formatHour(Number(t.dataset.hour))}`)}if(this._applySlotRovingTabindex(o),this._pendingSlotFocus){let{colIndex:e,hour:t}=this._pendingSlotFocus;this._pendingSlotFocus=null;let n=this._slotAt(o,e,t);n&&(this._applySlotRovingTabindex(o,n),n.focus())}this.addListener(this.container,`keydown`,t=>{let n=t.target.closest(`.fc-hour-slot`);if(!n||!this.container.contains(n))return;let r=n.closest(e),i=o.indexOf(r),a=Number(n.dataset.hour),s=null;switch(t.key){case`ArrowDown`:s=this._slotAt(o,i,a+1);break;case`ArrowUp`:s=this._slotAt(o,i,a-1);break;case`ArrowRight`:s=this._slotAt(o,i+1,a);break;case`ArrowLeft`:s=this._slotAt(o,i-1,a);break;case`Home`:s=this._slotAt(o,i,0);break;case`End`:s=this._slotAt(o,i,23);break;case`PageUp`:case`PageDown`:t.preventDefault(),this._pendingSlotFocus={colIndex:i,hour:a},t.key===`PageDown`?this.stateManager.next():this.stateManager.previous();return;case`Enter`:case` `:{t.preventDefault();let e=new Date(r.dataset.date);e.setHours(a,0,0,0),this._pendingSlotFocus={colIndex:i,hour:a},this.stateManager.selectDate(e);return}default:return}t.preventDefault(),s&&(this._applySlotRovingTabindex(o,s),s.scrollIntoView?.({block:`nearest`}),s.focus())})}_slotAt(e,t,n){return t<0||t>=e.length||n<0||n>23?null:e[t].querySelector(`.fc-hour-slot[data-hour="${n}"]`)}_applySlotRovingTabindex(e,t=null){let n=this.container.querySelectorAll(`.fc-hour-slot`);if(n.length!==0){if(!t){let r=e.find(e=>this.isToday(new Date(e.dataset.date)))||e[0];t=r&&r.querySelector(`.fc-hour-slot[data-hour="9"]`),t||=n[0]}for(let e of n)e.setAttribute(`tabindex`,e===t?`0`:`-1`)}}_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=4,d=15,f=1;function p(e,t=d){return Math.round(e/t)*t}function m(e,t){return Math.max(0,Math.min(e,1440-t))}function h(e,t){let n=new Date(e);return n.setHours(t.getHours(),t.getMinutes(),t.getSeconds(),t.getMilliseconds()),n}var g=class{constructor(e){this.renderer=e,this.container=e.container,this.stateManager=e.stateManager,this._active=null,this._docListeners=[]}enableMonthMove(){this.renderer.addListener(this.container,`pointerdown`,e=>{if(e.button!==0)return;let t=e.target.closest(`.fc-event`);!t||!this.container.contains(t)||t.closest(`.fc-month-day`)&&this._arm(e,{mode:`month-move`,eventEl:t,eventId:t.dataset.eventId,onDragMove:e=>this._monthDragMove(e),onDrop:e=>this._monthDrop(e)})})}enableTimeGrid(e){this._columnSelector=e,this._injectResizeHandles(),this.renderer.addListener(this.container,`pointerdown`,t=>{if(t.button!==0)return;let n=t.target.closest(`.fc-resize-handle`);if(n){let e=n.closest(`.fc-timed-event`);if(!e)return;t.preventDefault(),this._arm(t,{mode:`resize`,eventEl:e,eventId:e.dataset.eventId,originTop:parseFloat(e.style.top)||0,originHeight:parseFloat(e.style.height)||30,onDragMove:e=>this._resizeDragMove(e),onDrop:()=>this._resizeDrop()});return}let r=t.target.closest(`.fc-timed-event`);if(r&&this.container.contains(r)){this._arm(t,{mode:`time-move`,eventEl:r,eventId:r.dataset.eventId,originTop:parseFloat(r.style.top)||0,originColumn:r.closest(e),onDragMove:e=>this._timeMoveDragMove(e),onDrop:()=>this._timeMoveDrop()});return}let i=t.target.closest(e);i&&!t.target.closest(`.fc-event`)&&this._arm(t,{mode:`create`,column:i,onDragMove:e=>this._createDragMove(e),onDrop:()=>this._createDrop()})})}_arm(e,t){this._active={...t,startX:e.clientX,startY:e.clientY,dragging:!1};let n=e=>this._onPointerMove(e),r=e=>this._onPointerUp(e),i=()=>this._cancel(),a=e=>{e.key===`Escape`&&this._cancel()},o=this.container.ownerDocument;o.addEventListener(`pointermove`,n),o.addEventListener(`pointerup`,r),o.addEventListener(`pointercancel`,i),o.addEventListener(`keydown`,a),this._docListeners=[[`pointermove`,n],[`pointerup`,r],[`pointercancel`,i],[`keydown`,a]]}_onPointerMove(e){let t=this._active;if(t){if(!t.dragging){if(Math.abs(e.clientX-t.startX)<u&&Math.abs(e.clientY-t.startY)<u)return;t.dragging=!0,t.eventEl&&t.eventEl.classList.add(`fc-dragging`)}e.preventDefault(),t.onDragMove(e)}}_onPointerUp(e){let t=this._active;if(this._teardownDocListeners(),t){if(t.dragging){let n=this.container.ownerDocument,r=e=>{e.stopPropagation(),e.preventDefault()};n.addEventListener(`click`,r,{capture:!0,once:!0}),setTimeout(()=>n.removeEventListener(`click`,r,{capture:!0}),0),t.onDrop(e)}this._cleanupVisuals(t),this._active=null}}_cancel(){let e=this._active;this._teardownDocListeners(),this._active=null,e&&this._cleanupVisuals(e)}_teardownDocListeners(){let e=this.container.ownerDocument;for(let[t,n]of this._docListeners)e.removeEventListener(t,n);this._docListeners=[]}_cleanupVisuals(e){e.eventEl&&(e.eventEl.classList.remove(`fc-dragging`),e.eventEl.style.transform=``),this.container.querySelectorAll(`.fc-drop-target`).forEach(e=>e.classList.remove(`fc-drop-target`)),this._selectionEl?.remove(),this._selectionEl=null}_cellAtPoint(e,t){for(let n of this.container.querySelectorAll(`.fc-month-day`)){let r=n.getBoundingClientRect();if(e>=r.left&&e<r.right&&t>=r.top&&t<r.bottom)return n}return null}_monthDragMove(e){let t=this._active;t.eventEl.style.transform=`translate(${e.clientX-t.startX}px, ${e.clientY-t.startY}px)`;let n=this._cellAtPoint(e.clientX,e.clientY);n!==t.dropCell&&(t.dropCell?.classList.remove(`fc-drop-target`),n?.classList.add(`fc-drop-target`),t.dropCell=n)}_monthDrop(){let e=this._active??{},t=e.dropCell;if(!t)return;let n=this.stateManager.getEvents().find(t=>t.id===e.eventId);if(!n)return;let r=new Date(n.start),i=h(new Date(t.dataset.date),r),a=i.getTime()-r.getTime();a!==0&&this.stateManager.updateEvent(e.eventId,{start:i,end:new Date(new Date(n.end).getTime()+a)})}_columnAtPoint(e){for(let t of this.container.querySelectorAll(this._columnSelector)){let n=t.getBoundingClientRect();if(e>=n.left&&e<n.right)return t}return null}_timeMoveDragMove(e){let t=this._active,n=this._columnAtPoint(e.clientX)||t.originColumn;t.dropColumn=n,t.deltaMinutes=p((e.clientY-t.startY)/f);let r=t.originColumn.getBoundingClientRect(),i=n.getBoundingClientRect();t.eventEl.style.transform=`translate(${i.left-r.left}px, ${t.deltaMinutes*f}px)`}_timeMoveDrop(){let e=this._active??{},t=this.stateManager.getEvents().find(t=>t.id===e.eventId);if(!t||!e.deltaMinutes&&e.dropColumn===e.originColumn)return;let n=new Date(t.start),r=new Date(t.end).getTime()-n.getTime(),i=h(e.dropColumn?new Date(e.dropColumn.dataset.date):n,n),a=m(i.getHours()*60+i.getMinutes()+(e.deltaMinutes||0),Math.round(r/6e4)),o=new Date(i);o.setHours(Math.floor(a/60),a%60,0,0),o.getTime()!==n.getTime()&&this.stateManager.updateEvent(e.eventId,{start:o,end:new Date(o.getTime()+r)})}_resizeDragMove(e){let t=this._active,n=p((e.clientY-t.startY)/f);t.newHeight=Math.max(d,t.originHeight+n),t.newHeight=Math.min(t.newHeight,1440-t.originTop),t.eventEl.style.height=`${t.newHeight}px`}_resizeDrop(){let e=this._active??{};if(!e.newHeight||e.newHeight===e.originHeight)return;let t=this.stateManager.getEvents().find(t=>t.id===e.eventId);if(!t)return;let n=new Date(new Date(t.start).getTime()+e.newHeight*6e4);this.stateManager.updateEvent(e.eventId,{end:n})}_createDragMove(e){let t=this._active,n=t.column.getBoundingClientRect(),r=t.startY-n.top,i=e.clientY-n.top;t.fromMinutes=p(Math.min(r,i)/f),t.toMinutes=p(Math.max(r,i)/f),t.fromMinutes=Math.max(0,t.fromMinutes),t.toMinutes=Math.min(1440,Math.max(t.toMinutes,t.fromMinutes+d)),this._selectionEl||(this._selectionEl=this.container.ownerDocument.createElement(`div`),this._selectionEl.className=`fc-drag-selection`,t.column.appendChild(this._selectionEl)),this._selectionEl.style.top=`${t.fromMinutes*f}px`,this._selectionEl.style.height=`${(t.toMinutes-t.fromMinutes)*f}px`}_createDrop(){let e=this._active??{};if(e.fromMinutes==null)return;let t=new Date(e.column.dataset.date);t.setHours(Math.floor(e.fromMinutes/60),e.fromMinutes%60,0,0);let n=new Date(e.column.dataset.date);n.setHours(Math.floor(e.toMinutes/60),e.toMinutes%60,0,0),this.container.dispatchEvent(new CustomEvent(`range-select`,{detail:{start:t,end:n},bubbles:!0,composed:!0}))}_injectResizeHandles(){for(let e of this.container.querySelectorAll(`.fc-timed-event`)){if(e.querySelector(`.fc-resize-handle`))continue;let t=this.container.ownerDocument.createElement(`div`);t.className=`fc-resize-handle`,t.setAttribute(`aria-hidden`,`true`),e.appendChild(t)}}},_=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
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
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
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(``)}
@@ -274,7 +274,7 @@
274
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
275
  ${this.escapeHTML(e.title)}
276
276
  </div>
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`
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(),new g(this).enableMonthMove()}_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}},v=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`
278
278
  <div class="fc-week-view" style="display: flex; flex-direction: column; height: 100%; background: var(--fc-background); overflow: hidden;">
279
279
  ${this._renderHeader(a)}
280
280
  ${this._renderAllDayRow(a)}
@@ -328,7 +328,7 @@
328
328
  `}_renderDayColumn(e,t){return`
329
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;">
330
330
  <!-- Hour grid lines -->
331
- ${t.map(()=>`<div style="height: ${this.hourHeight}px; border-bottom: 1px solid var(--fc-background-hover);"></div>`).join(``)}
331
+ ${t.map(e=>`<div class="fc-hour-slot" data-hour="${e}" style="height: ${this.hourHeight}px; border-bottom: 1px solid var(--fc-background-hover);"></div>`).join(``)}
332
332
 
333
333
  <!-- Now indicator for today -->
334
334
  ${e.isToday?this.renderNowIndicator():``}
@@ -336,7 +336,7 @@
336
336
  <!-- Timed events -->
337
337
  ${(()=>{let t=this.computeOverlapLayout(e.timedEvents);return e.timedEvents.map(e=>this.renderTimedEvent(e,{compact:!0,overlapLayout:t})).join(``)})()}
338
338
  </div>
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`
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();let e=this.stateManager.getViewData()?.days||[],t=this.stateManager.getState().config.locale||`en-US`,n=e[0]?new Date(e[0].date):new Date,r=`Week of ${new Intl.DateTimeFormat(t,{month:`long`,day:`numeric`,year:`numeric`}).format(n)}`;this._enhanceTimeGridAccessibility(`.fc-week-day-column`,r),new g(this).enableTimeGrid(`.fc-week-day-column`)}_scrollToCurrentTime(){if(this._scrolled)return;let e=this.container.querySelector(`#week-scroll-container`);e&&(e.scrollTop=8*this.hourHeight-50,this._scrolled=!0)}},y=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`
340
340
  <div class="fc-day-view" style="display: flex; flex-direction: column; height: 100%; background: var(--fc-background); overflow: hidden;">
341
341
  ${this._renderHeader(i,a,o)}
342
342
  ${this._renderAllDayRow(s,i)}
@@ -386,7 +386,7 @@
386
386
  `}_renderDayColumn(e,t,n,r){return`
387
387
  <div class="fc-day-column" data-date="${n.toISOString()}" style="position: relative; cursor: pointer;">
388
388
  <!-- Hour grid lines -->
389
- ${r.map(()=>`<div style="height: ${this.hourHeight}px; border-bottom: 1px solid var(--fc-background-hover);"></div>`).join(``)}
389
+ ${r.map(e=>`<div class="fc-hour-slot" data-hour="${e}" style="height: ${this.hourHeight}px; border-bottom: 1px solid var(--fc-background-hover);"></div>`).join(``)}
390
390
 
391
391
  <!-- Now indicator for today -->
392
392
  ${t?this.renderNowIndicator():``}
@@ -394,7 +394,7 @@
394
394
  <!-- Timed events -->
395
395
  ${(()=>{let t=this.computeOverlapLayout(e);return e.map(e=>this.renderTimedEvent(e,{compact:!1,overlapLayout:t})).join(``)})()}
396
396
  </div>
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`
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();let e=this.stateManager.getState().config.locale||`en-US`,t=this.stateManager.getState().currentDate||new Date,n=new Intl.DateTimeFormat(e,{weekday:`long`,month:`long`,day:`numeric`,year:`numeric`}).format(t);this._enhanceTimeGridAccessibility(`.fc-day-column`,n),new g(this).enableTimeGrid(`.fc-day-column`)}_scrollToCurrentTime(){if(this._scrolled)return;let e=this.container.querySelector(`#day-scroll-container`);e&&(e.scrollTop=8*this.hourHeight-50,this._scrolled=!0)}},b=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
398
  ${c.getBaseStyles()}
399
399
  ${c.getButtonStyles()}
400
400
 
@@ -616,7 +616,7 @@
616
616
  <button class="fc-btn fc-btn-primary" id="save-btn">Save Event</button>
617
617
  </footer>
618
618
  </div>
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`
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`,b);var x=class e extends n{static RENDERERS={month:_,week:v,day:y};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]||_)(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
620
  ${c.getBaseStyles()}
621
621
  ${c.getButtonStyles()}
622
622
  ${c.getGridStyles()}
@@ -722,11 +722,45 @@
722
722
  }
723
723
 
724
724
  .fc-month-day:focus-visible,
725
+ .fc-hour-slot:focus-visible,
725
726
  .fc-event:focus-visible {
726
727
  outline: 2px solid var(--fc-primary-color);
727
728
  outline-offset: -2px;
728
729
  }
729
730
 
731
+ .fc-event { touch-action: none; }
732
+
733
+ .fc-dragging {
734
+ opacity: 0.6;
735
+ z-index: 30;
736
+ pointer-events: none;
737
+ }
738
+
739
+ .fc-drop-target {
740
+ outline: 2px dashed var(--fc-primary-color);
741
+ outline-offset: -2px;
742
+ }
743
+
744
+ .fc-resize-handle {
745
+ position: absolute;
746
+ left: 0;
747
+ right: 0;
748
+ bottom: 0;
749
+ height: 6px;
750
+ cursor: ns-resize;
751
+ }
752
+
753
+ .fc-drag-selection {
754
+ position: absolute;
755
+ left: 2px;
756
+ right: 2px;
757
+ background: color-mix(in srgb, var(--fc-primary-color) 18%, transparent);
758
+ border: 1px solid var(--fc-primary-color);
759
+ border-radius: 4px;
760
+ pointer-events: none;
761
+ z-index: 20;
762
+ }
763
+
730
764
  .fc-nav-arrow:focus-visible,
731
765
  .fc-btn:focus-visible,
732
766
  .fc-btn-today:focus-visible,
@@ -1070,7 +1104,7 @@
1070
1104
 
1071
1105
  <forcecal-event-form id="event-modal"></forcecal-event-form>
1072
1106
  </div>
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":`
1107
+ `}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]||_)(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)}),this.addListener(this.shadowRoot,`range-select`,e=>{this.emit(`calendar-range-select`,e.detail),n&&n.open(e.detail.start)}),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":`
1074
1108
  <svg class="fc-icon" viewBox="0 0 24 24">
1075
1109
  <path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
1076
1110
  </svg>
@@ -1082,5 +1116,5 @@
1082
1116
  <svg class="fc-icon" viewBox="0 0 24 24">
1083
1117
  <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"/>
1084
1118
  </svg>
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});
1119
+ `}[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`,x),e.BaseComponent=n,e.BaseViewRenderer=l,e.DOMUtils=s,e.DateUtils=o,e.DayViewRenderer=y,e.EventBus=r,e.ForceCalendar=x,e.MonthViewRenderer=_,e.StateManager=a,e.StyleUtils=c,e.WeekViewRenderer=v,e.eventBus=i});
1086
1120
  //# sourceMappingURL=force-calendar-interface.umd.js.map