@forcecalendar/interface 1.0.41 → 1.0.43

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.41",
3
+ "version": "1.0.43",
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",
@@ -6,7 +6,6 @@
6
6
 
7
7
  import { BaseComponent } from '../core/BaseComponent.js';
8
8
  import StateManager from '../core/StateManager.js';
9
- import eventBus from '../core/EventBus.js';
10
9
  import { StyleUtils } from '../utils/StyleUtils.js';
11
10
  import { DateUtils } from '../utils/DateUtils.js';
12
11
  import { DOMUtils } from '../utils/DOMUtils.js';
@@ -20,6 +19,12 @@ import { DayViewRenderer } from '../renderers/DayViewRenderer.js';
20
19
  import './EventForm.js';
21
20
 
22
21
  export class ForceCalendar extends BaseComponent {
22
+ static RENDERERS = {
23
+ month: MonthViewRenderer,
24
+ week: WeekViewRenderer,
25
+ day: DayViewRenderer
26
+ };
27
+
23
28
  static get observedAttributes() {
24
29
  return ['view', 'date', 'locale', 'timezone', 'week-starts-on', 'height'];
25
30
  }
@@ -57,16 +62,18 @@ export class ForceCalendar extends BaseComponent {
57
62
  this._busUnsubscribers.forEach(unsub => unsub());
58
63
  this._busUnsubscribers = [];
59
64
 
65
+ const bus = this.stateManager.eventBus;
66
+
60
67
  // Navigation events
61
68
  this._busUnsubscribers.push(
62
- eventBus.on('navigation:*', (data, event) => {
69
+ bus.on('navigation:*', (data, event) => {
63
70
  this.emit('calendar-navigate', { action: event.split(':')[1], ...data });
64
71
  })
65
72
  );
66
73
 
67
74
  // View change events
68
75
  this._busUnsubscribers.push(
69
- eventBus.on('view:changed', data => {
76
+ bus.on('view:changed', data => {
70
77
  this.emit('calendar-view-change', data);
71
78
  })
72
79
  );
@@ -77,17 +84,17 @@ export class ForceCalendar extends BaseComponent {
77
84
 
78
85
  // Event management events (canonical + backward-compatible aliases)
79
86
  this._busUnsubscribers.push(
80
- eventBus.on('event:add', data => {
87
+ bus.on('event:add', data => {
81
88
  forwardEventAction('add', data);
82
89
  })
83
90
  );
84
91
  this._busUnsubscribers.push(
85
- eventBus.on('event:update', data => {
92
+ bus.on('event:update', data => {
86
93
  forwardEventAction('update', data);
87
94
  })
88
95
  );
89
96
  this._busUnsubscribers.push(
90
- eventBus.on('event:remove', data => {
97
+ bus.on('event:remove', data => {
91
98
  forwardEventAction('remove', data);
92
99
  })
93
100
  );
@@ -97,24 +104,24 @@ export class ForceCalendar extends BaseComponent {
97
104
  // consumers that care about the distinction can subscribe to it without
98
105
  // receiving the generic event a second time.
99
106
  this._busUnsubscribers.push(
100
- eventBus.on('event:added', data => {
107
+ bus.on('event:added', data => {
101
108
  this.emit('calendar-event-added', data);
102
109
  })
103
110
  );
104
111
  this._busUnsubscribers.push(
105
- eventBus.on('event:updated', data => {
112
+ bus.on('event:updated', data => {
106
113
  this.emit('calendar-event-updated', data);
107
114
  })
108
115
  );
109
116
  this._busUnsubscribers.push(
110
- eventBus.on('event:deleted', data => {
117
+ bus.on('event:deleted', data => {
111
118
  this.emit('calendar-event-deleted', data);
112
119
  })
113
120
  );
114
121
 
115
122
  // Date selection events
116
123
  this._busUnsubscribers.push(
117
- eventBus.on('date:selected', data => {
124
+ bus.on('date:selected', data => {
118
125
  this.emit('calendar-date-select', data);
119
126
  })
120
127
  );
@@ -203,13 +210,7 @@ export class ForceCalendar extends BaseComponent {
203
210
 
204
211
  // Create new view using renderer classes
205
212
  try {
206
- const renderers = {
207
- month: MonthViewRenderer,
208
- week: WeekViewRenderer,
209
- day: DayViewRenderer
210
- };
211
-
212
- const RendererClass = renderers[this.currentView] || MonthViewRenderer;
213
+ const RendererClass = ForceCalendar.RENDERERS[this.currentView] || MonthViewRenderer;
213
214
  const viewRenderer = new RendererClass(container, this.stateManager);
214
215
  viewRenderer._viewType = this.currentView;
215
216
  this._currentViewInstance = viewRenderer;
@@ -746,13 +747,7 @@ export class ForceCalendar extends BaseComponent {
746
747
 
747
748
  // Create view renderer using the appropriate renderer class
748
749
  try {
749
- const renderers = {
750
- month: MonthViewRenderer,
751
- week: WeekViewRenderer,
752
- day: DayViewRenderer
753
- };
754
-
755
- const RendererClass = renderers[this.currentView] || MonthViewRenderer;
750
+ const RendererClass = ForceCalendar.RENDERERS[this.currentView] || MonthViewRenderer;
756
751
  const viewRenderer = new RendererClass(container, this.stateManager);
757
752
  viewRenderer._viewType = this.currentView;
758
753
  this._currentViewInstance = viewRenderer;
@@ -811,23 +806,6 @@ export class ForceCalendar extends BaseComponent {
811
806
  this._hasRendered = true;
812
807
  }
813
808
 
814
- /**
815
- * Create a view renderer instance for the given view type
816
- * Uses pure JavaScript renderer classes for Salesforce Locker Service compatibility
817
- * @param {string} viewName - 'month', 'week', or 'day'
818
- * @returns {BaseViewRenderer} Renderer instance
819
- */
820
- _createViewRenderer(viewName) {
821
- const renderers = {
822
- month: MonthViewRenderer,
823
- week: WeekViewRenderer,
824
- day: DayViewRenderer
825
- };
826
-
827
- const RendererClass = renderers[viewName] || MonthViewRenderer;
828
- return new RendererClass(null, null); // Container and stateManager set after creation
829
- }
830
-
831
809
  handleNavigation(event) {
832
810
  const action = event.currentTarget.dataset.action;
833
811
  switch (action) {
@@ -6,10 +6,14 @@
6
6
  */
7
7
 
8
8
  import { Calendar } from '@forcecalendar/core';
9
- import eventBus from './EventBus.js';
9
+ import { EventBus } from './EventBus.js';
10
10
 
11
11
  class StateManager {
12
12
  constructor(config = {}) {
13
+ // Each StateManager gets its own EventBus to prevent cross-instance
14
+ // contamination when multiple calendars exist on the same page.
15
+ this.eventBus = new EventBus();
16
+
13
17
  // Initialize Core Calendar instance
14
18
  this.calendar = new Calendar({
15
19
  view: config.view || 'month',
@@ -162,7 +166,7 @@ class StateManager {
162
166
  const changedKeys = Object.keys(newState).filter(key => oldState[key] !== newState[key]);
163
167
 
164
168
  changedKeys.forEach(key => {
165
- eventBus.emit(`state:${key}:changed`, {
169
+ this.eventBus.emit(`state:${key}:changed`, {
166
170
  oldValue: oldState[key],
167
171
  newValue: newState[key],
168
172
  state: newState
@@ -170,7 +174,7 @@ class StateManager {
170
174
  });
171
175
 
172
176
  if (changedKeys.length > 0) {
173
- eventBus.emit('state:changed', { oldState, newState, changedKeys });
177
+ this.eventBus.emit('state:changed', { oldState, newState, changedKeys });
174
178
  }
175
179
  }
176
180
 
@@ -178,7 +182,7 @@ class StateManager {
178
182
  setView(view) {
179
183
  this.calendar.setView(view);
180
184
  this.setState({ view });
181
- eventBus.emit('view:changed', { view });
185
+ this.eventBus.emit('view:changed', { view });
182
186
  }
183
187
 
184
188
  getView() {
@@ -188,7 +192,7 @@ class StateManager {
188
192
  setDate(date) {
189
193
  this.calendar.goToDate(date);
190
194
  this.setState({ currentDate: this.calendar.getCurrentDate() });
191
- eventBus.emit('date:changed', { date: this.state.currentDate });
195
+ this.eventBus.emit('date:changed', { date: this.state.currentDate });
192
196
  }
193
197
 
194
198
  getCurrentDate() {
@@ -199,25 +203,25 @@ class StateManager {
199
203
  next() {
200
204
  this.calendar.next();
201
205
  this.setState({ currentDate: this.calendar.getCurrentDate() });
202
- eventBus.emit('navigation:next', { date: this.state.currentDate });
206
+ this.eventBus.emit('navigation:next', { date: this.state.currentDate });
203
207
  }
204
208
 
205
209
  previous() {
206
210
  this.calendar.previous();
207
211
  this.setState({ currentDate: this.calendar.getCurrentDate() });
208
- eventBus.emit('navigation:previous', { date: this.state.currentDate });
212
+ this.eventBus.emit('navigation:previous', { date: this.state.currentDate });
209
213
  }
210
214
 
211
215
  today() {
212
216
  this.calendar.today();
213
217
  this.setState({ currentDate: this.calendar.getCurrentDate() });
214
- eventBus.emit('navigation:today', { date: this.state.currentDate });
218
+ this.eventBus.emit('navigation:today', { date: this.state.currentDate });
215
219
  }
216
220
 
217
221
  goToDate(date) {
218
222
  this.calendar.goToDate(date);
219
223
  this.setState({ currentDate: this.calendar.getCurrentDate() });
220
- eventBus.emit('navigation:goto', { date: this.state.currentDate });
224
+ this.eventBus.emit('navigation:goto', { date: this.state.currentDate });
221
225
  }
222
226
 
223
227
  // Event management
@@ -225,13 +229,13 @@ class StateManager {
225
229
  const addedEvent = this.calendar.addEvent(event);
226
230
  if (!addedEvent) {
227
231
  console.error('Failed to add event to calendar');
228
- eventBus.emit('event:error', { action: 'add', event, error: 'Failed to add event' });
232
+ this.eventBus.emit('event:error', { action: 'add', event, error: 'Failed to add event' });
229
233
  return null;
230
234
  }
231
235
  // Sync from Core to ensure consistency (single source of truth)
232
236
  this._syncEventsFromCore();
233
- eventBus.emit('event:add', { event: addedEvent });
234
- eventBus.emit('event:added', { event: addedEvent });
237
+ this.eventBus.emit('event:add', { event: addedEvent });
238
+ this.eventBus.emit('event:added', { event: addedEvent });
235
239
  return addedEvent;
236
240
  }
237
241
 
@@ -242,7 +246,7 @@ class StateManager {
242
246
  const event = this.calendar.updateEvent(eventId, updates);
243
247
  if (!event) {
244
248
  console.error(`Failed to update event: ${eventId}`);
245
- eventBus.emit('event:error', {
249
+ this.eventBus.emit('event:error', {
246
250
  action: 'update',
247
251
  eventId,
248
252
  updates,
@@ -254,8 +258,8 @@ class StateManager {
254
258
  // Force sync from Core — IDs are unchanged after an update so the
255
259
  // ID-only guard in _eventsMatch would otherwise skip the state update
256
260
  this._syncEventsFromCore({ force: true });
257
- eventBus.emit('event:update', { event });
258
- eventBus.emit('event:updated', { event });
261
+ this.eventBus.emit('event:update', { event });
262
+ this.eventBus.emit('event:updated', { event });
259
263
  return event;
260
264
  }
261
265
 
@@ -266,13 +270,13 @@ class StateManager {
266
270
  const deleted = this.calendar.removeEvent(eventId);
267
271
  if (!deleted) {
268
272
  console.error(`Failed to delete event: ${eventId}`);
269
- eventBus.emit('event:error', { action: 'delete', eventId, error: 'Event not found' });
273
+ this.eventBus.emit('event:error', { action: 'delete', eventId, error: 'Event not found' });
270
274
  return false;
271
275
  }
272
276
  // Sync from Core to ensure consistency (single source of truth)
273
277
  this._syncEventsFromCore();
274
- eventBus.emit('event:remove', { eventId });
275
- eventBus.emit('event:deleted', { eventId });
278
+ this.eventBus.emit('event:remove', { eventId });
279
+ this.eventBus.emit('event:deleted', { eventId });
276
280
  return true;
277
281
  }
278
282
 
@@ -350,7 +354,7 @@ class StateManager {
350
354
  // Selection management
351
355
  selectEvent(event) {
352
356
  this.setState({ selectedEvent: event });
353
- eventBus.emit('event:selected', { event });
357
+ this.eventBus.emit('event:selected', { event });
354
358
  }
355
359
 
356
360
  selectEventById(eventId) {
@@ -362,17 +366,17 @@ class StateManager {
362
366
 
363
367
  deselectEvent() {
364
368
  this.setState({ selectedEvent: null });
365
- eventBus.emit('event:deselected', {});
369
+ this.eventBus.emit('event:deselected', {});
366
370
  }
367
371
 
368
372
  selectDate(date) {
369
373
  this.setState({ selectedDate: date });
370
- eventBus.emit('date:selected', { date });
374
+ this.eventBus.emit('date:selected', { date });
371
375
  }
372
376
 
373
377
  deselectDate() {
374
378
  this.setState({ selectedDate: null });
375
- eventBus.emit('date:deselected', {});
379
+ this.eventBus.emit('date:deselected', {});
376
380
  }
377
381
 
378
382
  // Utility methods
@@ -401,7 +405,7 @@ class StateManager {
401
405
  setError(error) {
402
406
  this.setState({ error });
403
407
  if (error) {
404
- eventBus.emit('error', { error });
408
+ this.eventBus.emit('error', { error });
405
409
  }
406
410
  }
407
411