@forcecalendar/interface 0.5.0 → 0.7.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/dist/assets/{index-CPUFXutP.js → index-CDzXWV3y.js} +5 -5
- package/dist/index.html +1 -1
- package/package.json +7 -2
- package/src/components/EventForm.js +10 -8
- package/src/components/views/DayView.js +6 -5
- package/src/components/views/MonthView.js +3 -3
- package/src/components/views/WeekView.js +6 -5
- package/src/core/BaseComponent.js +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var Y=Object.defineProperty;var N=(u,e,t)=>e in u?Y(u,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):u[e]=t;var A=(u,e,t)=>N(u,typeof e!="symbol"?e+"":e,t);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))s(i);new MutationObserver(i=>{for(const a of i)if(a.type==="childList")for(const n of a.addedNodes)n.tagName==="LINK"&&n.rel==="modulepreload"&&s(n)}).observe(document,{childList:!0,subtree:!0});function t(i){const a={};return i.integrity&&(a.integrity=i.integrity),i.referrerPolicy&&(a.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?a.credentials="include":i.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function s(i){if(i.ep)return;i.ep=!0;const a=t(i);fetch(i.href,a)}})();class C extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._listeners=new Map,this._state=null,this._props=new Map,this._initialized=!1}connectedCallback(){this._initialized||(this.initialize(),this._initialized=!0),this.mount()}disconnectedCallback(){this.unmount(),this.cleanup()}initialize(){}mount(){this.render()}unmount(){}cleanup(){this._listeners.forEach((e,t)=>{t.removeEventListener(e.event,e.handler)}),this._listeners.clear()}setState(e){const 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){const s=this._props.get(e);this._props.set(e,t),this.propChanged(e,s,t)}getProp(e){return this._props.get(e)}propChanged(e,t,s){}
|
|
1
|
+
var Y=Object.defineProperty;var N=(u,e,t)=>e in u?Y(u,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):u[e]=t;var A=(u,e,t)=>N(u,typeof e!="symbol"?e+"":e,t);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))s(i);new MutationObserver(i=>{for(const a of i)if(a.type==="childList")for(const n of a.addedNodes)n.tagName==="LINK"&&n.rel==="modulepreload"&&s(n)}).observe(document,{childList:!0,subtree:!0});function t(i){const a={};return i.integrity&&(a.integrity=i.integrity),i.referrerPolicy&&(a.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?a.credentials="include":i.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function s(i){if(i.ep)return;i.ep=!0;const a=t(i);fetch(i.href,a)}})();class C extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._listeners=new Map,this._state=null,this._props=new Map,this._initialized=!1}connectedCallback(){this._initialized||(this.initialize(),this._initialized=!0),this.mount()}disconnectedCallback(){this.unmount(),this.cleanup()}initialize(){}mount(){this.render()}unmount(){}cleanup(){this._listeners.forEach((e,t)=>{t.removeEventListener(e.event,e.handler)}),this._listeners.clear()}setState(e){const 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){const s=this._props.get(e);this._props.set(e,t),this.propChanged(e,s,t)}getProp(e){return this._props.get(e)}propChanged(e,t,s){}addListener(e,t,s){if(!e||!t||!s){console.warn("addListener called with invalid parameters",{element:e,event:t,handler:s});return}const i=s.bind(this);e.addEventListener(t,i),this._listeners.set(e,{event:t,handler:i})}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;
|
|
@@ -501,7 +501,7 @@ var Y=Object.defineProperty;var N=(u,e,t)=>e in u?Y(u,e,{enumerable:!0,configura
|
|
|
501
501
|
${o?`<span class="event-time">${o}</span>`:""}
|
|
502
502
|
<span class="event-title">${T.escapeHTML(t)}</span>
|
|
503
503
|
</div>
|
|
504
|
-
`}afterRender(){this.$$(".month-day").forEach(e=>{
|
|
504
|
+
`}afterRender(){this.$$(".month-day").forEach(e=>{this.addListener(e,"click",this.handleDayClick)}),this.$$(".event-item").forEach(e=>{this.addListener(e,"click",this.handleEventClick)}),this.$$(".more-events").forEach(e=>{this.addListener(e,"click",this.handleMoreClick)})}handleDayClick(e){e.stopPropagation();const t=e.currentTarget,s=new Date(t.dataset.date);this.stateManager.selectDate(s),this.emit("day-click",{date:s})}handleEventClick(e){e.stopPropagation();const s=e.currentTarget.dataset.eventId,i=this.stateManager.getEvents().find(a=>a.id===s);i&&(this.stateManager.selectEvent(i),this.emit("event-click",{event:i}))}handleMoreClick(e){e.stopPropagation();const t=e.currentTarget.closest(".month-day"),s=new Date(t.dataset.date),i=this.stateManager.getEventsForDate(s);this.emit("more-events-click",{date:s,events:i})}unmount(){this.unsubscribe&&this.unsubscribe()}}class se extends C{constructor(){super(),this._stateManager=null,this.viewData=null,this.hours=Array.from({length:24},(e,t)=>t)}set stateManager(e){this._stateManager=e,e&&(this.unsubscribe=e.subscribe(this.handleStateUpdate.bind(this)),this.loadViewData())}get stateManager(){return this._stateManager}handleStateUpdate(e,t){if(e.currentDate!==(t==null?void 0:t.currentDate)||e.view!==(t==null?void 0:t.view)){this.loadViewData();return}e.events!==(t==null?void 0:t.events)&&this.loadViewData(),e.selectedDate!==(t==null?void 0:t.selectedDate)&&this.updateSelection(e.selectedDate,t==null?void 0:t.selectedDate)}updateSelection(e,t){if(t){const s=this.shadowRoot.querySelector(`[data-date^="${t.toISOString().split("T")[0]}"]`);s&&s.classList.remove("selected")}if(e){const s=this.shadowRoot.querySelector(`[data-date^="${e.toISOString().split("T")[0]}"]`);s&&s.classList.add("selected")}}loadViewData(){if(!this.stateManager)return;const e=this.stateManager.getViewData();this.viewData=this.processViewData(e),this.render()}processViewData(e){if(!e)return null;let t=[];return e.weeks&&e.weeks.length>0?t=e.weeks[0].days:e.days&&(t=e.days),!t||t.length===0?null:{...e,days:t.map(s=>{const i=new Date(s.date);return{...s,date:i,isToday:p.isToday(i),timedEvents:(s.events||[]).filter(a=>!a.allDay),allDayEvents:(s.events||[]).filter(a=>a.allDay)}})}}getStyles(){return`
|
|
505
505
|
:host {
|
|
506
506
|
display: flex;
|
|
507
507
|
flex-direction: column;
|
|
@@ -736,7 +736,7 @@ var Y=Object.defineProperty;var N=(u,e,t)=>e in u?Y(u,e,{enumerable:!0,configura
|
|
|
736
736
|
data-event-id="${e.id}">
|
|
737
737
|
${T.escapeHTML(e.title)}
|
|
738
738
|
</div>
|
|
739
|
-
`}renderNowIndicator(){const e=new Date;return`<div class="now-indicator" style="top: ${e.getHours()*60+e.getMinutes()}px"></div>`}afterRender(){const e=this.$("#scroll-container");e&&!this._scrolled&&(e.scrollTop=8*60-50,this._scrolled=!0),this.$$("[data-event-id]").forEach(t=>{
|
|
739
|
+
`}renderNowIndicator(){const e=new Date;return`<div class="now-indicator" style="top: ${e.getHours()*60+e.getMinutes()}px"></div>`}afterRender(){const e=this.$("#scroll-container");e&&!this._scrolled&&(e.scrollTop=8*60-50,this._scrolled=!0),this.$$("[data-event-id]").forEach(t=>{this.addListener(t,"click",s=>{s.stopPropagation();const i=s.currentTarget.dataset.eventId,a=this.stateManager.getEvents().find(n=>n.id===i);a&&this.emit("event-click",{event:a})})}),this.$$(".day-column").forEach(t=>{this.addListener(t,"click",s=>{const i=s.currentTarget,a=this.$("#scroll-container"),n=i.getBoundingClientRect(),r=s.clientY-n.top+(a?a.scrollTop:0),o=new Date(i.dataset.date);o.setHours(Math.floor(r/60),Math.floor(r%60),0,0),this.stateManager.selectDate(o),this.emit("day-click",{date:o})})})}unmount(){this.unsubscribe&&this.unsubscribe()}}class ie extends C{constructor(){super(),this._stateManager=null,this.viewData=null,this.hours=Array.from({length:24},(e,t)=>t)}set stateManager(e){this._stateManager=e,e&&(this.unsubscribe=e.subscribe(this.handleStateUpdate.bind(this)),this.loadViewData())}get stateManager(){return this._stateManager}handleStateUpdate(e,t){if(e.currentDate!==(t==null?void 0:t.currentDate)||e.view!==(t==null?void 0:t.view)){this.loadViewData();return}e.events!==(t==null?void 0:t.events)&&this.loadViewData(),e.selectedDate!==(t==null?void 0:t.selectedDate)&&this.updateSelection(e.selectedDate,t==null?void 0:t.selectedDate)}updateSelection(e,t){const s=this.shadowRoot.querySelector(".day-column");if(!s)return;(a=>a&&p.isSameDay(a,new Date(s.dataset.date)))(e)?s.classList.add("selected"):s.classList.remove("selected")}loadViewData(){if(!this.stateManager)return;const e=this.stateManager.getViewData();this.viewData=this.processViewData(e),this.render()}processViewData(e){var n;if(!e)return null;let t=null;const s=(n=this.stateManager)==null?void 0:n.getState(),i=(s==null?void 0:s.currentDate)||new Date;if(e.days&&Array.isArray(e.days)&&e.days.length>0)t=e.days.find(r=>p.isSameDay(new Date(r.date),i))||e.days[0];else if(e.weeks&&Array.isArray(e.weeks)&&e.weeks.length>0){const r=e.weeks.flatMap(o=>o.days||[]);t=r.find(o=>p.isSameDay(new Date(o.date),i))||r[0]}else e.date&&(t=e);if(!t)return null;const a=new Date(t.date);return{...e,day:{...t,date:a,isToday:p.isToday(a),timedEvents:(t.events||[]).filter(r=>!r.allDay),allDayEvents:(t.events||[]).filter(r=>r.allDay)}}}getStyles(){return`
|
|
740
740
|
:host {
|
|
741
741
|
display: flex;
|
|
742
742
|
flex-direction: column;
|
|
@@ -950,7 +950,7 @@ var Y=Object.defineProperty;var N=(u,e,t)=>e in u?Y(u,e,{enumerable:!0,configura
|
|
|
950
950
|
data-event-id="${e.id}">
|
|
951
951
|
${T.escapeHTML(e.title)}
|
|
952
952
|
</div>
|
|
953
|
-
`}renderNowIndicator(){const e=new Date;return`<div class="now-indicator" style="top: ${e.getHours()*60+e.getMinutes()}px"></div>`}afterRender(){const e=this.$("#scroll-container");e&&!this._scrolled&&(e.scrollTop=8*60-50,this._scrolled=!0),this.$$("[data-event-id]").forEach(s=>{
|
|
953
|
+
`}renderNowIndicator(){const e=new Date;return`<div class="now-indicator" style="top: ${e.getHours()*60+e.getMinutes()}px"></div>`}afterRender(){const e=this.$("#scroll-container");e&&!this._scrolled&&(e.scrollTop=8*60-50,this._scrolled=!0),this.$$("[data-event-id]").forEach(s=>{this.addListener(s,"click",i=>{i.stopPropagation();const a=i.currentTarget.dataset.eventId,n=this.stateManager.getEvents().find(r=>r.id===a);n&&this.emit("event-click",{event:n})})});const t=this.$(".day-column");t&&this.addListener(t,"click",s=>{const i=s.currentTarget,a=this.$("#scroll-container"),n=i.getBoundingClientRect(),r=s.clientY-n.top+(a?a.scrollTop:0),o=new Date(i.dataset.date);o.setHours(Math.floor(r/60),Math.floor(r%60),0,0),this.stateManager.selectDate(o),this.emit("day-click",{date:o})})}unmount(){this.unsubscribe&&this.unsubscribe()}}class ae extends C{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,s){e==="open"&&(s!==null?this.open():this.close())}getStyles(){return`
|
|
954
954
|
${D.getBaseStyles()}
|
|
955
955
|
${D.getButtonStyles()}
|
|
956
956
|
|
|
@@ -1172,7 +1172,7 @@ var Y=Object.defineProperty;var N=(u,e,t)=>e in u?Y(u,e,{enumerable:!0,configura
|
|
|
1172
1172
|
<button class="fc-btn fc-btn-primary" id="save-btn">Save Event</button>
|
|
1173
1173
|
</footer>
|
|
1174
1174
|
</div>
|
|
1175
|
-
`}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.$("#close-x")
|
|
1175
|
+
`}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",t=>{this._formData.color=t.currentTarget.dataset.color,this.updateColorSelection()})}),this.addListener(this,"click",e=>{e.target===this&&this.close()}),this._handleKeyDown=e=>{e.key==="Escape"&&this.hasAttribute("open")&&this.close()},window.addEventListener("keydown",this._handleKeyDown)}updateColorSelection(){this.colorContainer.querySelectorAll(".color-btn").forEach(t=>{const s=t.dataset.color===this._formData.color;t.classList.toggle("selected",s),t.setAttribute("aria-checked",s?"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=T.trapFocus(this.modalContent))}close(){this.removeAttribute("open"),this._cleanupFocusTrap&&(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);const 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;const 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){const t=o=>String(o).padStart(2,"0"),s=e.getFullYear(),i=t(e.getMonth()+1),a=t(e.getDate()),n=t(e.getHours()),r=t(e.getMinutes());return`${s}-${i}-${a}T${n}:${r}`}unmount(){this._cleanupFocusTrap&&this._cleanupFocusTrap(),window.removeEventListener("keydown",this._handleKeyDown)}}customElements.get("force-calendar-event-form")||customElements.define("force-calendar-event-form",ae);customElements.get("force-calendar-month")||customElements.define("force-calendar-month",te);customElements.get("force-calendar-week")||customElements.define("force-calendar-week",se);customElements.get("force-calendar-day")||customElements.define("force-calendar-day",ie);class ne extends C{static get observedAttributes(){return["view","date","locale","timezone","week-starts-on","height"]}constructor(){super(),this.stateManager=null,this.currentView=null}initialize(){const 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 ee(e),this.stateManager.subscribe(this.handleStateChange.bind(this)),this.setupEventListeners()}setupEventListeners(){g.on("navigation:*",(e,t)=>{this.emit("calendar-navigate",{action:t.split(":")[1],...e})}),g.on("view:changed",e=>{this.emit("calendar-view-change",e)}),g.on("event:*",(e,t)=>{this.emit(`calendar-event-${t.split(":")[1]}`,e)}),g.on("date:selected",e=>{this.emit("calendar-date-select",e)})}handleStateChange(e,t){e.view!==(t==null?void 0:t.view)&&(this.currentView=e.view),this.render()}mount(){super.mount(),this.loadView(this.stateManager.getView())}loadView(e){this.currentView=e,this.render()}getStyles(){const e=this.getAttribute("height")||"800px";return`
|
|
1176
1176
|
${D.getBaseStyles()}
|
|
1177
1177
|
${D.getButtonStyles()}
|
|
1178
1178
|
${D.getGridStyles()}
|
package/dist/index.html
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forcecalendar/interface",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Official interface layer for forceCalendar Core - Enterprise calendar components",
|
|
6
6
|
"main": "dist/force-calendar-interface.js",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"dev": "vite",
|
|
15
15
|
"build": "vite build",
|
|
16
16
|
"preview": "vite preview",
|
|
17
|
-
"test": "
|
|
17
|
+
"test": "jest --testTimeout=10000"
|
|
18
18
|
},
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
@@ -40,6 +40,11 @@
|
|
|
40
40
|
"@forcecalendar/core": "^0.3.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
+
"@babel/core": "^7.28.5",
|
|
44
|
+
"@babel/preset-env": "^7.28.5",
|
|
45
|
+
"babel-jest": "^30.2.0",
|
|
46
|
+
"jest": "^30.2.0",
|
|
47
|
+
"jest-environment-jsdom": "^30.2.0",
|
|
43
48
|
"vite": "^5.0.0"
|
|
44
49
|
}
|
|
45
50
|
}
|
|
@@ -283,20 +283,20 @@ export class EventForm extends BaseComponent {
|
|
|
283
283
|
this.titleGroup = this.$('#title-group');
|
|
284
284
|
this.endGroup = this.$('#end-group');
|
|
285
285
|
|
|
286
|
-
// Event Listeners
|
|
287
|
-
this.$('#close-x')
|
|
288
|
-
this.$('#cancel-btn')
|
|
289
|
-
this.$('#save-btn')
|
|
286
|
+
// Event Listeners using addListener for automatic cleanup
|
|
287
|
+
this.addListener(this.$('#close-x'), 'click', () => this.close());
|
|
288
|
+
this.addListener(this.$('#cancel-btn'), 'click', () => this.close());
|
|
289
|
+
this.addListener(this.$('#save-btn'), 'click', () => this.save());
|
|
290
290
|
|
|
291
291
|
this.colorContainer.querySelectorAll('.color-btn').forEach(btn => {
|
|
292
|
-
|
|
293
|
-
this._formData.color = e.
|
|
292
|
+
this.addListener(btn, 'click', (e) => {
|
|
293
|
+
this._formData.color = e.currentTarget.dataset.color;
|
|
294
294
|
this.updateColorSelection();
|
|
295
295
|
});
|
|
296
296
|
});
|
|
297
297
|
|
|
298
298
|
// Close on backdrop click
|
|
299
|
-
this.
|
|
299
|
+
this.addListener(this, 'click', (e) => {
|
|
300
300
|
if (e.target === this) this.close();
|
|
301
301
|
});
|
|
302
302
|
|
|
@@ -319,7 +319,9 @@ export class EventForm extends BaseComponent {
|
|
|
319
319
|
}
|
|
320
320
|
|
|
321
321
|
open(initialDate = new Date()) {
|
|
322
|
-
this.
|
|
322
|
+
if (!this.hasAttribute('open')) {
|
|
323
|
+
this.setAttribute('open', '');
|
|
324
|
+
}
|
|
323
325
|
|
|
324
326
|
// Reset errors
|
|
325
327
|
this.titleGroup.classList.remove('has-error');
|
|
@@ -365,9 +365,9 @@ export class DayView extends BaseComponent {
|
|
|
365
365
|
}
|
|
366
366
|
|
|
367
367
|
this.$$('[data-event-id]').forEach(el => {
|
|
368
|
-
|
|
368
|
+
this.addListener(el, 'click', (e) => {
|
|
369
369
|
e.stopPropagation();
|
|
370
|
-
const eventId =
|
|
370
|
+
const eventId = e.currentTarget.dataset.eventId;
|
|
371
371
|
const event = this.stateManager.getEvents().find(ev => ev.id === eventId);
|
|
372
372
|
if (event) this.emit('event-click', { event });
|
|
373
373
|
});
|
|
@@ -375,12 +375,13 @@ export class DayView extends BaseComponent {
|
|
|
375
375
|
|
|
376
376
|
const dayCol = this.$('.day-column');
|
|
377
377
|
if (dayCol) {
|
|
378
|
-
|
|
378
|
+
this.addListener(dayCol, 'click', (e) => {
|
|
379
|
+
const col = e.currentTarget;
|
|
379
380
|
const container = this.$('#scroll-container');
|
|
380
|
-
const rect =
|
|
381
|
+
const rect = col.getBoundingClientRect();
|
|
381
382
|
const y = e.clientY - rect.top + (container ? container.scrollTop : 0);
|
|
382
383
|
|
|
383
|
-
const date = new Date(
|
|
384
|
+
const date = new Date(col.dataset.date);
|
|
384
385
|
date.setHours(Math.floor(y / 60), Math.floor(y % 60), 0, 0);
|
|
385
386
|
|
|
386
387
|
this.stateManager.selectDate(date);
|
|
@@ -480,17 +480,17 @@ export class MonthView extends BaseComponent {
|
|
|
480
480
|
afterRender() {
|
|
481
481
|
// Add click handlers for days
|
|
482
482
|
this.$$('.month-day').forEach(dayEl => {
|
|
483
|
-
|
|
483
|
+
this.addListener(dayEl, 'click', this.handleDayClick);
|
|
484
484
|
});
|
|
485
485
|
|
|
486
486
|
// Add click handlers for events
|
|
487
487
|
this.$$('.event-item').forEach(eventEl => {
|
|
488
|
-
|
|
488
|
+
this.addListener(eventEl, 'click', this.handleEventClick);
|
|
489
489
|
});
|
|
490
490
|
|
|
491
491
|
// Add click handlers for "more events"
|
|
492
492
|
this.$$('.more-events').forEach(moreEl => {
|
|
493
|
-
|
|
493
|
+
this.addListener(moreEl, 'click', this.handleMoreClick);
|
|
494
494
|
});
|
|
495
495
|
}
|
|
496
496
|
|
|
@@ -373,21 +373,22 @@ export class WeekView extends BaseComponent {
|
|
|
373
373
|
}
|
|
374
374
|
|
|
375
375
|
this.$$('[data-event-id]').forEach(el => {
|
|
376
|
-
|
|
376
|
+
this.addListener(el, 'click', (e) => {
|
|
377
377
|
e.stopPropagation();
|
|
378
|
-
const eventId =
|
|
378
|
+
const eventId = e.currentTarget.dataset.eventId;
|
|
379
379
|
const event = this.stateManager.getEvents().find(ev => ev.id === eventId);
|
|
380
380
|
if (event) this.emit('event-click', { event });
|
|
381
381
|
});
|
|
382
382
|
});
|
|
383
383
|
|
|
384
384
|
this.$$('.day-column').forEach(el => {
|
|
385
|
-
|
|
385
|
+
this.addListener(el, 'click', (e) => {
|
|
386
|
+
const col = e.currentTarget;
|
|
386
387
|
const container = this.$('#scroll-container');
|
|
387
|
-
const rect =
|
|
388
|
+
const rect = col.getBoundingClientRect();
|
|
388
389
|
const y = e.clientY - rect.top + (container ? container.scrollTop : 0);
|
|
389
390
|
|
|
390
|
-
const date = new Date(
|
|
391
|
+
const date = new Date(col.dataset.date);
|
|
391
392
|
date.setHours(Math.floor(y / 60), Math.floor(y % 60), 0, 0);
|
|
392
393
|
|
|
393
394
|
this.stateManager.selectDate(date);
|
|
@@ -87,9 +87,9 @@ export class BaseComponent extends HTMLElement {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// Event handling
|
|
90
|
-
|
|
90
|
+
addListener(element, event, handler) {
|
|
91
91
|
if (!element || !event || !handler) {
|
|
92
|
-
console.warn('
|
|
92
|
+
console.warn('addListener called with invalid parameters', { element, event, handler });
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
95
|
const boundHandler = handler.bind(this);
|