@forcecalendar/interface 1.0.51 → 1.0.53

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forcecalendar/interface",
3
- "version": "1.0.51",
3
+ "version": "1.0.53",
4
4
  "type": "module",
5
5
  "description": "Official interface layer for forceCalendar Core - Enterprise calendar components",
6
6
  "main": "dist/force-calendar-interface.umd.js",
@@ -18,6 +18,7 @@ export class BaseViewRenderer {
18
18
  this.stateManager = stateManager;
19
19
  this._listeners = [];
20
20
  this._scrolled = false;
21
+ this._nowIndicatorTimer = null;
21
22
  }
22
23
 
23
24
  /**
@@ -36,6 +37,10 @@ export class BaseViewRenderer {
36
37
  element.removeEventListener(event, handler);
37
38
  });
38
39
  this._listeners = [];
40
+ if (this._nowIndicatorTimer) {
41
+ clearInterval(this._nowIndicatorTimer);
42
+ this._nowIndicatorTimer = null;
43
+ }
39
44
  }
40
45
 
41
46
  /**
@@ -137,6 +142,23 @@ export class BaseViewRenderer {
137
142
  return `<div class="fc-now-indicator" style="position: absolute; left: 0; right: 0; top: ${minutes}px; height: 2px; background: var(--fc-danger-color); z-index: 15; pointer-events: none;"></div>`;
138
143
  }
139
144
 
145
+ /**
146
+ * Start a timer that updates the now indicator position every 60 seconds.
147
+ * Call this after render() in day/week views that show a now indicator.
148
+ */
149
+ startNowIndicatorTimer() {
150
+ if (this._nowIndicatorTimer) {
151
+ clearInterval(this._nowIndicatorTimer);
152
+ }
153
+ this._nowIndicatorTimer = setInterval(() => {
154
+ const indicator = this.container.querySelector('.fc-now-indicator');
155
+ if (indicator) {
156
+ const now = new Date();
157
+ indicator.style.top = `${now.getHours() * 60 + now.getMinutes()}px`;
158
+ }
159
+ }, 60000);
160
+ }
161
+
140
162
  /**
141
163
  * Compute overlap layout columns for a list of timed events.
142
164
  * Returns a Map of event.id -> { column, totalColumns }.
@@ -157,7 +179,9 @@ export class BaseViewRenderer {
157
179
  });
158
180
 
159
181
  // Sort by start time, then by longer duration first
160
- entries.sort((a, b) => a.startMin - b.startMin || (b.endMin - b.startMin) - (a.endMin - a.startMin));
182
+ entries.sort(
183
+ (a, b) => a.startMin - b.startMin || b.endMin - b.startMin - (a.endMin - a.startMin)
184
+ );
161
185
 
162
186
  // Assign columns greedily
163
187
  const columns = []; // each column tracks the end time of its last event
@@ -31,6 +31,7 @@ export class DayViewRenderer extends BaseViewRenderer {
31
31
  this.container.innerHTML = html;
32
32
  this._attachEventHandlers();
33
33
  this._scrollToCurrentTime();
34
+ this.startNowIndicatorTimer();
34
35
  }
35
36
 
36
37
  _renderDayView(viewData, _config) {
@@ -172,7 +173,11 @@ export class DayViewRenderer extends BaseViewRenderer {
172
173
  <!-- Timed events -->
173
174
  ${(() => {
174
175
  const layout = this.computeOverlapLayout(timedEvents);
175
- return timedEvents.map(evt => this.renderTimedEvent(evt, { compact: false, overlapLayout: layout })).join('');
176
+ return timedEvents
177
+ .map(evt =>
178
+ this.renderTimedEvent(evt, { compact: false, overlapLayout: layout })
179
+ )
180
+ .join('');
176
181
  })()}
177
182
  </div>
178
183
  `;
@@ -187,7 +192,11 @@ export class DayViewRenderer extends BaseViewRenderer {
187
192
  const date = new Date(dayEl.dataset.date);
188
193
  const scrollContainer = this.container.querySelector('#day-scroll-container');
189
194
  const gridTop = dayEl.offsetTop;
190
- const y = e.clientY - dayEl.getBoundingClientRect().top + (scrollContainer ? scrollContainer.scrollTop : 0) - gridTop;
195
+ const y =
196
+ e.clientY -
197
+ dayEl.getBoundingClientRect().top +
198
+ (scrollContainer ? scrollContainer.scrollTop : 0) -
199
+ gridTop;
191
200
 
192
201
  // Calculate time from click position within the 1440px time grid
193
202
  const clampedY = Math.max(0, Math.min(y + gridTop, this.totalHeight));
@@ -31,6 +31,7 @@ export class WeekViewRenderer extends BaseViewRenderer {
31
31
  this.container.innerHTML = html;
32
32
  this._attachEventHandlers();
33
33
  this._scrollToCurrentTime();
34
+ this.startNowIndicatorTimer();
34
35
  }
35
36
 
36
37
  _renderWeekView(viewData, _config) {
@@ -151,7 +152,11 @@ export class WeekViewRenderer extends BaseViewRenderer {
151
152
  <!-- Timed events -->
152
153
  ${(() => {
153
154
  const layout = this.computeOverlapLayout(day.timedEvents);
154
- return day.timedEvents.map(evt => this.renderTimedEvent(evt, { compact: true, overlapLayout: layout })).join('');
155
+ return day.timedEvents
156
+ .map(evt =>
157
+ this.renderTimedEvent(evt, { compact: true, overlapLayout: layout })
158
+ )
159
+ .join('');
155
160
  })()}
156
161
  </div>
157
162
  `;
@@ -166,7 +171,11 @@ export class WeekViewRenderer extends BaseViewRenderer {
166
171
  const date = new Date(dayEl.dataset.date);
167
172
  const scrollContainer = this.container.querySelector('#week-scroll-container');
168
173
  const gridTop = dayEl.offsetTop;
169
- const y = e.clientY - dayEl.getBoundingClientRect().top + (scrollContainer ? scrollContainer.scrollTop : 0) - gridTop;
174
+ const y =
175
+ e.clientY -
176
+ dayEl.getBoundingClientRect().top +
177
+ (scrollContainer ? scrollContainer.scrollTop : 0) -
178
+ gridTop;
170
179
 
171
180
  // Calculate time from click position within the 1440px time grid
172
181
  const clampedY = Math.max(0, Math.min(y + gridTop, this.totalHeight));