@forcecalendar/interface 1.0.15 → 1.0.16

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.15",
3
+ "version": "1.0.16",
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",
@@ -39,6 +39,32 @@ class StateManager {
39
39
  this.subscribe = this.subscribe.bind(this);
40
40
  this.unsubscribe = this.unsubscribe.bind(this);
41
41
  this.setState = this.setState.bind(this);
42
+
43
+ // Initial sync of events from Core (in case events were pre-loaded)
44
+ this._syncEventsFromCore({ silent: true });
45
+ }
46
+
47
+ /**
48
+ * Sync state.events from Core calendar (single source of truth)
49
+ * This ensures state.events always matches Core's event store
50
+ */
51
+ _syncEventsFromCore(options = {}) {
52
+ const coreEvents = this.calendar.getEvents() || [];
53
+ // Only update if different to avoid unnecessary re-renders
54
+ if (this.state.events.length !== coreEvents.length ||
55
+ !this._eventsMatch(this.state.events, coreEvents)) {
56
+ this.setState({ events: [...coreEvents] }, options);
57
+ }
58
+ return coreEvents;
59
+ }
60
+
61
+ /**
62
+ * Check if two event arrays have the same events (by id)
63
+ */
64
+ _eventsMatch(arr1, arr2) {
65
+ if (arr1.length !== arr2.length) return false;
66
+ const ids1 = new Set(arr1.map(e => e.id));
67
+ return arr2.every(e => ids1.has(e.id));
42
68
  }
43
69
 
44
70
  // State management
@@ -150,14 +176,16 @@ class StateManager {
150
176
  eventBus.emit('event:error', { action: 'add', event, error: 'Failed to add event' });
151
177
  return null;
152
178
  }
153
- // Create new array to avoid mutation before setState
154
- const newEvents = [...this.state.events, addedEvent];
155
- this.setState({ events: newEvents });
179
+ // Sync from Core to ensure consistency (single source of truth)
180
+ this._syncEventsFromCore();
156
181
  eventBus.emit('event:added', { event: addedEvent });
157
182
  return addedEvent;
158
183
  }
159
184
 
160
185
  updateEvent(eventId, updates) {
186
+ // First, ensure state is in sync with Core (recover from any prior desync)
187
+ this._syncEventsFromCore({ silent: true });
188
+
161
189
  const event = this.calendar.updateEvent(eventId, updates);
162
190
  if (!event) {
163
191
  console.error(`Failed to update event: ${eventId}`);
@@ -165,37 +193,39 @@ class StateManager {
165
193
  return null;
166
194
  }
167
195
 
168
- const index = this.state.events.findIndex(e => e.id === eventId);
169
- if (index === -1) {
170
- console.error(`Event ${eventId} not found in state`);
171
- eventBus.emit('event:error', { action: 'update', eventId, error: 'Event not found in state' });
172
- return null;
173
- }
174
-
175
- // Create new array to avoid mutation before setState
176
- const newEvents = [...this.state.events];
177
- newEvents[index] = event;
178
- this.setState({ events: newEvents });
196
+ // Sync from Core to ensure consistency (single source of truth)
197
+ this._syncEventsFromCore();
179
198
  eventBus.emit('event:updated', { event });
180
199
  return event;
181
200
  }
182
201
 
183
202
  deleteEvent(eventId) {
203
+ // First, ensure state is in sync with Core (recover from any prior desync)
204
+ this._syncEventsFromCore({ silent: true });
205
+
184
206
  const deleted = this.calendar.removeEvent(eventId);
185
207
  if (!deleted) {
186
208
  console.error(`Failed to delete event: ${eventId}`);
187
209
  eventBus.emit('event:error', { action: 'delete', eventId, error: 'Event not found' });
188
210
  return false;
189
211
  }
190
- // Create new array to avoid mutation before setState
191
- const newEvents = this.state.events.filter(e => e.id !== eventId);
192
- this.setState({ events: newEvents });
212
+ // Sync from Core to ensure consistency (single source of truth)
213
+ this._syncEventsFromCore();
193
214
  eventBus.emit('event:deleted', { eventId });
194
215
  return true;
195
216
  }
196
217
 
197
218
  getEvents() {
198
- return this.calendar.getEvents();
219
+ // Return from Core (source of truth)
220
+ return this.calendar.getEvents() || [];
221
+ }
222
+
223
+ /**
224
+ * Force sync state.events from Core calendar
225
+ * Use this if you've modified events directly on the Core calendar
226
+ */
227
+ syncEvents() {
228
+ return this._syncEventsFromCore();
199
229
  }
200
230
 
201
231
  getEventsForDate(date) {