@forcecalendar/core 2.1.69 → 2.2.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/core/calendar/Calendar.js +5 -5
- package/core/conflicts/ConflictDetector.js +5 -5
- package/core/events/Event.js +17 -17
- package/core/events/EventStore.js +16 -16
- package/core/events/RecurrenceEngine.js +123 -29
- package/core/ics/ICSHandler.js +5 -3
- package/core/index.js +5 -1
- package/core/state/StateManager.js +3 -3
- package/core/timezone/TimezoneManager.js +91 -53
- package/core/types.js +17 -14
- package/package.json +40 -20
- package/types/calendar/Calendar.d.ts +287 -0
- package/types/calendar/DateUtils.d.ts +298 -0
- package/types/conflicts/ConflictDetector.d.ts +103 -0
- package/types/events/Event.d.ts +329 -0
- package/types/events/EventStore.d.ts +341 -0
- package/types/events/RRuleParser.d.ts +60 -0
- package/types/events/RecurrenceEngine.d.ts +128 -0
- package/types/events/RecurrenceEngineV2.d.ts +140 -0
- package/types/ics/ICSHandler.d.ts +111 -0
- package/types/ics/ICSParser.d.ts +111 -0
- package/types/index.d.ts +22 -0
- package/types/integration/EnhancedCalendar.d.ts +76 -0
- package/types/performance/AdaptiveMemoryManager.d.ts +104 -0
- package/types/performance/LRUCache.d.ts +59 -0
- package/types/performance/PerformanceOptimizer.d.ts +134 -0
- package/types/search/EventSearch.d.ts +91 -0
- package/types/search/SearchWorkerManager.d.ts +116 -0
- package/types/state/StateManager.d.ts +200 -0
- package/types/timezone/TimezoneDatabase.d.ts +993 -0
- package/types/timezone/TimezoneManager.d.ts +134 -0
- package/types/types.d.ts +1225 -0
|
@@ -39,11 +39,19 @@ export class TimezoneManager {
|
|
|
39
39
|
this.database = new TimezoneDatabase();
|
|
40
40
|
|
|
41
41
|
// Cache timezone offsets for performance
|
|
42
|
+
// offsetCache: Map<timezone, Map<15-minute UTC bucket, offset>>
|
|
42
43
|
this.offsetCache = new Map();
|
|
43
44
|
this.dstCache = new Map();
|
|
44
45
|
|
|
46
|
+
// Intl.DateTimeFormat construction is ~50x the cost of using one,
|
|
47
|
+
// so formatters are cached per timezone and reused
|
|
48
|
+
this.formatterCache = new Map();
|
|
49
|
+
|
|
45
50
|
// Cache size management
|
|
46
51
|
this.maxCacheSize = 1000;
|
|
52
|
+
// ~20k 15-minute buckets per zone (≈ a few hundred KB worst case) covers
|
|
53
|
+
// multi-year expansions without evicting entries mid-scan
|
|
54
|
+
this.maxOffsetBucketsPerZone = 20000;
|
|
47
55
|
this.cacheHits = 0;
|
|
48
56
|
this.cacheMisses = 0;
|
|
49
57
|
}
|
|
@@ -109,68 +117,106 @@ export class TimezoneManager {
|
|
|
109
117
|
// Resolve any aliases
|
|
110
118
|
timezone = this.database.resolveAlias(timezone);
|
|
111
119
|
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
120
|
+
// Offsets only change at DST transitions, which occur on 15-minute UTC
|
|
121
|
+
// boundaries worldwide — one cached entry covers each 15-minute bucket
|
|
122
|
+
const bucket = Math.floor(date.getTime() / 900000);
|
|
123
|
+
let zoneCache = this.offsetCache.get(timezone);
|
|
124
|
+
if (zoneCache) {
|
|
125
|
+
const cached = zoneCache.get(bucket);
|
|
126
|
+
if (cached !== undefined) {
|
|
127
|
+
this.cacheHits++;
|
|
128
|
+
return cached;
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
zoneCache = new Map();
|
|
132
|
+
this.offsetCache.set(timezone, zoneCache);
|
|
118
133
|
}
|
|
119
134
|
|
|
120
135
|
this.cacheMisses++;
|
|
121
136
|
|
|
137
|
+
let offset;
|
|
138
|
+
|
|
122
139
|
// Try using Intl API if available (best option for browser/Node.js environments)
|
|
123
140
|
if (typeof Intl !== 'undefined' && Intl.DateTimeFormat) {
|
|
124
141
|
try {
|
|
125
|
-
const formatter = new Intl.DateTimeFormat('en-US', {
|
|
126
|
-
timeZone: timezone,
|
|
127
|
-
year: 'numeric',
|
|
128
|
-
month: '2-digit',
|
|
129
|
-
day: '2-digit',
|
|
130
|
-
hour: '2-digit',
|
|
131
|
-
minute: '2-digit',
|
|
132
|
-
second: '2-digit',
|
|
133
|
-
hour12: false
|
|
134
|
-
});
|
|
135
|
-
|
|
136
142
|
// Create same date in target timezone
|
|
137
|
-
const parts =
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
143
|
+
const parts = this._getFormatter(timezone).formatToParts(date);
|
|
144
|
+
let year, month, day, hour, minute, second;
|
|
145
|
+
for (const part of parts) {
|
|
146
|
+
switch (part.type) {
|
|
147
|
+
case 'year':
|
|
148
|
+
year = +part.value;
|
|
149
|
+
break;
|
|
150
|
+
case 'month':
|
|
151
|
+
month = +part.value;
|
|
152
|
+
break;
|
|
153
|
+
case 'day':
|
|
154
|
+
day = +part.value;
|
|
155
|
+
break;
|
|
156
|
+
case 'hour':
|
|
157
|
+
hour = +part.value;
|
|
158
|
+
break;
|
|
159
|
+
case 'minute':
|
|
160
|
+
minute = +part.value;
|
|
161
|
+
break;
|
|
162
|
+
case 'second':
|
|
163
|
+
second = +part.value;
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const tzDate = new Date(year, month - 1, day, hour, minute, second);
|
|
168
|
+
offset = -((tzDate.getTime() - date.getTime()) / (1000 * 60));
|
|
151
169
|
} catch (e) {
|
|
152
170
|
// Fallback to database calculation
|
|
153
171
|
}
|
|
154
172
|
}
|
|
155
173
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
174
|
+
if (offset === undefined) {
|
|
175
|
+
// Fallback: Use timezone database
|
|
176
|
+
const tzData = this.database.getTimezone(timezone);
|
|
177
|
+
if (!tzData) {
|
|
178
|
+
throw new Error(`Unknown timezone: ${timezone}`);
|
|
179
|
+
}
|
|
161
180
|
|
|
162
|
-
|
|
181
|
+
offset = tzData.offset;
|
|
163
182
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
183
|
+
// Apply DST if applicable
|
|
184
|
+
if (tzData.dst && this.isDST(date, timezone, tzData.dst)) {
|
|
185
|
+
offset += tzData.dst.offset;
|
|
186
|
+
}
|
|
167
187
|
}
|
|
168
188
|
|
|
169
|
-
this.
|
|
170
|
-
|
|
189
|
+
if (zoneCache.size >= this.maxOffsetBucketsPerZone) {
|
|
190
|
+
zoneCache.clear();
|
|
191
|
+
}
|
|
192
|
+
zoneCache.set(bucket, offset);
|
|
171
193
|
return offset;
|
|
172
194
|
}
|
|
173
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Get a cached Intl.DateTimeFormat for a timezone
|
|
198
|
+
* @param {string} timezone - Timezone identifier
|
|
199
|
+
* @returns {Intl.DateTimeFormat}
|
|
200
|
+
* @private
|
|
201
|
+
*/
|
|
202
|
+
_getFormatter(timezone) {
|
|
203
|
+
let formatter = this.formatterCache.get(timezone);
|
|
204
|
+
if (!formatter) {
|
|
205
|
+
formatter = new Intl.DateTimeFormat('en-US', {
|
|
206
|
+
timeZone: timezone,
|
|
207
|
+
year: 'numeric',
|
|
208
|
+
month: '2-digit',
|
|
209
|
+
day: '2-digit',
|
|
210
|
+
hour: '2-digit',
|
|
211
|
+
minute: '2-digit',
|
|
212
|
+
second: '2-digit',
|
|
213
|
+
hour12: false
|
|
214
|
+
});
|
|
215
|
+
this.formatterCache.set(timezone, formatter);
|
|
216
|
+
}
|
|
217
|
+
return formatter;
|
|
218
|
+
}
|
|
219
|
+
|
|
174
220
|
/**
|
|
175
221
|
* Check if date is in DST for given timezone
|
|
176
222
|
* @param {Date} date - Date to check
|
|
@@ -449,7 +495,7 @@ export class TimezoneManager {
|
|
|
449
495
|
: 0;
|
|
450
496
|
|
|
451
497
|
return {
|
|
452
|
-
offsetCacheSize: this.offsetCache.size,
|
|
498
|
+
offsetCacheSize: [...this.offsetCache.values()].reduce((n, m) => n + m.size, 0),
|
|
453
499
|
dstCacheSize: this.dstCache.size,
|
|
454
500
|
maxCacheSize: this.maxCacheSize,
|
|
455
501
|
cacheHits: this.cacheHits,
|
|
@@ -463,16 +509,8 @@ export class TimezoneManager {
|
|
|
463
509
|
* @private
|
|
464
510
|
*/
|
|
465
511
|
_manageCacheSize() {
|
|
466
|
-
//
|
|
467
|
-
|
|
468
|
-
// Remove first half of entries (oldest)
|
|
469
|
-
const entriesToRemove = Math.floor(this.offsetCache.size / 2);
|
|
470
|
-
const keys = Array.from(this.offsetCache.keys());
|
|
471
|
-
for (let i = 0; i < entriesToRemove; i++) {
|
|
472
|
-
this.offsetCache.delete(keys[i]);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
512
|
+
// Offset cache size is managed per-zone at insertion time in
|
|
513
|
+
// getTimezoneOffset; only the DST cache needs periodic eviction here
|
|
476
514
|
if (this.dstCache.size > this.maxCacheSize / 2) {
|
|
477
515
|
const entriesToRemove = Math.floor(this.dstCache.size / 2);
|
|
478
516
|
const keys = Array.from(this.dstCache.keys());
|
package/core/types.js
CHANGED
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
* @property {boolean} [recurring=false] - Whether this is a recurring event
|
|
20
20
|
* @property {RecurrenceRule|string} [recurrenceRule=null] - Recurrence rule (RRULE string or object)
|
|
21
21
|
* @property {string} [timeZone=null] - IANA timezone for the event
|
|
22
|
+
* @property {string} [endTimeZone=null] - IANA timezone for the event end (cross-timezone events)
|
|
23
|
+
* @property {RecurrenceRule|string} [recurrence=null] - Backward-compatible alias for recurrenceRule
|
|
24
|
+
* @property {string} [category=null] - Single category (alias for a one-element categories array)
|
|
22
25
|
* @property {EventStatus} [status='confirmed'] - Event status
|
|
23
26
|
* @property {EventVisibility} [visibility='public'] - Event visibility
|
|
24
27
|
* @property {Organizer} [organizer=null] - Event organizer
|
|
@@ -172,7 +175,7 @@
|
|
|
172
175
|
* @property {boolean} isCurrentMonth - Whether this day is in the current month
|
|
173
176
|
* @property {boolean} isToday - Whether this is today
|
|
174
177
|
* @property {boolean} isWeekend - Whether this is a weekend day
|
|
175
|
-
* @property {import('./
|
|
178
|
+
* @property {import('./events/Event.js').Event[]} events - Events for this day
|
|
176
179
|
*/
|
|
177
180
|
|
|
178
181
|
/**
|
|
@@ -191,9 +194,9 @@
|
|
|
191
194
|
* @property {string} dayName - Localized day name
|
|
192
195
|
* @property {boolean} isToday - Whether this is today
|
|
193
196
|
* @property {boolean} isWeekend - Whether this is a weekend day
|
|
194
|
-
* @property {import('./
|
|
195
|
-
* @property {Array<import('./
|
|
196
|
-
* @property {
|
|
197
|
+
* @property {import('./events/Event.js').Event[]} events - All events for this day
|
|
198
|
+
* @property {Array<import('./events/Event.js').Event[]>} overlapGroups - Groups of overlapping events
|
|
199
|
+
* @property {(events: import('./events/Event.js').Event[]) => Map<string, EventPosition>} getEventPositions - Function to calculate positions
|
|
197
200
|
*/
|
|
198
201
|
|
|
199
202
|
/**
|
|
@@ -208,7 +211,7 @@
|
|
|
208
211
|
* @property {Date} date - Date being displayed
|
|
209
212
|
* @property {string} dayName - Localized day name
|
|
210
213
|
* @property {boolean} isToday - Whether this is today
|
|
211
|
-
* @property {import('./
|
|
214
|
+
* @property {import('./events/Event.js').Event[]} allDayEvents - All-day events
|
|
212
215
|
* @property {HourSlot[]} hours - Hourly time slots
|
|
213
216
|
*/
|
|
214
217
|
|
|
@@ -216,7 +219,7 @@
|
|
|
216
219
|
* @typedef {Object} HourSlot
|
|
217
220
|
* @property {number} hour - Hour (0-23)
|
|
218
221
|
* @property {string} time - Formatted time string
|
|
219
|
-
* @property {import('./
|
|
222
|
+
* @property {import('./events/Event.js').Event[]} events - Events in this hour
|
|
220
223
|
*/
|
|
221
224
|
|
|
222
225
|
/**
|
|
@@ -233,7 +236,7 @@
|
|
|
233
236
|
* @property {Date} date - Date object
|
|
234
237
|
* @property {string} dayName - Localized day name
|
|
235
238
|
* @property {boolean} isToday - Whether this is today
|
|
236
|
-
* @property {import('./
|
|
239
|
+
* @property {import('./events/Event.js').Event[]} events - Events for this day
|
|
237
240
|
*/
|
|
238
241
|
|
|
239
242
|
/**
|
|
@@ -273,9 +276,9 @@
|
|
|
273
276
|
/**
|
|
274
277
|
* @typedef {Object} EventStoreChange
|
|
275
278
|
* @property {('add'|'update'|'remove'|'clear')} type - Type of change
|
|
276
|
-
* @property {import('./
|
|
277
|
-
* @property {import('./
|
|
278
|
-
* @property {import('./
|
|
279
|
+
* @property {import('./events/Event.js').Event} [event] - Affected event
|
|
280
|
+
* @property {import('./events/Event.js').Event} [oldEvent] - Previous event state (for updates)
|
|
281
|
+
* @property {import('./events/Event.js').Event[]} [oldEvents] - Previous events (for clear)
|
|
279
282
|
* @property {number} version - Store version number
|
|
280
283
|
*/
|
|
281
284
|
|
|
@@ -305,16 +308,16 @@
|
|
|
305
308
|
|
|
306
309
|
/**
|
|
307
310
|
* @typedef {Object} CalendarPlugin
|
|
308
|
-
* @property {
|
|
309
|
-
* @property {
|
|
311
|
+
* @property {(calendar: import('./calendar/Calendar.js').Calendar) => void} install - Installation function
|
|
312
|
+
* @property {(calendar: import('./calendar/Calendar.js').Calendar) => void} [uninstall] - Cleanup function
|
|
310
313
|
*/
|
|
311
314
|
|
|
312
315
|
/**
|
|
313
|
-
* @typedef {
|
|
316
|
+
* @typedef {(payload: any) => void} EventListener
|
|
314
317
|
*/
|
|
315
318
|
|
|
316
319
|
/**
|
|
317
|
-
* @typedef {
|
|
320
|
+
* @typedef {() => void} UnsubscribeFn
|
|
318
321
|
*/
|
|
319
322
|
|
|
320
323
|
/**
|
package/package.json
CHANGED
|
@@ -1,32 +1,55 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forcecalendar/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "A modern, lightweight, framework-agnostic calendar engine optimized for Salesforce",
|
|
7
7
|
"main": "core/index.js",
|
|
8
8
|
"module": "core/index.js",
|
|
9
|
-
"types": "
|
|
9
|
+
"types": "./types/index.d.ts",
|
|
10
10
|
"sideEffects": false,
|
|
11
11
|
"scripts": {
|
|
12
12
|
"test": "node tests/run-all.js",
|
|
13
13
|
"test:ics": "node tests/integration/test-ics.js",
|
|
14
14
|
"test:search": "node tests/integration/test-search.js",
|
|
15
|
-
"lint": "eslint core/
|
|
16
|
-
"lint:fix": "eslint core/ --
|
|
15
|
+
"lint": "eslint core/",
|
|
16
|
+
"lint:fix": "eslint core/ --fix",
|
|
17
17
|
"format": "prettier --write \"core/**/*.js\"",
|
|
18
18
|
"format:check": "prettier --check \"core/**/*.js\"",
|
|
19
19
|
"quality": "npm run lint && npm run format:check",
|
|
20
|
-
"sync:version": "node scripts/sync-version.js"
|
|
20
|
+
"sync:version": "node scripts/sync-version.js",
|
|
21
|
+
"build:types": "tsc -p tsconfig.types.json",
|
|
22
|
+
"prepublishOnly": "npm run build:types"
|
|
21
23
|
},
|
|
22
24
|
"exports": {
|
|
23
|
-
".":
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"./
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./types/index.d.ts",
|
|
27
|
+
"default": "./core/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./calendar": {
|
|
30
|
+
"types": "./types/calendar/Calendar.d.ts",
|
|
31
|
+
"default": "./core/calendar/Calendar.js"
|
|
32
|
+
},
|
|
33
|
+
"./events": {
|
|
34
|
+
"types": "./types/events/Event.d.ts",
|
|
35
|
+
"default": "./core/events/Event.js"
|
|
36
|
+
},
|
|
37
|
+
"./state": {
|
|
38
|
+
"types": "./types/state/StateManager.d.ts",
|
|
39
|
+
"default": "./core/state/StateManager.js"
|
|
40
|
+
},
|
|
41
|
+
"./search": {
|
|
42
|
+
"types": "./types/search/EventSearch.d.ts",
|
|
43
|
+
"default": "./core/search/EventSearch.js"
|
|
44
|
+
},
|
|
45
|
+
"./ics": {
|
|
46
|
+
"types": "./types/ics/ICSHandler.d.ts",
|
|
47
|
+
"default": "./core/ics/ICSHandler.js"
|
|
48
|
+
},
|
|
49
|
+
"./types": {
|
|
50
|
+
"types": "./types/types.d.ts",
|
|
51
|
+
"default": "./core/types.js"
|
|
52
|
+
}
|
|
30
53
|
},
|
|
31
54
|
"repository": {
|
|
32
55
|
"type": "git",
|
|
@@ -50,20 +73,17 @@
|
|
|
50
73
|
},
|
|
51
74
|
"homepage": "https://github.com/forceCalendar/core#readme",
|
|
52
75
|
"devDependencies": {
|
|
53
|
-
"@
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
57
|
-
"@rollup/plugin-terser": "^1.0.0",
|
|
58
|
-
"eslint": "^8.50.0",
|
|
76
|
+
"@eslint/js": "^10.0.1",
|
|
77
|
+
"eslint": "^10.6.0",
|
|
78
|
+
"globals": "^17.7.0",
|
|
59
79
|
"prettier": "^3.0.3",
|
|
60
|
-
"
|
|
61
|
-
"vite": "^6.4.3"
|
|
80
|
+
"typescript": "^7.0.2"
|
|
62
81
|
},
|
|
63
82
|
"files": [
|
|
64
83
|
"core/**/*.js",
|
|
65
84
|
"!core/**/*.test.js",
|
|
66
85
|
"!core/**/*.spec.js",
|
|
86
|
+
"types/**/*.d.ts",
|
|
67
87
|
"README.md",
|
|
68
88
|
"LICENSE"
|
|
69
89
|
]
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { EventStore } from '../events/EventStore.js';
|
|
2
|
+
import { Event } from '../events/Event.js';
|
|
3
|
+
import { StateManager } from '../state/StateManager.js';
|
|
4
|
+
import { TimezoneManager } from '../timezone/TimezoneManager.js';
|
|
5
|
+
/**
|
|
6
|
+
* Calendar - Main calendar class with full timezone support
|
|
7
|
+
* Pure JavaScript, no DOM dependencies
|
|
8
|
+
* Framework agnostic, Locker Service compatible
|
|
9
|
+
*/
|
|
10
|
+
export declare class Calendar {
|
|
11
|
+
timezoneManager: TimezoneManager;
|
|
12
|
+
config: {
|
|
13
|
+
events?: import("../types.js").EventData[];
|
|
14
|
+
view: string;
|
|
15
|
+
date: Date;
|
|
16
|
+
weekStartsOn: number;
|
|
17
|
+
locale: string;
|
|
18
|
+
timeZone: string;
|
|
19
|
+
showWeekNumbers: boolean;
|
|
20
|
+
showWeekends: boolean;
|
|
21
|
+
fixedWeekCount: boolean;
|
|
22
|
+
businessHours: {
|
|
23
|
+
start: string;
|
|
24
|
+
end: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
eventStore: EventStore;
|
|
28
|
+
state: StateManager;
|
|
29
|
+
listeners: Map<any, any>;
|
|
30
|
+
plugins: Set<any>;
|
|
31
|
+
views: Map<any, any>;
|
|
32
|
+
/**
|
|
33
|
+
* Create a new Calendar instance
|
|
34
|
+
* @param {import('../types.js').CalendarConfig} [config={}] - Configuration options
|
|
35
|
+
*/
|
|
36
|
+
constructor(config?: import('../types.js').CalendarConfig);
|
|
37
|
+
/**
|
|
38
|
+
* Set the calendar view
|
|
39
|
+
* @param {import('../types.js').ViewType} viewType - The view type ('month', 'week', 'day', 'list')
|
|
40
|
+
* @param {Date} [date=null] - Optional date to navigate to
|
|
41
|
+
*/
|
|
42
|
+
setView(viewType: import('../types.js').ViewType, date?: Date): void;
|
|
43
|
+
/**
|
|
44
|
+
* Get the current view type
|
|
45
|
+
* @returns {import('../types.js').ViewType} The current view type
|
|
46
|
+
*/
|
|
47
|
+
getView(): import('../types.js').ViewType;
|
|
48
|
+
/**
|
|
49
|
+
* Navigate to the next period
|
|
50
|
+
*/
|
|
51
|
+
next(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Navigate to the previous period
|
|
54
|
+
*/
|
|
55
|
+
previous(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Navigate to today
|
|
58
|
+
*/
|
|
59
|
+
today(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Navigate to a specific date
|
|
62
|
+
* @param {Date} date - The date to navigate to
|
|
63
|
+
*/
|
|
64
|
+
goToDate(date: Date): void;
|
|
65
|
+
/**
|
|
66
|
+
* Alias for goToDate (compat)
|
|
67
|
+
* @param {Date} date - The date to navigate to
|
|
68
|
+
*/
|
|
69
|
+
setDate(date: Date): void;
|
|
70
|
+
/**
|
|
71
|
+
* Get the current date
|
|
72
|
+
* @returns {Date}
|
|
73
|
+
*/
|
|
74
|
+
getCurrentDate(): Date;
|
|
75
|
+
/**
|
|
76
|
+
* Add an event
|
|
77
|
+
* @param {import('../events/Event.js').Event|import('../types.js').EventData} eventData - Event data or Event instance
|
|
78
|
+
* @returns {import('../events/Event.js').Event} The added event
|
|
79
|
+
*/
|
|
80
|
+
addEvent(eventData: import('../events/Event.js').Event | import('../types.js').EventData): import('../events/Event.js').Event;
|
|
81
|
+
/**
|
|
82
|
+
* Update an event
|
|
83
|
+
* @param {string} eventId - The event ID
|
|
84
|
+
* @param {Object} updates - Properties to update
|
|
85
|
+
* @returns {Event} The updated event
|
|
86
|
+
*/
|
|
87
|
+
updateEvent(eventId: string, updates: Object): Event;
|
|
88
|
+
/**
|
|
89
|
+
* Remove an event
|
|
90
|
+
* @param {string} eventId - The event ID
|
|
91
|
+
* @returns {boolean} True if removed
|
|
92
|
+
*/
|
|
93
|
+
removeEvent(eventId: string): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Alias for removeEvent (compat)
|
|
96
|
+
* @param {string} eventId - The event ID
|
|
97
|
+
* @returns {boolean} True if removed
|
|
98
|
+
*/
|
|
99
|
+
deleteEvent(eventId: string): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Get an event by ID
|
|
102
|
+
* @param {string} eventId - The event ID
|
|
103
|
+
* @returns {Event|null}
|
|
104
|
+
*/
|
|
105
|
+
getEvent(eventId: string): Event | null;
|
|
106
|
+
/**
|
|
107
|
+
* Get all events
|
|
108
|
+
* @returns {Event[]}
|
|
109
|
+
*/
|
|
110
|
+
getEvents(): Event[];
|
|
111
|
+
/**
|
|
112
|
+
* Set all events (replaces existing)
|
|
113
|
+
* @param {Event[]} events - Array of events
|
|
114
|
+
*/
|
|
115
|
+
setEvents(events: Event[]): void;
|
|
116
|
+
/**
|
|
117
|
+
* Query events with filters
|
|
118
|
+
* @param {Object} filters - Query filters
|
|
119
|
+
* @returns {Event[]}
|
|
120
|
+
*/
|
|
121
|
+
queryEvents(filters: Object): Event[];
|
|
122
|
+
/**
|
|
123
|
+
* Get events for a specific date
|
|
124
|
+
* @param {Date} date - The date
|
|
125
|
+
* @param {string} [timezone] - Timezone for the query (defaults to calendar timezone)
|
|
126
|
+
* @returns {Event[]}
|
|
127
|
+
*/
|
|
128
|
+
getEventsForDate(date: Date, timezone?: string): Event[];
|
|
129
|
+
/**
|
|
130
|
+
* Get events in a date range
|
|
131
|
+
* @param {Date} start - Start date
|
|
132
|
+
* @param {Date} end - End date
|
|
133
|
+
* @param {string} [timezone] - Timezone for the query (defaults to calendar timezone)
|
|
134
|
+
* @returns {Event[]}
|
|
135
|
+
*/
|
|
136
|
+
getEventsInRange(start: Date, end: Date, timezone?: string): Event[];
|
|
137
|
+
/**
|
|
138
|
+
* Set the calendar's timezone
|
|
139
|
+
* @param {string} timezone - IANA timezone identifier
|
|
140
|
+
*/
|
|
141
|
+
setTimezone(timezone: string): void;
|
|
142
|
+
/**
|
|
143
|
+
* Get the current timezone
|
|
144
|
+
* @returns {string} Current timezone
|
|
145
|
+
*/
|
|
146
|
+
getTimezone(): string;
|
|
147
|
+
/**
|
|
148
|
+
* Set the calendar locale
|
|
149
|
+
* @param {string} locale - Locale identifier (e.g. 'en-US')
|
|
150
|
+
*/
|
|
151
|
+
setLocale(locale: string): void;
|
|
152
|
+
/**
|
|
153
|
+
* Set the week start day
|
|
154
|
+
* @param {number} weekStartsOn - 0 = Sunday, 1 = Monday, etc.
|
|
155
|
+
*/
|
|
156
|
+
setWeekStartsOn(weekStartsOn: number): void;
|
|
157
|
+
/**
|
|
158
|
+
* Convert a date from one timezone to another
|
|
159
|
+
* @param {Date} date - Date to convert
|
|
160
|
+
* @param {string} fromTimezone - Source timezone
|
|
161
|
+
* @param {string} toTimezone - Target timezone
|
|
162
|
+
* @returns {Date} Converted date
|
|
163
|
+
*/
|
|
164
|
+
convertTimezone(date: Date, fromTimezone: string, toTimezone: string): Date;
|
|
165
|
+
/**
|
|
166
|
+
* Convert a date to the calendar's timezone
|
|
167
|
+
* @param {Date} date - Date to convert
|
|
168
|
+
* @param {string} fromTimezone - Source timezone
|
|
169
|
+
* @returns {Date} Date in calendar timezone
|
|
170
|
+
*/
|
|
171
|
+
toCalendarTimezone(date: Date, fromTimezone: string): Date;
|
|
172
|
+
/**
|
|
173
|
+
* Convert a date from the calendar's timezone
|
|
174
|
+
* @param {Date} date - Date in calendar timezone
|
|
175
|
+
* @param {string} toTimezone - Target timezone
|
|
176
|
+
* @returns {Date} Converted date
|
|
177
|
+
*/
|
|
178
|
+
fromCalendarTimezone(date: Date, toTimezone: string): Date;
|
|
179
|
+
/**
|
|
180
|
+
* Format a date in a specific timezone
|
|
181
|
+
* @param {Date} date - Date to format
|
|
182
|
+
* @param {string} [timezone] - Timezone for formatting (defaults to calendar timezone)
|
|
183
|
+
* @param {Object} [options] - Formatting options
|
|
184
|
+
* @returns {string} Formatted date string
|
|
185
|
+
*/
|
|
186
|
+
formatInTimezone(date: Date, timezone?: string, options?: Object): string;
|
|
187
|
+
/**
|
|
188
|
+
* Get list of common timezones with offsets
|
|
189
|
+
* @returns {Array<{value: string, label: string, offset: string}>} Timezone list
|
|
190
|
+
*/
|
|
191
|
+
getTimezones(): Array<{
|
|
192
|
+
value: string;
|
|
193
|
+
label: string;
|
|
194
|
+
offset: string;
|
|
195
|
+
}>;
|
|
196
|
+
/**
|
|
197
|
+
* Get overlapping event groups for a date
|
|
198
|
+
* @param {Date} date - The date to check
|
|
199
|
+
* @param {boolean} timedOnly - Only include timed events
|
|
200
|
+
* @returns {Array<Event[]>} Array of event groups that overlap
|
|
201
|
+
*/
|
|
202
|
+
getOverlapGroups(date: Date, timedOnly?: boolean): Array<Event[]>;
|
|
203
|
+
/**
|
|
204
|
+
* Calculate event positions for rendering
|
|
205
|
+
* @param {Event[]} events - Array of overlapping events
|
|
206
|
+
* @returns {Map<string, {column: number, totalColumns: number}>} Position data
|
|
207
|
+
*/
|
|
208
|
+
calculateEventPositions(events: Event[]): Map<string, {
|
|
209
|
+
column: number;
|
|
210
|
+
totalColumns: number;
|
|
211
|
+
}>;
|
|
212
|
+
/**
|
|
213
|
+
* Get the current view's data
|
|
214
|
+
* @returns {import('../types.js').MonthViewData|import('../types.js').WeekViewData|import('../types.js').DayViewData|import('../types.js').ListViewData|null} View-specific data
|
|
215
|
+
*/
|
|
216
|
+
getViewData(): import('../types.js').MonthViewData | import('../types.js').WeekViewData | import('../types.js').DayViewData | import('../types.js').ListViewData | null;
|
|
217
|
+
/**
|
|
218
|
+
* Get month view data
|
|
219
|
+
* @private
|
|
220
|
+
*/
|
|
221
|
+
private _getMonthViewData;
|
|
222
|
+
/**
|
|
223
|
+
* Get week view data
|
|
224
|
+
* @private
|
|
225
|
+
*/
|
|
226
|
+
private _getWeekViewData;
|
|
227
|
+
/**
|
|
228
|
+
* Get day view data
|
|
229
|
+
* @private
|
|
230
|
+
*/
|
|
231
|
+
private _getDayViewData;
|
|
232
|
+
/**
|
|
233
|
+
* Get list view data
|
|
234
|
+
* @private
|
|
235
|
+
*/
|
|
236
|
+
private _getListViewData;
|
|
237
|
+
/**
|
|
238
|
+
* Select an event
|
|
239
|
+
* @param {string} eventId - Event ID to select
|
|
240
|
+
*/
|
|
241
|
+
selectEvent(eventId: string): void;
|
|
242
|
+
/**
|
|
243
|
+
* Clear event selection
|
|
244
|
+
*/
|
|
245
|
+
clearEventSelection(): void;
|
|
246
|
+
/**
|
|
247
|
+
* Select a date
|
|
248
|
+
* @param {Date} date - Date to select
|
|
249
|
+
*/
|
|
250
|
+
selectDate(date: Date): void;
|
|
251
|
+
/**
|
|
252
|
+
* Clear date selection
|
|
253
|
+
*/
|
|
254
|
+
clearDateSelection(): void;
|
|
255
|
+
/**
|
|
256
|
+
* Subscribe to calendar events
|
|
257
|
+
* @param {string} eventName - Event name
|
|
258
|
+
* @param {Function} callback - Callback function
|
|
259
|
+
* @returns {Function} Unsubscribe function
|
|
260
|
+
*/
|
|
261
|
+
on(eventName: string, callback: Function): Function;
|
|
262
|
+
/**
|
|
263
|
+
* Unsubscribe from calendar events
|
|
264
|
+
* @param {string} eventName - Event name
|
|
265
|
+
* @param {Function} callback - Callback function
|
|
266
|
+
*/
|
|
267
|
+
off(eventName: string, callback: Function): void;
|
|
268
|
+
/**
|
|
269
|
+
* Emit an event
|
|
270
|
+
* @private
|
|
271
|
+
*/
|
|
272
|
+
private _emit;
|
|
273
|
+
/**
|
|
274
|
+
* Set up internal listeners
|
|
275
|
+
* @private
|
|
276
|
+
*/
|
|
277
|
+
private _setupInternalListeners;
|
|
278
|
+
/**
|
|
279
|
+
* Install a plugin
|
|
280
|
+
* @param {Object} plugin - Plugin object with install method
|
|
281
|
+
*/
|
|
282
|
+
use(plugin: Object): void;
|
|
283
|
+
/**
|
|
284
|
+
* Destroy the calendar and clean up
|
|
285
|
+
*/
|
|
286
|
+
destroy(): void;
|
|
287
|
+
}
|