@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/dist/force-calendar-interface.esm.js +290 -304
- package/dist/force-calendar-interface.esm.js.map +1 -1
- package/dist/force-calendar-interface.umd.js +34 -34
- package/dist/force-calendar-interface.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ForceCalendar.js +19 -41
- package/src/core/StateManager.js +27 -23
package/package.json
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
87
|
+
bus.on('event:add', data => {
|
|
81
88
|
forwardEventAction('add', data);
|
|
82
89
|
})
|
|
83
90
|
);
|
|
84
91
|
this._busUnsubscribers.push(
|
|
85
|
-
|
|
92
|
+
bus.on('event:update', data => {
|
|
86
93
|
forwardEventAction('update', data);
|
|
87
94
|
})
|
|
88
95
|
);
|
|
89
96
|
this._busUnsubscribers.push(
|
|
90
|
-
|
|
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
|
-
|
|
107
|
+
bus.on('event:added', data => {
|
|
101
108
|
this.emit('calendar-event-added', data);
|
|
102
109
|
})
|
|
103
110
|
);
|
|
104
111
|
this._busUnsubscribers.push(
|
|
105
|
-
|
|
112
|
+
bus.on('event:updated', data => {
|
|
106
113
|
this.emit('calendar-event-updated', data);
|
|
107
114
|
})
|
|
108
115
|
);
|
|
109
116
|
this._busUnsubscribers.push(
|
|
110
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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) {
|
package/src/core/StateManager.js
CHANGED
|
@@ -6,10 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { Calendar } from '@forcecalendar/core';
|
|
9
|
-
import
|
|
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
|
|