@forcecalendar/interface 1.0.49 → 1.0.51
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 +246 -239
- package/dist/force-calendar-interface.esm.js.map +1 -1
- package/dist/force-calendar-interface.umd.js +35 -35
- package/dist/force-calendar-interface.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ForceCalendar.js +0 -1
- package/src/renderers/DayViewRenderer.js +4 -3
- package/src/renderers/MonthViewRenderer.js +3 -2
- package/src/renderers/WeekViewRenderer.js +3 -2
- package/src/utils/DateUtils.js +8 -0
|
@@ -52,8 +52,8 @@ class M extends HTMLElement {
|
|
|
52
52
|
console.warn("addListener called with invalid parameters", { element: t, event: e, handler: r });
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
|
-
const
|
|
56
|
-
t.addEventListener(e,
|
|
55
|
+
const i = r.bind(this);
|
|
56
|
+
t.addEventListener(e, i), this._listeners.push({ element: t, event: e, handler: i });
|
|
57
57
|
}
|
|
58
58
|
emit(t, e = {}) {
|
|
59
59
|
this.dispatchEvent(
|
|
@@ -111,7 +111,7 @@ class M extends HTMLElement {
|
|
|
111
111
|
this.setProp(t, r), this._initialized && this.render();
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
-
class
|
|
114
|
+
class S {
|
|
115
115
|
constructor() {
|
|
116
116
|
this.events = /* @__PURE__ */ new Map(), this.wildcardHandlers = /* @__PURE__ */ new Set();
|
|
117
117
|
}
|
|
@@ -123,13 +123,13 @@ class T {
|
|
|
123
123
|
* @returns {Function} Unsubscribe function
|
|
124
124
|
*/
|
|
125
125
|
on(t, e, r = {}) {
|
|
126
|
-
const { once:
|
|
126
|
+
const { once: i = !1, priority: s = 0 } = r;
|
|
127
127
|
if (t.includes("*")) {
|
|
128
|
-
const o = { pattern: t, handler: e, once:
|
|
128
|
+
const o = { pattern: t, handler: e, once: i, priority: s };
|
|
129
129
|
return this.wildcardHandlers.add(o), () => this.wildcardHandlers.delete(o);
|
|
130
130
|
}
|
|
131
131
|
this.events.has(t) || this.events.set(t, []);
|
|
132
|
-
const n = { handler: e, once:
|
|
132
|
+
const n = { handler: e, once: i, priority: s }, a = this.events.get(t);
|
|
133
133
|
return a.push(n), a.sort((o, c) => c.priority - o.priority), () => {
|
|
134
134
|
const o = a.indexOf(n);
|
|
135
135
|
o > -1 && a.splice(o, 1);
|
|
@@ -146,16 +146,16 @@ class T {
|
|
|
146
146
|
*/
|
|
147
147
|
off(t, e) {
|
|
148
148
|
if (t.includes("*")) {
|
|
149
|
-
for (const
|
|
150
|
-
if (
|
|
151
|
-
this.wildcardHandlers.delete(
|
|
149
|
+
for (const s of this.wildcardHandlers)
|
|
150
|
+
if (s.pattern === t && s.handler === e) {
|
|
151
|
+
this.wildcardHandlers.delete(s);
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
154
154
|
return;
|
|
155
155
|
}
|
|
156
156
|
if (!this.events.has(t)) return;
|
|
157
|
-
const r = this.events.get(t),
|
|
158
|
-
|
|
157
|
+
const r = this.events.get(t), i = r.findIndex((s) => s.handler === e);
|
|
158
|
+
i > -1 && r.splice(i, 1), r.length === 0 && this.events.delete(t);
|
|
159
159
|
}
|
|
160
160
|
/**
|
|
161
161
|
* Remove all wildcard handlers matching a pattern
|
|
@@ -172,8 +172,8 @@ class T {
|
|
|
172
172
|
*/
|
|
173
173
|
offAll(t) {
|
|
174
174
|
for (const [e, r] of this.events) {
|
|
175
|
-
const
|
|
176
|
-
|
|
175
|
+
const i = r.findIndex((s) => s.handler === t);
|
|
176
|
+
i > -1 && r.splice(i, 1), r.length === 0 && this.events.delete(e);
|
|
177
177
|
}
|
|
178
178
|
for (const e of [...this.wildcardHandlers])
|
|
179
179
|
e.handler === t && this.wildcardHandlers.delete(e);
|
|
@@ -185,9 +185,9 @@ class T {
|
|
|
185
185
|
*/
|
|
186
186
|
emit(t, e) {
|
|
187
187
|
if (this.events.has(t)) {
|
|
188
|
-
const
|
|
189
|
-
for (const
|
|
190
|
-
const { handler: n, once: a } =
|
|
188
|
+
const i = [...this.events.get(t)];
|
|
189
|
+
for (const s of i) {
|
|
190
|
+
const { handler: n, once: a } = s;
|
|
191
191
|
a && this.off(t, n);
|
|
192
192
|
try {
|
|
193
193
|
n(e, t);
|
|
@@ -197,17 +197,17 @@ class T {
|
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
const r = [];
|
|
200
|
-
for (const
|
|
201
|
-
if (this.matchesPattern(t,
|
|
202
|
-
const { handler:
|
|
203
|
-
n && r.push(
|
|
200
|
+
for (const i of [...this.wildcardHandlers])
|
|
201
|
+
if (this.matchesPattern(t, i.pattern)) {
|
|
202
|
+
const { handler: s, once: n } = i;
|
|
203
|
+
n && r.push(i);
|
|
204
204
|
try {
|
|
205
|
-
|
|
205
|
+
s(e, t);
|
|
206
206
|
} catch (a) {
|
|
207
207
|
console.error(`Error in wildcard handler for ${t}:`, a);
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
|
-
r.forEach((
|
|
210
|
+
r.forEach((i) => this.wildcardHandlers.delete(i));
|
|
211
211
|
}
|
|
212
212
|
/**
|
|
213
213
|
* Check if event name matches a pattern
|
|
@@ -249,10 +249,10 @@ class T {
|
|
|
249
249
|
return t;
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
|
-
const U = new
|
|
252
|
+
const U = new S();
|
|
253
253
|
class I {
|
|
254
254
|
constructor(t = {}) {
|
|
255
|
-
this.eventBus = new
|
|
255
|
+
this.eventBus = new S(), this.calendar = new L({
|
|
256
256
|
view: t.view || "month",
|
|
257
257
|
date: t.date || /* @__PURE__ */ new Date(),
|
|
258
258
|
weekStartsOn: t.weekStartsOn ?? 0,
|
|
@@ -291,8 +291,8 @@ class I {
|
|
|
291
291
|
*/
|
|
292
292
|
_eventsMatch(t, e) {
|
|
293
293
|
if (t.length !== e.length) return !1;
|
|
294
|
-
const r = new Set(t.map((
|
|
295
|
-
return e.every((
|
|
294
|
+
const r = new Set(t.map((i) => i.id));
|
|
295
|
+
return e.every((i) => r.has(i.id));
|
|
296
296
|
}
|
|
297
297
|
// State management
|
|
298
298
|
getState() {
|
|
@@ -303,8 +303,8 @@ class I {
|
|
|
303
303
|
};
|
|
304
304
|
}
|
|
305
305
|
setState(t, e = {}) {
|
|
306
|
-
const { silent: r = !1 } = e,
|
|
307
|
-
return this.state = { ...this.state, ...t }, r || (this.notifySubscribers(
|
|
306
|
+
const { silent: r = !1 } = e, i = { ...this.state };
|
|
307
|
+
return this.state = { ...this.state, ...t }, r || (this.notifySubscribers(i, this.state), this.emitStateChange(i, this.state)), this.state;
|
|
308
308
|
}
|
|
309
309
|
subscribe(t, e = null) {
|
|
310
310
|
return this.subscribers.add(t), e && (this._subscriberIds || (this._subscriberIds = /* @__PURE__ */ new Map()), this._subscriberIds.set(e, t)), () => this.unsubscribe(t, e);
|
|
@@ -331,17 +331,17 @@ class I {
|
|
|
331
331
|
this.subscribers.forEach((r) => {
|
|
332
332
|
try {
|
|
333
333
|
r(e, t);
|
|
334
|
-
} catch (
|
|
335
|
-
console.error("Error in state subscriber:",
|
|
334
|
+
} catch (i) {
|
|
335
|
+
console.error("Error in state subscriber:", i);
|
|
336
336
|
}
|
|
337
337
|
});
|
|
338
338
|
}
|
|
339
339
|
emitStateChange(t, e) {
|
|
340
|
-
const r = Object.keys(e).filter((
|
|
341
|
-
r.forEach((
|
|
342
|
-
this.eventBus.emit(`state:${
|
|
343
|
-
oldValue: t[
|
|
344
|
-
newValue: e[
|
|
340
|
+
const r = Object.keys(e).filter((i) => t[i] !== e[i]);
|
|
341
|
+
r.forEach((i) => {
|
|
342
|
+
this.eventBus.emit(`state:${i}:changed`, {
|
|
343
|
+
oldValue: t[i],
|
|
344
|
+
newValue: e[i],
|
|
345
345
|
state: e
|
|
346
346
|
});
|
|
347
347
|
}), r.length > 0 && this.eventBus.emit("state:changed", { oldState: t, newState: e, changedKeys: r });
|
|
@@ -412,11 +412,11 @@ class I {
|
|
|
412
412
|
return this.enrichViewData(t);
|
|
413
413
|
}
|
|
414
414
|
enrichViewData(t) {
|
|
415
|
-
var
|
|
416
|
-
const e = { ...t }, r = (
|
|
417
|
-
if (e.weeks && (e.weeks = e.weeks.map((
|
|
418
|
-
...
|
|
419
|
-
days:
|
|
415
|
+
var i;
|
|
416
|
+
const e = { ...t }, r = (i = this.state.selectedDate) == null ? void 0 : i.toDateString();
|
|
417
|
+
if (e.weeks && (e.weeks = e.weeks.map((s) => ({
|
|
418
|
+
...s,
|
|
419
|
+
days: s.days.map((n) => {
|
|
420
420
|
const a = new Date(n.date);
|
|
421
421
|
return {
|
|
422
422
|
...n,
|
|
@@ -424,16 +424,16 @@ class I {
|
|
|
424
424
|
events: n.events || this.getEventsForDate(a)
|
|
425
425
|
};
|
|
426
426
|
})
|
|
427
|
-
}))), e.days && (e.days = e.days.map((
|
|
428
|
-
const n = new Date(
|
|
427
|
+
}))), e.days && (e.days = e.days.map((s) => {
|
|
428
|
+
const n = new Date(s.date);
|
|
429
429
|
return {
|
|
430
|
-
...
|
|
430
|
+
...s,
|
|
431
431
|
isSelected: n.toDateString() === r,
|
|
432
|
-
events:
|
|
432
|
+
events: s.events || this.getEventsForDate(n)
|
|
433
433
|
};
|
|
434
434
|
})), e.date && !e.days && !e.weeks) {
|
|
435
|
-
const
|
|
436
|
-
e.isSelected =
|
|
435
|
+
const s = new Date(e.date);
|
|
436
|
+
e.isSelected = s.toDateString() === r, e.events = e.events || this.getEventsForDate(s);
|
|
437
437
|
}
|
|
438
438
|
return e;
|
|
439
439
|
}
|
|
@@ -486,13 +486,13 @@ class I {
|
|
|
486
486
|
this.subscribers.clear(), this._subscriberIds && (this._subscriberIds.clear(), this._subscriberIds = null), this.eventBus && (this.eventBus.clear(), this.eventBus = null), this.state = null, this.calendar = null;
|
|
487
487
|
}
|
|
488
488
|
}
|
|
489
|
-
class
|
|
489
|
+
class u extends V {
|
|
490
490
|
/**
|
|
491
491
|
* Format date for display
|
|
492
492
|
*/
|
|
493
493
|
static formatDate(t, e = "default", r = "en-US") {
|
|
494
494
|
if (!t) return "";
|
|
495
|
-
const
|
|
495
|
+
const i = {
|
|
496
496
|
default: { year: "numeric", month: "long", day: "numeric" },
|
|
497
497
|
short: { year: "numeric", month: "short", day: "numeric" },
|
|
498
498
|
long: { weekday: "long", year: "numeric", month: "long", day: "numeric" },
|
|
@@ -509,20 +509,20 @@ class p extends V {
|
|
|
509
509
|
hour: "numeric",
|
|
510
510
|
minute: "2-digit"
|
|
511
511
|
}
|
|
512
|
-
},
|
|
513
|
-
return new Intl.DateTimeFormat(r,
|
|
512
|
+
}, s = i[e] || i.default;
|
|
513
|
+
return new Intl.DateTimeFormat(r, s).format(t);
|
|
514
514
|
}
|
|
515
515
|
/**
|
|
516
516
|
* Format time for display
|
|
517
517
|
*/
|
|
518
|
-
static formatTime(t, e = !0, r = !1,
|
|
518
|
+
static formatTime(t, e = !0, r = !1, i = "en-US") {
|
|
519
519
|
if (!t) return "";
|
|
520
|
-
const
|
|
520
|
+
const s = {
|
|
521
521
|
hour: "numeric",
|
|
522
522
|
minute: e ? "2-digit" : void 0,
|
|
523
523
|
hour12: !r
|
|
524
524
|
};
|
|
525
|
-
return new Intl.DateTimeFormat(
|
|
525
|
+
return new Intl.DateTimeFormat(i, s).format(t);
|
|
526
526
|
}
|
|
527
527
|
/**
|
|
528
528
|
* Format date range for display
|
|
@@ -531,25 +531,25 @@ class p extends V {
|
|
|
531
531
|
if (!t) return "";
|
|
532
532
|
if (!e || this.isSameDay(t, e))
|
|
533
533
|
return this.formatDate(t, "default", r);
|
|
534
|
-
const
|
|
535
|
-
return `${this.formatDate(t,
|
|
534
|
+
const i = this.isSameYear(t, e) ? "short" : "default";
|
|
535
|
+
return `${this.formatDate(t, i, r)} - ${this.formatDate(e, "default", r)}`;
|
|
536
536
|
}
|
|
537
537
|
/**
|
|
538
538
|
* Format time range for display
|
|
539
539
|
*/
|
|
540
540
|
static formatTimeRange(t, e, r = "en-US") {
|
|
541
541
|
if (!t) return "";
|
|
542
|
-
const
|
|
543
|
-
if (!e) return
|
|
544
|
-
const
|
|
545
|
-
return `${
|
|
542
|
+
const i = this.formatTime(t, !0, !1, r);
|
|
543
|
+
if (!e) return i;
|
|
544
|
+
const s = this.formatTime(e, !0, !1, r);
|
|
545
|
+
return `${i} - ${s}`;
|
|
546
546
|
}
|
|
547
547
|
/**
|
|
548
548
|
* Get relative time string (e.g., "2 hours ago", "in 3 days")
|
|
549
549
|
*/
|
|
550
550
|
static getRelativeTime(t, e = /* @__PURE__ */ new Date(), r = "en-US") {
|
|
551
|
-
const
|
|
552
|
-
return Math.abs(n) < 60 ?
|
|
551
|
+
const i = new Intl.RelativeTimeFormat(r, { numeric: "auto" }), s = t - e, n = Math.floor(s / 1e3), a = Math.floor(n / 60), o = Math.floor(a / 60), c = Math.floor(o / 24), l = Math.floor(c / 7), d = Math.floor(c / 30), p = Math.floor(c / 365);
|
|
552
|
+
return Math.abs(n) < 60 ? i.format(n, "second") : Math.abs(a) < 60 ? i.format(a, "minute") : Math.abs(o) < 24 ? i.format(o, "hour") : Math.abs(c) < 7 ? i.format(c, "day") : Math.abs(l) < 4 ? i.format(l, "week") : Math.abs(d) < 12 ? i.format(d, "month") : i.format(p, "year");
|
|
553
553
|
}
|
|
554
554
|
/**
|
|
555
555
|
* Check if date is today
|
|
@@ -584,65 +584,72 @@ class p extends V {
|
|
|
584
584
|
const r = new Date(2024, 0, 7 + t);
|
|
585
585
|
return new Intl.DateTimeFormat(e, { weekday: "short" }).format(r);
|
|
586
586
|
}
|
|
587
|
+
/**
|
|
588
|
+
* Get full day name
|
|
589
|
+
*/
|
|
590
|
+
static getDayName(t, e = "en-US") {
|
|
591
|
+
const r = new Date(2024, 0, 7 + t);
|
|
592
|
+
return new Intl.DateTimeFormat(e, { weekday: "long" }).format(r);
|
|
593
|
+
}
|
|
587
594
|
/**
|
|
588
595
|
* Get month name
|
|
589
596
|
*/
|
|
590
597
|
static getMonthName(t, e = "long", r = "en-US") {
|
|
591
|
-
const
|
|
592
|
-
return new Intl.DateTimeFormat(r, { month: e }).format(
|
|
598
|
+
const i = new Date(2024, t, 1);
|
|
599
|
+
return new Intl.DateTimeFormat(r, { month: e }).format(i);
|
|
593
600
|
}
|
|
594
601
|
/**
|
|
595
602
|
* Parse time string (e.g., "14:30" or "2:30 PM")
|
|
596
603
|
*/
|
|
597
604
|
static parseTimeString(t, e = /* @__PURE__ */ new Date()) {
|
|
598
|
-
const r = new Date(e), [
|
|
605
|
+
const r = new Date(e), [i, s] = t.split(/\s+/), [n, a] = i.split(":").map(Number);
|
|
599
606
|
let o = n;
|
|
600
|
-
return
|
|
607
|
+
return s && (s.toLowerCase() === "pm" && n < 12 ? o = n + 12 : s.toLowerCase() === "am" && n === 12 && (o = 0)), r.setHours(o, a || 0, 0, 0), r;
|
|
601
608
|
}
|
|
602
609
|
}
|
|
603
|
-
class
|
|
610
|
+
class k {
|
|
604
611
|
/**
|
|
605
612
|
* Create element with attributes and children
|
|
606
613
|
*/
|
|
607
614
|
static createElement(t, e = {}, r = []) {
|
|
608
|
-
const
|
|
609
|
-
return Object.entries(e).forEach(([
|
|
610
|
-
if (
|
|
611
|
-
|
|
612
|
-
else if (
|
|
613
|
-
Object.assign(
|
|
614
|
-
else if (
|
|
615
|
-
|
|
616
|
-
else if (
|
|
617
|
-
const a =
|
|
618
|
-
|
|
615
|
+
const i = document.createElement(t);
|
|
616
|
+
return Object.entries(e).forEach(([s, n]) => {
|
|
617
|
+
if (s === "className")
|
|
618
|
+
i.className = n;
|
|
619
|
+
else if (s === "style" && typeof n == "object")
|
|
620
|
+
Object.assign(i.style, n);
|
|
621
|
+
else if (s.startsWith("data-"))
|
|
622
|
+
i.setAttribute(s, n);
|
|
623
|
+
else if (s.startsWith("on") && typeof n == "function") {
|
|
624
|
+
const a = s.slice(2).toLowerCase();
|
|
625
|
+
i.addEventListener(a, n);
|
|
619
626
|
} else
|
|
620
|
-
s
|
|
621
|
-
}), r.forEach((
|
|
622
|
-
typeof
|
|
623
|
-
}),
|
|
627
|
+
i[s] = n;
|
|
628
|
+
}), r.forEach((s) => {
|
|
629
|
+
typeof s == "string" ? i.appendChild(document.createTextNode(s)) : s instanceof Node && i.appendChild(s);
|
|
630
|
+
}), i;
|
|
624
631
|
}
|
|
625
632
|
/**
|
|
626
633
|
* Add multiple event listeners
|
|
627
634
|
*/
|
|
628
635
|
static addEventListeners(t, e) {
|
|
629
|
-
return Object.entries(e).forEach(([r,
|
|
630
|
-
t.addEventListener(r,
|
|
636
|
+
return Object.entries(e).forEach(([r, i]) => {
|
|
637
|
+
t.addEventListener(r, i);
|
|
631
638
|
}), () => {
|
|
632
|
-
Object.entries(e).forEach(([r,
|
|
633
|
-
t.removeEventListener(r,
|
|
639
|
+
Object.entries(e).forEach(([r, i]) => {
|
|
640
|
+
t.removeEventListener(r, i);
|
|
634
641
|
});
|
|
635
642
|
};
|
|
636
643
|
}
|
|
637
644
|
/**
|
|
638
645
|
* Delegate event handling
|
|
639
646
|
*/
|
|
640
|
-
static delegate(t, e, r,
|
|
641
|
-
const
|
|
647
|
+
static delegate(t, e, r, i) {
|
|
648
|
+
const s = (n) => {
|
|
642
649
|
const a = n.target.closest(e);
|
|
643
|
-
a && t.contains(a) &&
|
|
650
|
+
a && t.contains(a) && i.call(a, n);
|
|
644
651
|
};
|
|
645
|
-
return t.addEventListener(r,
|
|
652
|
+
return t.addEventListener(r, s), () => t.removeEventListener(r, s);
|
|
646
653
|
}
|
|
647
654
|
/**
|
|
648
655
|
* Get element position relative to viewport
|
|
@@ -669,8 +676,8 @@ class D {
|
|
|
669
676
|
* Smooth scroll to element
|
|
670
677
|
*/
|
|
671
678
|
static scrollToElement(t, e = {}) {
|
|
672
|
-
const { behavior: r = "smooth", block:
|
|
673
|
-
t.scrollIntoView({ behavior: r, block:
|
|
679
|
+
const { behavior: r = "smooth", block: i = "start", inline: s = "nearest" } = e;
|
|
680
|
+
t.scrollIntoView({ behavior: r, block: i, inline: s });
|
|
674
681
|
}
|
|
675
682
|
/**
|
|
676
683
|
* Get computed style value
|
|
@@ -695,10 +702,10 @@ class D {
|
|
|
695
702
|
*/
|
|
696
703
|
static waitForAnimation(t, e = "animationend") {
|
|
697
704
|
return new Promise((r) => {
|
|
698
|
-
const
|
|
699
|
-
t.removeEventListener(e,
|
|
705
|
+
const i = () => {
|
|
706
|
+
t.removeEventListener(e, i), r();
|
|
700
707
|
};
|
|
701
|
-
t.addEventListener(e,
|
|
708
|
+
t.addEventListener(e, i);
|
|
702
709
|
});
|
|
703
710
|
}
|
|
704
711
|
/**
|
|
@@ -726,9 +733,9 @@ class D {
|
|
|
726
733
|
*/
|
|
727
734
|
static debounce(t, e = 250) {
|
|
728
735
|
let r;
|
|
729
|
-
return function(...
|
|
736
|
+
return function(...s) {
|
|
730
737
|
const n = () => {
|
|
731
|
-
clearTimeout(r), t(...
|
|
738
|
+
clearTimeout(r), t(...s);
|
|
732
739
|
};
|
|
733
740
|
clearTimeout(r), r = setTimeout(n, e);
|
|
734
741
|
};
|
|
@@ -738,8 +745,8 @@ class D {
|
|
|
738
745
|
*/
|
|
739
746
|
static throttle(t, e = 250) {
|
|
740
747
|
let r;
|
|
741
|
-
return function(...
|
|
742
|
-
r || (t.apply(this,
|
|
748
|
+
return function(...i) {
|
|
749
|
+
r || (t.apply(this, i), r = !0, setTimeout(() => r = !1, e));
|
|
743
750
|
};
|
|
744
751
|
}
|
|
745
752
|
/**
|
|
@@ -753,9 +760,9 @@ class D {
|
|
|
753
760
|
*/
|
|
754
761
|
static parents(t, e) {
|
|
755
762
|
const r = [];
|
|
756
|
-
let
|
|
757
|
-
for (;
|
|
758
|
-
|
|
763
|
+
let i = t.parentElement;
|
|
764
|
+
for (; i; )
|
|
765
|
+
i.matches(e) && r.push(i), i = i.parentElement;
|
|
759
766
|
return r;
|
|
760
767
|
}
|
|
761
768
|
/**
|
|
@@ -789,13 +796,13 @@ class D {
|
|
|
789
796
|
);
|
|
790
797
|
if (e.length === 0)
|
|
791
798
|
return t.setAttribute("tabindex", "-1"), t.focus(), () => t.removeAttribute("tabindex");
|
|
792
|
-
const r = e[0],
|
|
793
|
-
n.key === "Tab" && (n.shiftKey ? document.activeElement === r && (
|
|
799
|
+
const r = e[0], i = e[e.length - 1], s = (n) => {
|
|
800
|
+
n.key === "Tab" && (n.shiftKey ? document.activeElement === r && (i == null || i.focus(), n.preventDefault()) : document.activeElement === i && (r == null || r.focus(), n.preventDefault()));
|
|
794
801
|
};
|
|
795
|
-
return t.addEventListener("keydown",
|
|
802
|
+
return t.addEventListener("keydown", s), r == null || r.focus(), () => t.removeEventListener("keydown", s);
|
|
796
803
|
}
|
|
797
804
|
}
|
|
798
|
-
class
|
|
805
|
+
class f {
|
|
799
806
|
/**
|
|
800
807
|
* Get CSS variable value
|
|
801
808
|
*/
|
|
@@ -806,8 +813,8 @@ class u {
|
|
|
806
813
|
* Set CSS variables
|
|
807
814
|
*/
|
|
808
815
|
static setCSSVariables(t, e = document.documentElement) {
|
|
809
|
-
Object.entries(t).forEach(([r,
|
|
810
|
-
e.style.setProperty(r,
|
|
816
|
+
Object.entries(t).forEach(([r, i]) => {
|
|
817
|
+
e.style.setProperty(r, i);
|
|
811
818
|
});
|
|
812
819
|
}
|
|
813
820
|
/**
|
|
@@ -963,22 +970,22 @@ class u {
|
|
|
963
970
|
* Darken color by percentage
|
|
964
971
|
*/
|
|
965
972
|
static darken(t, e) {
|
|
966
|
-
const r = parseInt(t.replace("#", ""), 16),
|
|
967
|
-
return "#" + (16777216 + (
|
|
973
|
+
const r = parseInt(t.replace("#", ""), 16), i = Math.round(2.55 * e), s = (r >> 16) - i, n = (r >> 8 & 255) - i, a = (r & 255) - i;
|
|
974
|
+
return "#" + (16777216 + (s < 255 ? s < 1 ? 0 : s : 255) * 65536 + (n < 255 ? n < 1 ? 0 : n : 255) * 256 + (a < 255 ? a < 1 ? 0 : a : 255)).toString(16).slice(1);
|
|
968
975
|
}
|
|
969
976
|
/**
|
|
970
977
|
* Lighten color by percentage
|
|
971
978
|
*/
|
|
972
979
|
static lighten(t, e) {
|
|
973
|
-
const r = parseInt(t.replace("#", ""), 16),
|
|
974
|
-
return "#" + (16777216 + (
|
|
980
|
+
const r = parseInt(t.replace("#", ""), 16), i = Math.round(2.55 * e), s = (r >> 16) + i, n = (r >> 8 & 255) + i, a = (r & 255) + i;
|
|
981
|
+
return "#" + (16777216 + (s < 255 ? s < 1 ? 0 : s : 255) * 65536 + (n < 255 ? n < 1 ? 0 : n : 255) * 256 + (a < 255 ? a < 1 ? 0 : a : 255)).toString(16).slice(1);
|
|
975
982
|
}
|
|
976
983
|
/**
|
|
977
984
|
* Get contrast color (black or white) for background
|
|
978
985
|
*/
|
|
979
986
|
static getContrastColor(t) {
|
|
980
|
-
const e = t.replace("#", ""), r = parseInt(e.substr(0, 2), 16),
|
|
981
|
-
return (r * 299 +
|
|
987
|
+
const e = t.replace("#", ""), r = parseInt(e.substr(0, 2), 16), i = parseInt(e.substr(2, 2), 16), s = parseInt(e.substr(4, 2), 16);
|
|
988
|
+
return (r * 299 + i * 587 + s * 114) / 1e3 >= 128 ? "#000000" : "#FFFFFF";
|
|
982
989
|
}
|
|
983
990
|
/**
|
|
984
991
|
* Sanitize color value to prevent CSS injection
|
|
@@ -1020,8 +1027,8 @@ class u {
|
|
|
1020
1027
|
* Convert hex to rgba
|
|
1021
1028
|
*/
|
|
1022
1029
|
static hexToRgba(t, e = 1) {
|
|
1023
|
-
const r = t.replace("#", ""),
|
|
1024
|
-
return `rgba(${
|
|
1030
|
+
const r = t.replace("#", ""), i = parseInt(r.substr(0, 2), 16), s = parseInt(r.substr(2, 2), 16), n = parseInt(r.substr(4, 2), 16);
|
|
1031
|
+
return `rgba(${i}, ${s}, ${n}, ${e})`;
|
|
1025
1032
|
}
|
|
1026
1033
|
/**
|
|
1027
1034
|
* Generate grid styles
|
|
@@ -1132,7 +1139,7 @@ class u {
|
|
|
1132
1139
|
/**
|
|
1133
1140
|
* Default theme colors
|
|
1134
1141
|
*/
|
|
1135
|
-
v(
|
|
1142
|
+
v(f, "colors", {
|
|
1136
1143
|
primary: "#3B82F6",
|
|
1137
1144
|
// Modern Blue
|
|
1138
1145
|
secondary: "#64748B",
|
|
@@ -1165,7 +1172,7 @@ v(u, "colors", {
|
|
|
1165
1172
|
}), /**
|
|
1166
1173
|
* Common CSS variables
|
|
1167
1174
|
*/
|
|
1168
|
-
v(
|
|
1175
|
+
v(f, "cssVariables", {
|
|
1169
1176
|
// "Pro" Palette - Functional & Sharp
|
|
1170
1177
|
"--fc-primary-color": "#2563EB",
|
|
1171
1178
|
// International Blue (Focus)
|
|
@@ -1233,7 +1240,7 @@ v(u, "cssVariables", {
|
|
|
1233
1240
|
}), /**
|
|
1234
1241
|
* Get responsive breakpoints
|
|
1235
1242
|
*/
|
|
1236
|
-
v(
|
|
1243
|
+
v(f, "breakpoints", {
|
|
1237
1244
|
xs: "320px",
|
|
1238
1245
|
sm: "576px",
|
|
1239
1246
|
md: "768px",
|
|
@@ -1271,8 +1278,8 @@ class E {
|
|
|
1271
1278
|
* @param {Function} handler
|
|
1272
1279
|
*/
|
|
1273
1280
|
addListener(t, e, r) {
|
|
1274
|
-
const
|
|
1275
|
-
t.addEventListener(e,
|
|
1281
|
+
const i = r.bind(this);
|
|
1282
|
+
t.addEventListener(e, i), this._listeners.push({ element: t, event: e, handler: i });
|
|
1276
1283
|
}
|
|
1277
1284
|
/**
|
|
1278
1285
|
* Escape HTML to prevent XSS
|
|
@@ -1280,7 +1287,7 @@ class E {
|
|
|
1280
1287
|
* @returns {string}
|
|
1281
1288
|
*/
|
|
1282
1289
|
escapeHTML(t) {
|
|
1283
|
-
return t == null ? "" :
|
|
1290
|
+
return t == null ? "" : k.escapeHTML(String(t));
|
|
1284
1291
|
}
|
|
1285
1292
|
/**
|
|
1286
1293
|
* Check if a date is today
|
|
@@ -1315,8 +1322,8 @@ class E {
|
|
|
1315
1322
|
* @returns {string}
|
|
1316
1323
|
*/
|
|
1317
1324
|
formatTime(t) {
|
|
1318
|
-
const e = t.getHours(), r = t.getMinutes(),
|
|
1319
|
-
return r === 0 ? `${
|
|
1325
|
+
const e = t.getHours(), r = t.getMinutes(), i = e >= 12 ? "PM" : "AM", s = e % 12 || 12;
|
|
1326
|
+
return r === 0 ? `${s} ${i}` : `${s}:${r.toString().padStart(2, "0")} ${i}`;
|
|
1320
1327
|
}
|
|
1321
1328
|
/**
|
|
1322
1329
|
* Get contrasting text color for a background color.
|
|
@@ -1325,7 +1332,7 @@ class E {
|
|
|
1325
1332
|
* @returns {string} '#000000' or '#FFFFFF'
|
|
1326
1333
|
*/
|
|
1327
1334
|
getContrastingTextColor(t) {
|
|
1328
|
-
return !t || typeof t != "string" || t.charAt(0) !== "#" ? "white" :
|
|
1335
|
+
return !t || typeof t != "string" || t.charAt(0) !== "#" ? "white" : f.getContrastColor(t);
|
|
1329
1336
|
}
|
|
1330
1337
|
/**
|
|
1331
1338
|
* Render the "now" indicator line for time-based views
|
|
@@ -1345,31 +1352,31 @@ class E {
|
|
|
1345
1352
|
computeOverlapLayout(t) {
|
|
1346
1353
|
if (!t || t.length === 0) return /* @__PURE__ */ new Map();
|
|
1347
1354
|
const e = t.map((o) => {
|
|
1348
|
-
const c = new Date(o.start),
|
|
1349
|
-
return { id: o.id, startMin:
|
|
1355
|
+
const c = new Date(o.start), l = new Date(o.end), d = c.getHours() * 60 + c.getMinutes(), p = Math.max(d + 1, l.getHours() * 60 + l.getMinutes());
|
|
1356
|
+
return { id: o.id, startMin: d, endMin: p };
|
|
1350
1357
|
});
|
|
1351
1358
|
e.sort((o, c) => o.startMin - c.startMin || c.endMin - c.startMin - (o.endMin - o.startMin));
|
|
1352
|
-
const r = [],
|
|
1359
|
+
const r = [], i = /* @__PURE__ */ new Map();
|
|
1353
1360
|
for (const o of e) {
|
|
1354
1361
|
let c = !1;
|
|
1355
|
-
for (let
|
|
1356
|
-
if (r[
|
|
1357
|
-
r[
|
|
1362
|
+
for (let l = 0; l < r.length; l++)
|
|
1363
|
+
if (r[l] <= o.startMin) {
|
|
1364
|
+
r[l] = o.endMin, i.set(o.id, { column: l, totalColumns: 0 }), c = !0;
|
|
1358
1365
|
break;
|
|
1359
1366
|
}
|
|
1360
|
-
c || (
|
|
1367
|
+
c || (i.set(o.id, { column: r.length, totalColumns: 0 }), r.push(o.endMin));
|
|
1361
1368
|
}
|
|
1362
|
-
const
|
|
1369
|
+
const s = [];
|
|
1363
1370
|
let n = [], a = 0;
|
|
1364
1371
|
for (const o of e)
|
|
1365
|
-
n.length === 0 || o.startMin < a ? (n.push(o), a = Math.max(a, o.endMin)) : (
|
|
1366
|
-
n.length > 0 &&
|
|
1367
|
-
for (const o of
|
|
1368
|
-
const c = Math.max(...o.map((
|
|
1369
|
-
for (const
|
|
1370
|
-
|
|
1372
|
+
n.length === 0 || o.startMin < a ? (n.push(o), a = Math.max(a, o.endMin)) : (s.push(n), n = [o], a = o.endMin);
|
|
1373
|
+
n.length > 0 && s.push(n);
|
|
1374
|
+
for (const o of s) {
|
|
1375
|
+
const c = Math.max(...o.map((l) => i.get(l.id).column)) + 1;
|
|
1376
|
+
for (const l of o)
|
|
1377
|
+
i.get(l.id).totalColumns = c;
|
|
1371
1378
|
}
|
|
1372
|
-
return
|
|
1379
|
+
return i;
|
|
1373
1380
|
}
|
|
1374
1381
|
/**
|
|
1375
1382
|
* Render a timed event block
|
|
@@ -1380,10 +1387,10 @@ class E {
|
|
|
1380
1387
|
* @returns {string} HTML string
|
|
1381
1388
|
*/
|
|
1382
1389
|
renderTimedEvent(t, e = {}) {
|
|
1383
|
-
const { compact: r = !0, overlapLayout:
|
|
1390
|
+
const { compact: r = !0, overlapLayout: i = null } = e, s = new Date(t.start), n = new Date(t.end), a = s.getHours() * 60 + s.getMinutes(), o = Math.max((n - s) / (1e3 * 60), r ? 20 : 30), c = this.getEventColor(t), l = this.getContrastingTextColor(c), d = r ? "4px 8px" : "8px 12px", p = r ? "11px" : "13px", g = r ? 2 : 12, b = r ? 2 : 24, T = r ? "4px" : "6px";
|
|
1384
1391
|
let y, x;
|
|
1385
|
-
if (
|
|
1386
|
-
const { column: C, totalColumns: _ } =
|
|
1392
|
+
if (i && i.has(t.id)) {
|
|
1393
|
+
const { column: C, totalColumns: _ } = i.get(t.id), $ = `(100% - ${g + b}px)`;
|
|
1387
1394
|
y = `calc(${g}px + ${C} * ${$} / ${_})`, x = `calc(${$} / ${_})`;
|
|
1388
1395
|
} else
|
|
1389
1396
|
y = `${g}px`, x = `calc(100% - ${g + b}px)`;
|
|
@@ -1391,16 +1398,16 @@ class E {
|
|
|
1391
1398
|
<div class="fc-event fc-timed-event" data-event-id="${this.escapeHTML(t.id)}"
|
|
1392
1399
|
style="position: absolute; top: ${a}px; height: ${o}px;
|
|
1393
1400
|
left: ${y}; width: ${x};
|
|
1394
|
-
background-color: ${c}; border-radius: ${
|
|
1395
|
-
padding: ${
|
|
1396
|
-
font-weight: 500; color: ${
|
|
1401
|
+
background-color: ${c}; border-radius: ${T};
|
|
1402
|
+
padding: ${d}; font-size: ${p};
|
|
1403
|
+
font-weight: 500; color: ${l}; overflow: hidden;
|
|
1397
1404
|
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
|
|
1398
1405
|
cursor: pointer; z-index: 5;">
|
|
1399
1406
|
<div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
|
|
1400
1407
|
${this.escapeHTML(t.title)}
|
|
1401
1408
|
</div>
|
|
1402
1409
|
<div style="font-size: ${r ? "10px" : "11px"}; opacity: 0.9;">
|
|
1403
|
-
${this.formatTime(
|
|
1410
|
+
${this.formatTime(s)}${r ? "" : " - " + this.formatTime(n)}
|
|
1404
1411
|
</div>
|
|
1405
1412
|
</div>
|
|
1406
1413
|
`;
|
|
@@ -1411,7 +1418,7 @@ class E {
|
|
|
1411
1418
|
* @returns {string}
|
|
1412
1419
|
*/
|
|
1413
1420
|
getEventColor(t) {
|
|
1414
|
-
return
|
|
1421
|
+
return f.sanitizeColor(t == null ? void 0 : t.backgroundColor, "#2563eb");
|
|
1415
1422
|
}
|
|
1416
1423
|
/**
|
|
1417
1424
|
* Attach common event handlers for day/event clicks
|
|
@@ -1421,8 +1428,8 @@ class E {
|
|
|
1421
1428
|
const e = t.target.closest(".fc-event");
|
|
1422
1429
|
if (!e || !this.container.contains(e)) return;
|
|
1423
1430
|
t.stopPropagation();
|
|
1424
|
-
const r = e.dataset.eventId,
|
|
1425
|
-
|
|
1431
|
+
const r = e.dataset.eventId, i = this.stateManager.getEvents().find((s) => s.id === r);
|
|
1432
|
+
i && this.stateManager.selectEvent(i);
|
|
1426
1433
|
});
|
|
1427
1434
|
}
|
|
1428
1435
|
}
|
|
@@ -1443,7 +1450,7 @@ class w extends E {
|
|
|
1443
1450
|
}
|
|
1444
1451
|
_renderMonthView(t, e) {
|
|
1445
1452
|
const r = e.weekStartsOn || 0;
|
|
1446
|
-
let
|
|
1453
|
+
let s = `
|
|
1447
1454
|
<div class="fc-month-view" style="display: flex; flex-direction: column; height: 100%; min-height: 400px; background: var(--fc-background); border: 1px solid var(--fc-border-color);">
|
|
1448
1455
|
<div class="fc-month-header" style="display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--fc-border-color); background: var(--fc-background-alt);">
|
|
1449
1456
|
${this._getDayNames(r).map((n) => `<div class="fc-month-header-cell" style="padding: 12px 8px; text-align: center; font-size: 11px; font-weight: 600; color: var(--fc-text-light); text-transform: uppercase;">${n}</div>`).join("")}
|
|
@@ -1451,14 +1458,14 @@ class w extends E {
|
|
|
1451
1458
|
<div class="fc-month-body" style="display: flex; flex-direction: column; flex: 1;">
|
|
1452
1459
|
`;
|
|
1453
1460
|
return t.weeks.forEach((n) => {
|
|
1454
|
-
|
|
1455
|
-
}),
|
|
1461
|
+
s += this._renderWeek(n);
|
|
1462
|
+
}), s += "</div></div>", s;
|
|
1456
1463
|
}
|
|
1457
1464
|
_getDayNames(t) {
|
|
1458
|
-
const e =
|
|
1459
|
-
for (let
|
|
1460
|
-
const
|
|
1461
|
-
r.push(e
|
|
1465
|
+
const e = this.stateManager.getState().config.locale || "en-US", r = [];
|
|
1466
|
+
for (let i = 0; i < 7; i++) {
|
|
1467
|
+
const s = (t + i) % 7;
|
|
1468
|
+
r.push(u.getDayAbbreviation(s, e));
|
|
1462
1469
|
}
|
|
1463
1470
|
return r;
|
|
1464
1471
|
}
|
|
@@ -1469,15 +1476,15 @@ class w extends E {
|
|
|
1469
1476
|
}), e += "</div>", e;
|
|
1470
1477
|
}
|
|
1471
1478
|
_renderDay(t) {
|
|
1472
|
-
const e = !t.isCurrentMonth, r = t.isToday,
|
|
1479
|
+
const e = !t.isCurrentMonth, r = t.isToday, i = e ? "var(--fc-background-hover)" : "var(--fc-background)", s = e ? "var(--fc-text-light)" : "var(--fc-text-color)", n = r ? "background: var(--fc-primary-color); color: white; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;" : "", a = t.events || [], o = a.slice(0, this.maxEventsToShow), c = a.length - this.maxEventsToShow;
|
|
1473
1480
|
return `
|
|
1474
1481
|
<div class="fc-month-day" data-date="${t.date}"
|
|
1475
|
-
style="background: ${
|
|
1476
|
-
<div class="fc-day-number" style="font-size: 13px; font-weight: 500; color: ${
|
|
1482
|
+
style="background: ${i}; border-right: 1px solid var(--fc-border-color); border-bottom: 1px solid var(--fc-border-color); padding: 4px; min-height: 80px; cursor: pointer; display: flex; flex-direction: column;">
|
|
1483
|
+
<div class="fc-day-number" style="font-size: 13px; font-weight: 500; color: ${s}; padding: 2px 4px; margin-bottom: 4px; ${n}">
|
|
1477
1484
|
${t.dayOfMonth}
|
|
1478
1485
|
</div>
|
|
1479
1486
|
<div class="fc-day-events" style="display: flex; flex-direction: column; gap: 2px; flex: 1; overflow: hidden;">
|
|
1480
|
-
${o.map((
|
|
1487
|
+
${o.map((l) => this._renderEvent(l)).join("")}
|
|
1481
1488
|
${c > 0 ? `<div class="fc-more-events" style="font-size: 10px; color: var(--fc-text-light); padding: 2px 4px; font-weight: 500;">+${c} more</div>` : ""}
|
|
1482
1489
|
</div>
|
|
1483
1490
|
</div>
|
|
@@ -1517,23 +1524,23 @@ class z extends E {
|
|
|
1517
1524
|
this.container.innerHTML = r, this._attachEventHandlers(), this._scrollToCurrentTime();
|
|
1518
1525
|
}
|
|
1519
1526
|
_renderWeekView(t, e) {
|
|
1520
|
-
const r = t.days,
|
|
1527
|
+
const r = t.days, i = this.stateManager.getState().config.locale || "en-US", s = Array.from({ length: 24 }, (a, o) => o), n = r.map((a) => {
|
|
1521
1528
|
const o = new Date(a.date), c = a.events || [];
|
|
1522
1529
|
return {
|
|
1523
1530
|
...a,
|
|
1524
1531
|
date: o,
|
|
1525
|
-
dayName:
|
|
1532
|
+
dayName: u.getDayAbbreviation(o.getDay(), i),
|
|
1526
1533
|
dayOfMonth: o.getDate(),
|
|
1527
1534
|
isToday: this.isToday(o),
|
|
1528
|
-
timedEvents: c.filter((
|
|
1529
|
-
allDayEvents: c.filter((
|
|
1535
|
+
timedEvents: c.filter((l) => !l.allDay),
|
|
1536
|
+
allDayEvents: c.filter((l) => l.allDay)
|
|
1530
1537
|
};
|
|
1531
1538
|
});
|
|
1532
1539
|
return `
|
|
1533
1540
|
<div class="fc-week-view" style="display: flex; flex-direction: column; height: 100%; background: var(--fc-background); overflow: hidden;">
|
|
1534
1541
|
${this._renderHeader(n)}
|
|
1535
1542
|
${this._renderAllDayRow(n)}
|
|
1536
|
-
${this._renderTimeGrid(n,
|
|
1543
|
+
${this._renderTimeGrid(n, s)}
|
|
1537
1544
|
</div>
|
|
1538
1545
|
`;
|
|
1539
1546
|
}
|
|
@@ -1614,7 +1621,7 @@ class z extends E {
|
|
|
1614
1621
|
<!-- Timed events -->
|
|
1615
1622
|
${(() => {
|
|
1616
1623
|
const r = this.computeOverlapLayout(t.timedEvents);
|
|
1617
|
-
return t.timedEvents.map((
|
|
1624
|
+
return t.timedEvents.map((i) => this.renderTimedEvent(i, { compact: !0, overlapLayout: r })).join("");
|
|
1618
1625
|
})()}
|
|
1619
1626
|
</div>
|
|
1620
1627
|
`;
|
|
@@ -1623,7 +1630,7 @@ class z extends E {
|
|
|
1623
1630
|
this.addListener(this.container, "click", (t) => {
|
|
1624
1631
|
const e = t.target.closest(".fc-week-day-column");
|
|
1625
1632
|
if (!e || !this.container.contains(e) || t.target.closest(".fc-event")) return;
|
|
1626
|
-
const r = new Date(e.dataset.date),
|
|
1633
|
+
const r = new Date(e.dataset.date), i = this.container.querySelector("#week-scroll-container"), s = e.offsetTop, n = t.clientY - e.getBoundingClientRect().top + (i ? i.scrollTop : 0) - s, a = Math.max(0, Math.min(n + s, this.totalHeight));
|
|
1627
1634
|
r.setHours(
|
|
1628
1635
|
Math.floor(a / this.hourHeight),
|
|
1629
1636
|
Math.floor(a % this.hourHeight / (this.hourHeight / 60)),
|
|
@@ -1654,40 +1661,40 @@ class B extends E {
|
|
|
1654
1661
|
this.container.innerHTML = r, this._attachEventHandlers(), this._scrollToCurrentTime();
|
|
1655
1662
|
}
|
|
1656
1663
|
_renderDayView(t, e) {
|
|
1657
|
-
var
|
|
1658
|
-
const r = ((
|
|
1659
|
-
if (!
|
|
1664
|
+
var d, p;
|
|
1665
|
+
const r = ((p = (d = this.stateManager) == null ? void 0 : d.getState()) == null ? void 0 : p.currentDate) || /* @__PURE__ */ new Date(), i = this._extractDayData(t, r);
|
|
1666
|
+
if (!i)
|
|
1660
1667
|
return '<div style="padding: 20px; text-align: center; color: var(--fc-text-secondary);">No data available for day view.</div>';
|
|
1661
|
-
const { dayDate:
|
|
1668
|
+
const { dayDate: s, dayName: n, isToday: a, allDayEvents: o, timedEvents: c } = i, l = Array.from({ length: 24 }, (g, b) => b);
|
|
1662
1669
|
return `
|
|
1663
1670
|
<div class="fc-day-view" style="display: flex; flex-direction: column; height: 100%; background: var(--fc-background); overflow: hidden;">
|
|
1664
|
-
${this._renderHeader(
|
|
1665
|
-
${this._renderAllDayRow(o,
|
|
1666
|
-
${this._renderTimeGrid(c, a,
|
|
1671
|
+
${this._renderHeader(s, n, a)}
|
|
1672
|
+
${this._renderAllDayRow(o, s)}
|
|
1673
|
+
${this._renderTimeGrid(c, a, s, l)}
|
|
1667
1674
|
</div>
|
|
1668
1675
|
`;
|
|
1669
1676
|
}
|
|
1670
1677
|
_extractDayData(t, e) {
|
|
1671
|
-
let r,
|
|
1672
|
-
const o =
|
|
1678
|
+
let r, i, s, n, a;
|
|
1679
|
+
const o = this.stateManager.getState().config.locale || "en-US";
|
|
1673
1680
|
if (t.type === "day" && t.date)
|
|
1674
|
-
if (r = new Date(t.date),
|
|
1681
|
+
if (r = new Date(t.date), i = t.dayName || u.getDayName(r.getDay(), o), s = t.isToday !== void 0 ? t.isToday : this.isToday(r), n = t.allDayEvents || [], t.hours && Array.isArray(t.hours)) {
|
|
1675
1682
|
const c = /* @__PURE__ */ new Map();
|
|
1676
|
-
t.hours.forEach((
|
|
1677
|
-
(
|
|
1678
|
-
c.has(
|
|
1683
|
+
t.hours.forEach((l) => {
|
|
1684
|
+
(l.events || []).forEach((d) => {
|
|
1685
|
+
c.has(d.id) || c.set(d.id, d);
|
|
1679
1686
|
});
|
|
1680
1687
|
}), a = Array.from(c.values());
|
|
1681
1688
|
} else
|
|
1682
1689
|
a = [];
|
|
1683
1690
|
else if (t.days && t.days.length > 0) {
|
|
1684
|
-
const c = t.days.find((
|
|
1685
|
-
r = new Date(c.date),
|
|
1686
|
-
const
|
|
1687
|
-
n =
|
|
1691
|
+
const c = t.days.find((d) => this.isSameDay(new Date(d.date), e)) || t.days[0];
|
|
1692
|
+
r = new Date(c.date), i = u.getDayName(r.getDay(), o), s = this.isToday(r);
|
|
1693
|
+
const l = c.events || [];
|
|
1694
|
+
n = l.filter((d) => d.allDay), a = l.filter((d) => !d.allDay);
|
|
1688
1695
|
} else
|
|
1689
1696
|
return null;
|
|
1690
|
-
return { dayDate: r, dayName:
|
|
1697
|
+
return { dayDate: r, dayName: i, isToday: s, allDayEvents: n, timedEvents: a };
|
|
1691
1698
|
}
|
|
1692
1699
|
_renderHeader(t, e, r) {
|
|
1693
1700
|
return `
|
|
@@ -1723,12 +1730,12 @@ class B extends E {
|
|
|
1723
1730
|
</div>
|
|
1724
1731
|
`;
|
|
1725
1732
|
}
|
|
1726
|
-
_renderTimeGrid(t, e, r,
|
|
1733
|
+
_renderTimeGrid(t, e, r, i) {
|
|
1727
1734
|
return `
|
|
1728
1735
|
<div id="day-scroll-container" class="fc-time-grid-container" style="flex: 1; overflow-y: auto; overflow-x: hidden; position: relative;">
|
|
1729
1736
|
<div class="fc-time-grid" style="display: grid; grid-template-columns: 60px 1fr; position: relative; height: ${this.totalHeight}px;">
|
|
1730
|
-
${this._renderTimeGutter(
|
|
1731
|
-
${this._renderDayColumn(t, e, r,
|
|
1737
|
+
${this._renderTimeGutter(i)}
|
|
1738
|
+
${this._renderDayColumn(t, e, r, i)}
|
|
1732
1739
|
</div>
|
|
1733
1740
|
</div>
|
|
1734
1741
|
`;
|
|
@@ -1746,19 +1753,19 @@ class B extends E {
|
|
|
1746
1753
|
</div>
|
|
1747
1754
|
`;
|
|
1748
1755
|
}
|
|
1749
|
-
_renderDayColumn(t, e, r,
|
|
1756
|
+
_renderDayColumn(t, e, r, i) {
|
|
1750
1757
|
return `
|
|
1751
1758
|
<div class="fc-day-column" data-date="${r.toISOString()}" style="position: relative; cursor: pointer;">
|
|
1752
1759
|
<!-- Hour grid lines -->
|
|
1753
|
-
${
|
|
1760
|
+
${i.map(() => `<div style="height: ${this.hourHeight}px; border-bottom: 1px solid var(--fc-background-hover);"></div>`).join("")}
|
|
1754
1761
|
|
|
1755
1762
|
<!-- Now indicator for today -->
|
|
1756
1763
|
${e ? this.renderNowIndicator() : ""}
|
|
1757
1764
|
|
|
1758
1765
|
<!-- Timed events -->
|
|
1759
1766
|
${(() => {
|
|
1760
|
-
const
|
|
1761
|
-
return t.map((n) => this.renderTimedEvent(n, { compact: !1, overlapLayout:
|
|
1767
|
+
const s = this.computeOverlapLayout(t);
|
|
1768
|
+
return t.map((n) => this.renderTimedEvent(n, { compact: !1, overlapLayout: s })).join("");
|
|
1762
1769
|
})()}
|
|
1763
1770
|
</div>
|
|
1764
1771
|
`;
|
|
@@ -1767,7 +1774,7 @@ class B extends E {
|
|
|
1767
1774
|
this.addListener(this.container, "click", (t) => {
|
|
1768
1775
|
const e = t.target.closest(".fc-day-column");
|
|
1769
1776
|
if (!e || !this.container.contains(e) || t.target.closest(".fc-event")) return;
|
|
1770
|
-
const r = new Date(e.dataset.date),
|
|
1777
|
+
const r = new Date(e.dataset.date), i = this.container.querySelector("#day-scroll-container"), s = e.offsetTop, n = t.clientY - e.getBoundingClientRect().top + (i ? i.scrollTop : 0) - s, a = Math.max(0, Math.min(n + s, this.totalHeight));
|
|
1771
1778
|
r.setHours(
|
|
1772
1779
|
Math.floor(a / this.hourHeight),
|
|
1773
1780
|
Math.floor(a % this.hourHeight / (this.hourHeight / 60)),
|
|
@@ -1812,8 +1819,8 @@ class A extends M {
|
|
|
1812
1819
|
}
|
|
1813
1820
|
getStyles() {
|
|
1814
1821
|
return `
|
|
1815
|
-
${
|
|
1816
|
-
${
|
|
1822
|
+
${f.getBaseStyles()}
|
|
1823
|
+
${f.getButtonStyles()}
|
|
1817
1824
|
|
|
1818
1825
|
:host {
|
|
1819
1826
|
display: none;
|
|
@@ -2058,7 +2065,7 @@ class A extends M {
|
|
|
2058
2065
|
});
|
|
2059
2066
|
}
|
|
2060
2067
|
open(t = /* @__PURE__ */ new Date()) {
|
|
2061
|
-
this.hasAttribute("open") || this.setAttribute("open", ""), this.titleGroup.classList.remove("has-error"), this.endGroup.classList.remove("has-error"), this._formData.start = t, this._formData.end = new Date(t.getTime() + this.config.defaultDuration * 60 * 1e3), this._formData.title = "", this._formData.color = this.config.colors[0].color, this.startInput && (this.titleInput.value = "", this.startInput.value = this.formatDateForInput(this._formData.start), this.endInput.value = this.formatDateForInput(this._formData.end), this.updateColorSelection(), this._cleanupFocusTrap && this._cleanupFocusTrap(), this._cleanupFocusTrap =
|
|
2068
|
+
this.hasAttribute("open") || this.setAttribute("open", ""), this.titleGroup.classList.remove("has-error"), this.endGroup.classList.remove("has-error"), this._formData.start = t, this._formData.end = new Date(t.getTime() + this.config.defaultDuration * 60 * 1e3), this._formData.title = "", this._formData.color = this.config.colors[0].color, this.startInput && (this.titleInput.value = "", this.startInput.value = this.formatDateForInput(this._formData.start), this.endInput.value = this.formatDateForInput(this._formData.end), this.updateColorSelection(), this._cleanupFocusTrap && this._cleanupFocusTrap(), this._cleanupFocusTrap = k.trapFocus(this.modalContent));
|
|
2062
2069
|
}
|
|
2063
2070
|
close() {
|
|
2064
2071
|
this.removeAttribute("open"), this._cleanupFocusTrap && (this._cleanupFocusTrap(), this._cleanupFocusTrap = null);
|
|
@@ -2080,8 +2087,8 @@ class A extends M {
|
|
|
2080
2087
|
this.emit("save", t), this.close();
|
|
2081
2088
|
}
|
|
2082
2089
|
formatDateForInput(t) {
|
|
2083
|
-
const e = (o) => String(o).padStart(2, "0"), r = t.getFullYear(),
|
|
2084
|
-
return `${r}-${
|
|
2090
|
+
const e = (o) => String(o).padStart(2, "0"), r = t.getFullYear(), i = e(t.getMonth() + 1), s = e(t.getDate()), n = e(t.getHours()), a = e(t.getMinutes());
|
|
2091
|
+
return `${r}-${i}-${s}T${n}:${a}`;
|
|
2085
2092
|
}
|
|
2086
2093
|
unmount() {
|
|
2087
2094
|
this._cleanupFocusTrap && this._cleanupFocusTrap(), this._handleKeyDown && (window.removeEventListener("keydown", this._handleKeyDown), this._handleKeyDown = null, this._keydownListenerAdded = !1);
|
|
@@ -2093,7 +2100,7 @@ const m = class m extends M {
|
|
|
2093
2100
|
return ["view", "date", "locale", "timezone", "week-starts-on", "height"];
|
|
2094
2101
|
}
|
|
2095
2102
|
constructor() {
|
|
2096
|
-
super(), this.stateManager = null, this.currentView = null, this._hasRendered = !1, this.
|
|
2103
|
+
super(), this.stateManager = null, this.currentView = null, this._hasRendered = !1, this._busUnsubscribers = [];
|
|
2097
2104
|
}
|
|
2098
2105
|
initialize() {
|
|
2099
2106
|
const t = {
|
|
@@ -2109,16 +2116,16 @@ const m = class m extends M {
|
|
|
2109
2116
|
this._busUnsubscribers.forEach((r) => r()), this._busUnsubscribers = [];
|
|
2110
2117
|
const t = this.stateManager.eventBus;
|
|
2111
2118
|
this._busUnsubscribers.push(
|
|
2112
|
-
t.on("navigation:*", (r,
|
|
2113
|
-
this.emit("calendar-navigate", { action:
|
|
2119
|
+
t.on("navigation:*", (r, i) => {
|
|
2120
|
+
this.emit("calendar-navigate", { action: i.split(":")[1], ...r });
|
|
2114
2121
|
})
|
|
2115
2122
|
), this._busUnsubscribers.push(
|
|
2116
2123
|
t.on("view:changed", (r) => {
|
|
2117
2124
|
this.emit("calendar-view-change", r);
|
|
2118
2125
|
})
|
|
2119
2126
|
);
|
|
2120
|
-
const e = (r,
|
|
2121
|
-
this.emit(`calendar-event-${r}`,
|
|
2127
|
+
const e = (r, i) => {
|
|
2128
|
+
this.emit(`calendar-event-${r}`, i);
|
|
2122
2129
|
};
|
|
2123
2130
|
this._busUnsubscribers.push(
|
|
2124
2131
|
t.on("event:add", (r) => {
|
|
@@ -2154,7 +2161,7 @@ const m = class m extends M {
|
|
|
2154
2161
|
var o, c;
|
|
2155
2162
|
if (!this._hasRendered)
|
|
2156
2163
|
return;
|
|
2157
|
-
const r = t.view !== (e == null ? void 0 : e.view),
|
|
2164
|
+
const r = t.view !== (e == null ? void 0 : e.view), i = ((o = t.currentDate) == null ? void 0 : o.getTime()) !== ((c = e == null ? void 0 : e.currentDate) == null ? void 0 : c.getTime()), s = t.events !== (e == null ? void 0 : e.events), n = t.loading !== (e == null ? void 0 : e.loading);
|
|
2158
2165
|
if (t.error !== (e == null ? void 0 : e.error)) {
|
|
2159
2166
|
this.render();
|
|
2160
2167
|
return;
|
|
@@ -2163,7 +2170,7 @@ const m = class m extends M {
|
|
|
2163
2170
|
this._updateLoadingState(t.loading);
|
|
2164
2171
|
return;
|
|
2165
2172
|
}
|
|
2166
|
-
r && (this.currentView = t.view), r ? (this._updateTitle(), this._updateViewButtons(), this._switchView()) :
|
|
2173
|
+
r && (this.currentView = t.view), r ? (this._updateTitle(), this._updateViewButtons(), this._switchView()) : i ? (this._updateTitle(), this._updateViewContent()) : s && this._updateViewContent();
|
|
2167
2174
|
}
|
|
2168
2175
|
/**
|
|
2169
2176
|
* Update only the title text (no DOM recreation)
|
|
@@ -2222,10 +2229,10 @@ const m = class m extends M {
|
|
|
2222
2229
|
getStyles() {
|
|
2223
2230
|
const t = this.getAttribute("height") || "800px";
|
|
2224
2231
|
return `
|
|
2225
|
-
${
|
|
2226
|
-
${
|
|
2227
|
-
${
|
|
2228
|
-
${
|
|
2232
|
+
${f.getBaseStyles()}
|
|
2233
|
+
${f.getButtonStyles()}
|
|
2234
|
+
${f.getGridStyles()}
|
|
2235
|
+
${f.getAnimations()}
|
|
2229
2236
|
|
|
2230
2237
|
:host {
|
|
2231
2238
|
--calendar-height: ${t};
|
|
@@ -2609,12 +2616,12 @@ const m = class m extends M {
|
|
|
2609
2616
|
`;
|
|
2610
2617
|
}
|
|
2611
2618
|
template() {
|
|
2612
|
-
const t = this.stateManager.getState(), { currentDate: e, view: r, loading:
|
|
2613
|
-
if (
|
|
2619
|
+
const t = this.stateManager.getState(), { currentDate: e, view: r, loading: i, error: s } = t;
|
|
2620
|
+
if (s)
|
|
2614
2621
|
return `
|
|
2615
2622
|
<div class="force-calendar">
|
|
2616
2623
|
<div class="fc-error">
|
|
2617
|
-
<p><strong>Error:</strong> ${
|
|
2624
|
+
<p><strong>Error:</strong> ${k.escapeHTML(s.message || "An error occurred")}</p>
|
|
2618
2625
|
</div>
|
|
2619
2626
|
</div>
|
|
2620
2627
|
`;
|
|
@@ -2654,11 +2661,11 @@ const m = class m extends M {
|
|
|
2654
2661
|
</header>
|
|
2655
2662
|
|
|
2656
2663
|
<div class="fc-body">
|
|
2657
|
-
<div class="fc-loading" style="display: ${
|
|
2664
|
+
<div class="fc-loading" style="display: ${i ? "flex" : "none"};">
|
|
2658
2665
|
<div class="fc-spinner"></div>
|
|
2659
2666
|
<span>Loading...</span>
|
|
2660
2667
|
</div>
|
|
2661
|
-
<div class="fc-view-container" style="display: ${
|
|
2668
|
+
<div class="fc-view-container" style="display: ${i ? "none" : "flex"};">
|
|
2662
2669
|
${this.renderView()}
|
|
2663
2670
|
</div>
|
|
2664
2671
|
</div>
|
|
@@ -2677,27 +2684,27 @@ const m = class m extends M {
|
|
|
2677
2684
|
return;
|
|
2678
2685
|
this._currentViewInstance && (this._currentViewInstance.cleanup && this._currentViewInstance.cleanup(), this._viewUnsubscribe && (this._viewUnsubscribe(), this._viewUnsubscribe = null));
|
|
2679
2686
|
try {
|
|
2680
|
-
const
|
|
2681
|
-
|
|
2682
|
-
} catch (
|
|
2683
|
-
console.error("[ForceCalendar] Error creating/rendering view:",
|
|
2687
|
+
const i = m.RENDERERS[this.currentView] || w, s = new i(t, this.stateManager);
|
|
2688
|
+
s._viewType = this.currentView, this._currentViewInstance = s, s.render();
|
|
2689
|
+
} catch (i) {
|
|
2690
|
+
console.error("[ForceCalendar] Error creating/rendering view:", i);
|
|
2684
2691
|
}
|
|
2685
2692
|
}
|
|
2686
|
-
this.$$("[data-action]").forEach((
|
|
2687
|
-
this.addListener(
|
|
2688
|
-
}), this.$$("[data-view]").forEach((
|
|
2689
|
-
this.addListener(
|
|
2693
|
+
this.$$("[data-action]").forEach((i) => {
|
|
2694
|
+
this.addListener(i, "click", this.handleNavigation);
|
|
2695
|
+
}), this.$$("[data-view]").forEach((i) => {
|
|
2696
|
+
this.addListener(i, "click", this.handleViewChange);
|
|
2690
2697
|
});
|
|
2691
2698
|
const e = this.$("#event-modal"), r = this.$("#create-event-btn");
|
|
2692
2699
|
r && e && this.addListener(r, "click", () => {
|
|
2693
2700
|
e.open(/* @__PURE__ */ new Date());
|
|
2694
|
-
}), this.addListener(this.shadowRoot, "day-click", (
|
|
2695
|
-
e && e.open(
|
|
2696
|
-
}), e && this.addListener(e, "save", (
|
|
2697
|
-
const
|
|
2701
|
+
}), this.addListener(this.shadowRoot, "day-click", (i) => {
|
|
2702
|
+
e && e.open(i.detail.date);
|
|
2703
|
+
}), e && this.addListener(e, "save", (i) => {
|
|
2704
|
+
const s = i.detail, n = window.crypto && typeof window.crypto.randomUUID == "function" ? window.crypto.randomUUID() : Math.random().toString(36).substring(2, 15);
|
|
2698
2705
|
this.stateManager.addEvent({
|
|
2699
2706
|
id: n,
|
|
2700
|
-
...
|
|
2707
|
+
...s
|
|
2701
2708
|
});
|
|
2702
2709
|
}), this._hasRendered = !0;
|
|
2703
2710
|
}
|
|
@@ -2722,15 +2729,15 @@ const m = class m extends M {
|
|
|
2722
2729
|
const r = this.stateManager.getState().config.locale;
|
|
2723
2730
|
switch (e) {
|
|
2724
2731
|
case "month":
|
|
2725
|
-
return
|
|
2732
|
+
return u.formatDate(t, "month", r);
|
|
2726
2733
|
case "week": {
|
|
2727
|
-
const
|
|
2728
|
-
return
|
|
2734
|
+
const i = u.startOfWeek(t), s = u.endOfWeek(t);
|
|
2735
|
+
return u.formatDateRange(i, s, r);
|
|
2729
2736
|
}
|
|
2730
2737
|
case "day":
|
|
2731
|
-
return
|
|
2738
|
+
return u.formatDate(t, "long", r);
|
|
2732
2739
|
default:
|
|
2733
|
-
return
|
|
2740
|
+
return u.formatDate(t, "month", r);
|
|
2734
2741
|
}
|
|
2735
2742
|
}
|
|
2736
2743
|
getIcon(t) {
|
|
@@ -2792,19 +2799,19 @@ v(m, "RENDERERS", {
|
|
|
2792
2799
|
week: z,
|
|
2793
2800
|
day: B
|
|
2794
2801
|
});
|
|
2795
|
-
let
|
|
2796
|
-
customElements.get("forcecal-main") || customElements.define("forcecal-main",
|
|
2802
|
+
let D = m;
|
|
2803
|
+
customElements.get("forcecal-main") || customElements.define("forcecal-main", D);
|
|
2797
2804
|
export {
|
|
2798
2805
|
M as BaseComponent,
|
|
2799
2806
|
E as BaseViewRenderer,
|
|
2800
|
-
|
|
2801
|
-
|
|
2807
|
+
k as DOMUtils,
|
|
2808
|
+
u as DateUtils,
|
|
2802
2809
|
B as DayViewRenderer,
|
|
2803
|
-
|
|
2804
|
-
|
|
2810
|
+
S as EventBus,
|
|
2811
|
+
D as ForceCalendar,
|
|
2805
2812
|
w as MonthViewRenderer,
|
|
2806
2813
|
I as StateManager,
|
|
2807
|
-
|
|
2814
|
+
f as StyleUtils,
|
|
2808
2815
|
z as WeekViewRenderer,
|
|
2809
2816
|
U as eventBus
|
|
2810
2817
|
};
|