calendarkit-pro 1.3.0 → 1.4.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/README.md +26 -3
- package/dist/index.d.mts +45 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +1235 -559
- package/dist/index.mjs +1201 -525
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/index.tsx
|
|
4
|
-
import
|
|
4
|
+
import React20, { useCallback as useCallback6, useId, useState as useState8, useMemo as useMemo4 } from "react";
|
|
5
5
|
import { DndContext, useSensor, useSensors, PointerSensor, DragOverlay } from "@dnd-kit/core";
|
|
6
6
|
import { createSnapModifier, restrictToWindowEdges } from "@dnd-kit/modifiers";
|
|
7
7
|
import { AnimatePresence as AnimatePresence3, motion as motion4 } from "framer-motion";
|
|
@@ -94,7 +94,8 @@ var CalendarHeader = ({
|
|
|
94
94
|
variant: "ghost",
|
|
95
95
|
size: "icon",
|
|
96
96
|
className: "text-muted-foreground hover:text-foreground hover:bg-accent/80 rounded-xl h-10 w-10 hidden md:inline-flex transition-all duration-200",
|
|
97
|
-
onClick: onMenuClick
|
|
97
|
+
onClick: onMenuClick,
|
|
98
|
+
"aria-label": translations.toggleSidebar
|
|
98
99
|
},
|
|
99
100
|
/* @__PURE__ */ React2.createElement(Menu, { className: "h-5 w-5" })
|
|
100
101
|
), /* @__PURE__ */ React2.createElement(
|
|
@@ -111,7 +112,8 @@ var CalendarHeader = ({
|
|
|
111
112
|
variant: "ghost",
|
|
112
113
|
size: "icon",
|
|
113
114
|
onClick: onPrev,
|
|
114
|
-
className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200"
|
|
115
|
+
className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200",
|
|
116
|
+
"aria-label": translations.previous
|
|
115
117
|
},
|
|
116
118
|
/* @__PURE__ */ React2.createElement(ChevronLeft, { className: "h-4 w-4 text-muted-foreground" })
|
|
117
119
|
), /* @__PURE__ */ React2.createElement(
|
|
@@ -120,7 +122,8 @@ var CalendarHeader = ({
|
|
|
120
122
|
variant: "ghost",
|
|
121
123
|
size: "icon",
|
|
122
124
|
onClick: onNext,
|
|
123
|
-
className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200"
|
|
125
|
+
className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200",
|
|
126
|
+
"aria-label": translations.next
|
|
124
127
|
},
|
|
125
128
|
/* @__PURE__ */ React2.createElement(ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
|
|
126
129
|
)), /* @__PURE__ */ React2.createElement("div", { className: "ml-2 md:ml-4" }, /* @__PURE__ */ React2.createElement("h2", { className: "text-lg md:text-xl font-semibold text-foreground whitespace-nowrap capitalize tracking-tight" }, format(currentDate, "MMMM yyyy", { locale }))))), /* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-2 md:gap-3 w-full md:w-auto justify-end" }, onLanguageChange && language && /* @__PURE__ */ React2.createElement(
|
|
@@ -129,6 +132,7 @@ var CalendarHeader = ({
|
|
|
129
132
|
variant: "ghost",
|
|
130
133
|
size: "sm",
|
|
131
134
|
onClick: () => onLanguageChange(language === "en" ? "fr" : "en"),
|
|
135
|
+
"aria-label": translations.switchLanguage,
|
|
132
136
|
className: "h-9 px-3 rounded-xl text-xs font-semibold text-muted-foreground hover:text-foreground hover:bg-accent/80 transition-all duration-200 uppercase tracking-wider"
|
|
133
137
|
},
|
|
134
138
|
language
|
|
@@ -138,7 +142,8 @@ var CalendarHeader = ({
|
|
|
138
142
|
variant: "ghost",
|
|
139
143
|
size: "icon",
|
|
140
144
|
className: "rounded-xl h-9 w-9 hover:bg-accent/80 transition-all duration-200",
|
|
141
|
-
onClick: onThemeToggle
|
|
145
|
+
onClick: onThemeToggle,
|
|
146
|
+
"aria-label": translations.toggleTheme
|
|
142
147
|
},
|
|
143
148
|
isDarkMode ? /* @__PURE__ */ React2.createElement(Sun, { className: "h-4 w-4 text-amber-500" }) : /* @__PURE__ */ React2.createElement(Moon, { className: "h-4 w-4 text-muted-foreground" })
|
|
144
149
|
), !hideViewSwitcher && /* @__PURE__ */ React2.createElement("div", { className: "flex items-center bg-muted/50 backdrop-blur-sm rounded-xl p-1" }, viewConfig.map(({ key, icon: Icon }) => /* @__PURE__ */ React2.createElement(
|
|
@@ -148,6 +153,8 @@ var CalendarHeader = ({
|
|
|
148
153
|
variant: "ghost",
|
|
149
154
|
size: "sm",
|
|
150
155
|
onClick: () => onViewChange(key),
|
|
156
|
+
"aria-pressed": view === key,
|
|
157
|
+
"aria-label": translations[key],
|
|
151
158
|
className: cn(
|
|
152
159
|
"h-8 px-3 text-xs rounded-lg transition-all duration-200 gap-1.5",
|
|
153
160
|
view === key ? "bg-background shadow-sm text-foreground font-medium border-[0.5px] border-border/50" : "text-muted-foreground hover:text-foreground hover:bg-background/50"
|
|
@@ -192,7 +199,8 @@ var MiniCalendar = ({
|
|
|
192
199
|
onDateChange,
|
|
193
200
|
onViewChange,
|
|
194
201
|
className,
|
|
195
|
-
locale
|
|
202
|
+
locale,
|
|
203
|
+
labels
|
|
196
204
|
}) => {
|
|
197
205
|
const [viewDate, setViewDate] = React3.useState(currentDate);
|
|
198
206
|
React3.useEffect(() => {
|
|
@@ -230,7 +238,7 @@ var MiniCalendar = ({
|
|
|
230
238
|
size: "icon",
|
|
231
239
|
className: "h-7 w-7 rounded-md hover:bg-background/80 transition-all",
|
|
232
240
|
onClick: handlePrev,
|
|
233
|
-
"aria-label": "Previous month"
|
|
241
|
+
"aria-label": labels?.previousMonth || "Previous month"
|
|
234
242
|
},
|
|
235
243
|
/* @__PURE__ */ React3.createElement(ChevronLeft2, { className: "h-4 w-4" })
|
|
236
244
|
), /* @__PURE__ */ React3.createElement(
|
|
@@ -240,7 +248,7 @@ var MiniCalendar = ({
|
|
|
240
248
|
size: "icon",
|
|
241
249
|
className: "h-7 w-7 rounded-md hover:bg-background/80 transition-all",
|
|
242
250
|
onClick: handleNext,
|
|
243
|
-
"aria-label": "Next month"
|
|
251
|
+
"aria-label": labels?.nextMonth || "Next month"
|
|
244
252
|
},
|
|
245
253
|
/* @__PURE__ */ React3.createElement(ChevronRight2, { className: "h-4 w-4" })
|
|
246
254
|
))), /* @__PURE__ */ React3.createElement("div", { className: "grid grid-cols-7 gap-y-2 text-center mb-2" }, weekDays.map((day, i) => /* @__PURE__ */ React3.createElement("div", { key: `${day}-${i}`, className: "text-[10px] text-muted-foreground/70 font-semibold uppercase" }, day))), /* @__PURE__ */ React3.createElement("div", { className: "grid grid-cols-7 gap-y-1 text-center" }, days.map((day) => {
|
|
@@ -340,7 +348,50 @@ var en = {
|
|
|
340
348
|
allCaughtUp: "All caught up!",
|
|
341
349
|
noEventsScheduled: "No events scheduled",
|
|
342
350
|
noUpcoming: "Your schedule is clear",
|
|
343
|
-
noUpcomingHint: "No upcoming events to show. Create a new event to start planning."
|
|
351
|
+
noUpcomingHint: "No upcoming events to show. Create a new event to start planning.",
|
|
352
|
+
newEvent: "New Event",
|
|
353
|
+
saveChanges: "Save Changes",
|
|
354
|
+
close: "Close",
|
|
355
|
+
noTitle: "(No title)",
|
|
356
|
+
openInMaps: "Open in maps",
|
|
357
|
+
notesLabel: "Notes",
|
|
358
|
+
addNotes: "Add description or notes...",
|
|
359
|
+
attachments: "Attachments",
|
|
360
|
+
reminders: "Reminders",
|
|
361
|
+
add: "Add",
|
|
362
|
+
calendar: "Calendar",
|
|
363
|
+
select: "Select",
|
|
364
|
+
addLocation: "Add location",
|
|
365
|
+
guestSingular: "Guest",
|
|
366
|
+
addGuestPlaceholder: "Add a guest email and press Enter",
|
|
367
|
+
invalidEmail: "Enter a valid email address",
|
|
368
|
+
removeGuest: "Remove {email}",
|
|
369
|
+
reminderAtTime: "At time of event",
|
|
370
|
+
reminderMinutes: "{n} minutes before",
|
|
371
|
+
reminderHour: "1 hour before",
|
|
372
|
+
reminderHours: "{n} hours before",
|
|
373
|
+
reminderDay: "1 day before",
|
|
374
|
+
reminderDays: "{n} days before",
|
|
375
|
+
reminderWeek: "1 week before",
|
|
376
|
+
removeReminder: "Remove reminder",
|
|
377
|
+
durationMinutes: "{n} min",
|
|
378
|
+
durationHours: "{n} hr",
|
|
379
|
+
durationHoursMinutes: "{h} hr {m} min",
|
|
380
|
+
moreEvents: "+{n} more",
|
|
381
|
+
idLabel: "ID: {id}",
|
|
382
|
+
previous: "Previous",
|
|
383
|
+
next: "Next",
|
|
384
|
+
previousMonth: "Previous month",
|
|
385
|
+
nextMonth: "Next month",
|
|
386
|
+
toggleSidebar: "Toggle sidebar",
|
|
387
|
+
toggleTheme: "Toggle dark mode",
|
|
388
|
+
switchLanguage: "Switch language",
|
|
389
|
+
eventColor: "Event color",
|
|
390
|
+
showLess: "Show less",
|
|
391
|
+
continuesBefore: "Started earlier",
|
|
392
|
+
continuesAfter: "Continues later",
|
|
393
|
+
durationDay: "1 day",
|
|
394
|
+
durationDays: "{n} days"
|
|
344
395
|
};
|
|
345
396
|
var fr = {
|
|
346
397
|
today: "Aujourd'hui",
|
|
@@ -409,7 +460,50 @@ var fr = {
|
|
|
409
460
|
allCaughtUp: "Tout est \xE0 jour !",
|
|
410
461
|
noEventsScheduled: "Aucun \xE9v\xE9nement pr\xE9vu",
|
|
411
462
|
noUpcoming: "Votre planning est libre",
|
|
412
|
-
noUpcomingHint: "Aucun \xE9v\xE9nement \xE0 venir. Cr\xE9ez un nouvel \xE9v\xE9nement pour commencer \xE0 planifier."
|
|
463
|
+
noUpcomingHint: "Aucun \xE9v\xE9nement \xE0 venir. Cr\xE9ez un nouvel \xE9v\xE9nement pour commencer \xE0 planifier.",
|
|
464
|
+
newEvent: "Nouvel \xE9v\xE9nement",
|
|
465
|
+
saveChanges: "Enregistrer",
|
|
466
|
+
close: "Fermer",
|
|
467
|
+
noTitle: "(Sans titre)",
|
|
468
|
+
openInMaps: "Ouvrir dans Maps",
|
|
469
|
+
notesLabel: "Notes",
|
|
470
|
+
addNotes: "Ajouter une description ou des notes\u2026",
|
|
471
|
+
attachments: "Pi\xE8ces jointes",
|
|
472
|
+
reminders: "Rappels",
|
|
473
|
+
add: "Ajouter",
|
|
474
|
+
calendar: "Calendrier",
|
|
475
|
+
select: "Choisir",
|
|
476
|
+
addLocation: "Ajouter un lieu",
|
|
477
|
+
guestSingular: "Invit\xE9",
|
|
478
|
+
addGuestPlaceholder: "Ajoutez l'e-mail d'un invit\xE9 puis Entr\xE9e",
|
|
479
|
+
invalidEmail: "Saisissez une adresse e-mail valide",
|
|
480
|
+
removeGuest: "Retirer {email}",
|
|
481
|
+
reminderAtTime: "Au moment de l'\xE9v\xE9nement",
|
|
482
|
+
reminderMinutes: "{n} minutes avant",
|
|
483
|
+
reminderHour: "1 heure avant",
|
|
484
|
+
reminderHours: "{n} heures avant",
|
|
485
|
+
reminderDay: "1 jour avant",
|
|
486
|
+
reminderDays: "{n} jours avant",
|
|
487
|
+
reminderWeek: "1 semaine avant",
|
|
488
|
+
removeReminder: "Supprimer le rappel",
|
|
489
|
+
durationMinutes: "{n} min",
|
|
490
|
+
durationHours: "{n} h",
|
|
491
|
+
durationHoursMinutes: "{h} h {m} min",
|
|
492
|
+
moreEvents: "+{n} de plus",
|
|
493
|
+
idLabel: "ID : {id}",
|
|
494
|
+
previous: "Pr\xE9c\xE9dent",
|
|
495
|
+
next: "Suivant",
|
|
496
|
+
previousMonth: "Mois pr\xE9c\xE9dent",
|
|
497
|
+
nextMonth: "Mois suivant",
|
|
498
|
+
toggleSidebar: "Afficher ou masquer la barre lat\xE9rale",
|
|
499
|
+
toggleTheme: "Basculer le th\xE8me sombre",
|
|
500
|
+
switchLanguage: "Changer de langue",
|
|
501
|
+
eventColor: "Couleur de l'\xE9v\xE9nement",
|
|
502
|
+
showLess: "R\xE9duire",
|
|
503
|
+
continuesBefore: "A commenc\xE9 avant",
|
|
504
|
+
continuesAfter: "Continue apr\xE8s",
|
|
505
|
+
durationDay: "1 jour",
|
|
506
|
+
durationDays: "{n} jours"
|
|
413
507
|
};
|
|
414
508
|
|
|
415
509
|
// src/core/format.ts
|
|
@@ -452,7 +546,18 @@ function timeZoneAbbreviation(date, timeZone) {
|
|
|
452
546
|
}
|
|
453
547
|
}
|
|
454
548
|
function resolveTranslations(language, overrides) {
|
|
455
|
-
|
|
549
|
+
const defined = Object.fromEntries(Object.entries(overrides ?? {}).filter(([, value]) => value !== void 0));
|
|
550
|
+
return { ...language === "fr" ? fr : en, ...defined };
|
|
551
|
+
}
|
|
552
|
+
function interpolate(template, values) {
|
|
553
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => key in values ? String(values[key]) : match);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// src/core/color.ts
|
|
557
|
+
var SAFE_COLOR = /^[#\w\s%.,/()+-]+$/;
|
|
558
|
+
var FORBIDDEN = /url\(|expression\(/i;
|
|
559
|
+
function safeColor(value, fallback) {
|
|
560
|
+
return value && SAFE_COLOR.test(value.trim()) && !FORBIDDEN.test(value) ? value.trim() : fallback;
|
|
456
561
|
}
|
|
457
562
|
|
|
458
563
|
// src/components/Sidebar.tsx
|
|
@@ -480,12 +585,6 @@ var Sidebar = ({
|
|
|
480
585
|
const timer = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
481
586
|
return () => clearInterval(timer);
|
|
482
587
|
}, []);
|
|
483
|
-
const defaultCalendars = [
|
|
484
|
-
{ id: "1", label: "My Calendar", color: "#3b82f6", active: true },
|
|
485
|
-
{ id: "2", label: "Birthdays", color: "#10b981", active: true },
|
|
486
|
-
{ id: "3", label: "Tasks", color: "#6366f1", active: true }
|
|
487
|
-
];
|
|
488
|
-
const displayCalendars = calendars || defaultCalendars;
|
|
489
588
|
const getAcronym = (tz) => !tz || !now ? "LOC" : timeZoneAbbreviation(now, tz);
|
|
490
589
|
const timezones = [
|
|
491
590
|
{ value: "", label: translations?.localTime || "Local Time", acronym: "LOC" },
|
|
@@ -535,7 +634,16 @@ var Sidebar = ({
|
|
|
535
634
|
},
|
|
536
635
|
/* @__PURE__ */ React4.createElement(Plus, { className: "w-5 h-5" }),
|
|
537
636
|
/* @__PURE__ */ React4.createElement("span", { className: "text-sm" }, translations?.create || "Create")
|
|
538
|
-
)), /* @__PURE__ */ React4.createElement(
|
|
637
|
+
)), /* @__PURE__ */ React4.createElement(
|
|
638
|
+
MiniCalendar,
|
|
639
|
+
{
|
|
640
|
+
currentDate,
|
|
641
|
+
onDateChange,
|
|
642
|
+
onViewChange,
|
|
643
|
+
locale,
|
|
644
|
+
labels: { previousMonth: translations?.previousMonth, nextMonth: translations?.nextMonth }
|
|
645
|
+
}
|
|
646
|
+
), /* @__PURE__ */ React4.createElement("div", { className: "flex-1 px-4 space-y-5 mt-5" }, calendars && calendars.length > 0 && /* @__PURE__ */ React4.createElement("div", { className: "bg-muted/20 rounded-2xl p-3 border-[0px] border-border/30" }, /* @__PURE__ */ React4.createElement(
|
|
539
647
|
"div",
|
|
540
648
|
{
|
|
541
649
|
className: "flex items-center justify-between cursor-pointer hover:bg-accent/50 p-2 -m-1 rounded-xl mb-2 transition-all duration-200",
|
|
@@ -543,41 +651,40 @@ var Sidebar = ({
|
|
|
543
651
|
},
|
|
544
652
|
/* @__PURE__ */ React4.createElement("span", { className: "text-sm font-semibold text-foreground" }, translations?.calendars || "Calendars"),
|
|
545
653
|
/* @__PURE__ */ React4.createElement(ChevronDown, { className: cn("w-4 h-4 text-muted-foreground transition-transform duration-200", calendarsOpen && "rotate-180") })
|
|
546
|
-
), calendarsOpen && /* @__PURE__ */ React4.createElement("div", { className: "space-y-1" },
|
|
654
|
+
), calendarsOpen && /* @__PURE__ */ React4.createElement("div", { className: "space-y-1" }, calendars.map((cal) => /* @__PURE__ */ React4.createElement(
|
|
547
655
|
"div",
|
|
548
656
|
{
|
|
549
657
|
key: cal.id,
|
|
550
658
|
className: "flex items-center gap-3 py-2 px-2 hover:bg-accent/60 rounded-xl cursor-pointer group transition-all duration-200",
|
|
551
659
|
onClick: () => onCalendarToggle?.(cal.id, !(cal.active ?? true))
|
|
552
660
|
},
|
|
553
|
-
/* @__PURE__ */ React4.createElement(
|
|
554
|
-
"
|
|
661
|
+
/* @__PURE__ */ React4.createElement(
|
|
662
|
+
"div",
|
|
555
663
|
{
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
`)),
|
|
664
|
+
className: "relative flex items-center justify-center",
|
|
665
|
+
style: { "--cal-color": safeColor(cal.color, "hsl(var(--primary))") }
|
|
666
|
+
},
|
|
667
|
+
/* @__PURE__ */ React4.createElement(
|
|
668
|
+
"input",
|
|
669
|
+
{
|
|
670
|
+
type: "checkbox",
|
|
671
|
+
checked: cal.active ?? true,
|
|
672
|
+
onChange: (e) => {
|
|
673
|
+
e.stopPropagation();
|
|
674
|
+
onCalendarToggle?.(cal.id, e.target.checked);
|
|
675
|
+
},
|
|
676
|
+
"aria-label": cal.label,
|
|
677
|
+
className: "peer h-5 w-5 rounded-md border-2 border-border/60 cursor-pointer appearance-none checked:border-transparent checked:bg-[var(--cal-color)] focus:ring-2 focus:ring-[var(--cal-color)] transition-all duration-200"
|
|
678
|
+
}
|
|
679
|
+
),
|
|
680
|
+
/* @__PURE__ */ React4.createElement("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none opacity-0 peer-checked:opacity-100 transition-opacity" }, /* @__PURE__ */ React4.createElement("svg", { className: "w-3.5 h-3.5 text-white", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3 }, /* @__PURE__ */ React4.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" })))
|
|
681
|
+
),
|
|
575
682
|
/* @__PURE__ */ React4.createElement("div", { className: "flex items-center gap-2 flex-1 min-w-0" }, /* @__PURE__ */ React4.createElement("span", { className: "text-sm text-foreground/90 truncate font-medium" }, cal.label)),
|
|
576
683
|
/* @__PURE__ */ React4.createElement(
|
|
577
684
|
"div",
|
|
578
685
|
{
|
|
579
686
|
className: "w-2 h-2 rounded-full opacity-60 group-hover:opacity-100 transition-opacity",
|
|
580
|
-
style: { backgroundColor: cal.color }
|
|
687
|
+
style: { backgroundColor: safeColor(cal.color, "hsl(var(--primary))") }
|
|
581
688
|
}
|
|
582
689
|
)
|
|
583
690
|
))))), /* @__PURE__ */ React4.createElement("div", { className: "mt-auto px-4 pt-5" }, /* @__PURE__ */ React4.createElement("div", { className: "bg-muted/20 rounded-2xl p-3" }, /* @__PURE__ */ React4.createElement("div", { className: "flex items-center gap-2 mb-3" }, /* @__PURE__ */ React4.createElement("div", { className: "p-1.5 bg-primary/10 rounded-lg" }, /* @__PURE__ */ React4.createElement(Globe, { className: "w-4 h-4 text-primary" })), /* @__PURE__ */ React4.createElement("span", { className: "text-sm font-semibold text-foreground" }, translations?.timezone || "Timezone")), /* @__PURE__ */ React4.createElement("div", { className: "relative" }, /* @__PURE__ */ React4.createElement(
|
|
@@ -606,11 +713,14 @@ var Sidebar = ({
|
|
|
606
713
|
};
|
|
607
714
|
|
|
608
715
|
// src/views/MonthView.tsx
|
|
609
|
-
import
|
|
610
|
-
import { format as
|
|
716
|
+
import React8, { useMemo } from "react";
|
|
717
|
+
import { format as format8, isSameDay as isSameDay3, isSameMonth as isSameMonth2 } from "date-fns";
|
|
611
718
|
|
|
612
719
|
// src/core/events.ts
|
|
613
|
-
import { addDays, format as format6, startOfDay as
|
|
720
|
+
import { addDays as addDays2, format as format6, startOfDay as startOfDay3 } from "date-fns";
|
|
721
|
+
|
|
722
|
+
// src/core/allDay.ts
|
|
723
|
+
import { addDays, differenceInCalendarDays, startOfDay as startOfDay2 } from "date-fns";
|
|
614
724
|
|
|
615
725
|
// src/core/timezone.ts
|
|
616
726
|
import { format as format5, isSameDay as isSameDay2, startOfDay } from "date-fns";
|
|
@@ -670,6 +780,91 @@ function displayToday(tz, now = /* @__PURE__ */ new Date()) {
|
|
|
670
780
|
return startOfDay(toDisplay(now, tz));
|
|
671
781
|
}
|
|
672
782
|
|
|
783
|
+
// src/core/allDay.ts
|
|
784
|
+
var DAY_EVENT_MIN_MS = 24 * 60 * 60 * 1e3;
|
|
785
|
+
function isDayEvent(event) {
|
|
786
|
+
return event.allDay === true || event.end.getTime() - event.start.getTime() >= DAY_EVENT_MIN_MS;
|
|
787
|
+
}
|
|
788
|
+
var isMidnight = (date) => date.getHours() === 0 && date.getMinutes() === 0 && date.getSeconds() === 0 && date.getMilliseconds() === 0;
|
|
789
|
+
var isUtcMidnight = (date) => date.getUTCHours() === 0 && date.getUTCMinutes() === 0 && date.getUTCSeconds() === 0 && date.getUTCMilliseconds() === 0;
|
|
790
|
+
function toCalendarMidnight(date) {
|
|
791
|
+
return !isMidnight(date) && isUtcMidnight(date) ? new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) : date;
|
|
792
|
+
}
|
|
793
|
+
function calendarDay(date) {
|
|
794
|
+
if (isMidnight(date)) return { day: startOfDay2(date), midnight: true };
|
|
795
|
+
if (isUtcMidnight(date)) return { day: new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()), midnight: true };
|
|
796
|
+
return { day: startOfDay2(date), midnight: false };
|
|
797
|
+
}
|
|
798
|
+
function dayEventSpan(event, tz) {
|
|
799
|
+
if (event.allDay) {
|
|
800
|
+
const firstDay2 = calendarDay(event.start).day;
|
|
801
|
+
if (event.end.getTime() <= event.start.getTime()) return { firstDay: firstDay2, lastDay: firstDay2 };
|
|
802
|
+
const end = calendarDay(event.end);
|
|
803
|
+
const lastDay2 = end.midnight ? addDays(end.day, -1) : end.day;
|
|
804
|
+
return { firstDay: firstDay2, lastDay: lastDay2 < firstDay2 ? firstDay2 : lastDay2 };
|
|
805
|
+
}
|
|
806
|
+
const firstDay = startOfDay2(toDisplay(event.start, tz));
|
|
807
|
+
const lastDay = startOfDay2(toDisplay(new Date(event.end.getTime() - 1), tz));
|
|
808
|
+
return { firstDay, lastDay: lastDay < firstDay ? firstDay : lastDay };
|
|
809
|
+
}
|
|
810
|
+
var partitionCache = /* @__PURE__ */ new WeakMap();
|
|
811
|
+
function partitionDayEvents(events, tz) {
|
|
812
|
+
let byZone = partitionCache.get(events);
|
|
813
|
+
if (!byZone) {
|
|
814
|
+
byZone = /* @__PURE__ */ new Map();
|
|
815
|
+
partitionCache.set(events, byZone);
|
|
816
|
+
}
|
|
817
|
+
const key = tz ?? "";
|
|
818
|
+
let result = byZone.get(key);
|
|
819
|
+
if (!result) {
|
|
820
|
+
const dayEvents = [];
|
|
821
|
+
const timedEvents = [];
|
|
822
|
+
for (const event of events) (isDayEvent(event) ? dayEvents : timedEvents).push(event);
|
|
823
|
+
result = { dayEvents, timedEvents };
|
|
824
|
+
byZone.set(key, result);
|
|
825
|
+
}
|
|
826
|
+
return result;
|
|
827
|
+
}
|
|
828
|
+
var rowCache = /* @__PURE__ */ new WeakMap();
|
|
829
|
+
function layoutDayRow(days, dayEvents, tz) {
|
|
830
|
+
if (days.length === 0) return { segments: [], laneCount: 0 };
|
|
831
|
+
const rowStart = startOfDay2(days[0]);
|
|
832
|
+
const columns = days.length;
|
|
833
|
+
const key = `${tz ?? ""}|${rowStart.getTime()}|${columns}`;
|
|
834
|
+
let cache = rowCache.get(dayEvents);
|
|
835
|
+
if (!cache) {
|
|
836
|
+
cache = /* @__PURE__ */ new Map();
|
|
837
|
+
rowCache.set(dayEvents, cache);
|
|
838
|
+
}
|
|
839
|
+
const cached = cache.get(key);
|
|
840
|
+
if (cached) return cached;
|
|
841
|
+
const unplaced = [];
|
|
842
|
+
for (const event of dayEvents) {
|
|
843
|
+
const { firstDay, lastDay } = dayEventSpan(event, tz);
|
|
844
|
+
const first = differenceInCalendarDays(firstDay, rowStart);
|
|
845
|
+
const last = differenceInCalendarDays(lastDay, rowStart);
|
|
846
|
+
if (last < 0 || first >= columns) continue;
|
|
847
|
+
const startCol = Math.max(first, 0);
|
|
848
|
+
const endCol = Math.min(last, columns - 1);
|
|
849
|
+
unplaced.push({ event, startCol, span: endCol - startCol + 1, continuesBefore: first < 0, continuesAfter: last >= columns });
|
|
850
|
+
}
|
|
851
|
+
unplaced.sort((a, b) => a.startCol - b.startCol || b.span - a.span || (a.event.id < b.event.id ? -1 : a.event.id > b.event.id ? 1 : 0));
|
|
852
|
+
const occupied = [];
|
|
853
|
+
const segments = [];
|
|
854
|
+
for (const segment of unplaced) {
|
|
855
|
+
let lane = occupied.findIndex((row) => row.slice(segment.startCol, segment.startCol + segment.span).every((taken) => !taken));
|
|
856
|
+
if (lane === -1) {
|
|
857
|
+
lane = occupied.length;
|
|
858
|
+
occupied.push(new Array(columns).fill(false));
|
|
859
|
+
}
|
|
860
|
+
for (let c = segment.startCol; c < segment.startCol + segment.span; c++) occupied[lane][c] = true;
|
|
861
|
+
segments.push({ ...segment, lane });
|
|
862
|
+
}
|
|
863
|
+
const layout = { segments, laneCount: occupied.length };
|
|
864
|
+
cache.set(key, layout);
|
|
865
|
+
return layout;
|
|
866
|
+
}
|
|
867
|
+
|
|
673
868
|
// src/core/events.ts
|
|
674
869
|
var toDate = (value) => value === void 0 || value === null ? void 0 : value instanceof Date ? value : new Date(value);
|
|
675
870
|
var isValidDate = (date) => !!date && !Number.isNaN(date.getTime());
|
|
@@ -678,29 +873,35 @@ var normalizedList = /* @__PURE__ */ new WeakMap();
|
|
|
678
873
|
function normalizeEvent(event) {
|
|
679
874
|
const cached = normalizedEvent.get(event);
|
|
680
875
|
if (cached !== void 0) return cached;
|
|
681
|
-
const
|
|
682
|
-
const
|
|
876
|
+
const day = (value) => event.allDay && value ? toCalendarMidnight(value) : value;
|
|
877
|
+
const start = day(toDate(event.start));
|
|
878
|
+
const end = day(toDate(event.end));
|
|
683
879
|
let result = null;
|
|
684
880
|
if (!isValidDate(start) || !isValidDate(end)) {
|
|
685
881
|
warnOnce(`invalid-date:${event.id}`, `Event "${event.id}" has an invalid start or end date and was skipped.`);
|
|
686
882
|
} else if (end.getTime() < start.getTime()) {
|
|
687
883
|
warnOnce(`end-before-start:${event.id}`, `Event "${event.id}" ends before it starts and was skipped.`);
|
|
688
884
|
} else {
|
|
689
|
-
const needsCopy = start !== event.start || end !== event.end || needsRecurrenceCopy(event);
|
|
885
|
+
const needsCopy = start !== event.start || end !== event.end || needsRecurrenceCopy(event) || !!event.allDay && dateOnlyRecurrence(event);
|
|
690
886
|
result = needsCopy ? {
|
|
691
887
|
...event,
|
|
692
888
|
start,
|
|
693
889
|
end,
|
|
694
890
|
recurrence: event.recurrence && {
|
|
695
891
|
...event.recurrence,
|
|
696
|
-
until: toDate(event.recurrence.until),
|
|
697
|
-
exdates: event.recurrence.exdates?.map((d) => toDate(d))
|
|
892
|
+
until: day(toDate(event.recurrence.until)),
|
|
893
|
+
exdates: event.recurrence.exdates?.map((d) => day(toDate(d)))
|
|
698
894
|
}
|
|
699
895
|
} : event;
|
|
700
896
|
}
|
|
701
897
|
normalizedEvent.set(event, result);
|
|
702
898
|
return result;
|
|
703
899
|
}
|
|
900
|
+
function dateOnlyRecurrence(event) {
|
|
901
|
+
const r = event.recurrence;
|
|
902
|
+
const changes = (d) => d instanceof Date && toCalendarMidnight(d) !== d;
|
|
903
|
+
return !!r && (changes(r.until) || !!r.exdates?.some(changes));
|
|
904
|
+
}
|
|
704
905
|
function needsRecurrenceCopy(event) {
|
|
705
906
|
const r = event.recurrence;
|
|
706
907
|
if (!r) return false;
|
|
@@ -761,10 +962,10 @@ function segmentsByDisplayDay(events, tz, range) {
|
|
|
761
962
|
const rawEnd = toDisplay(event.end, tz);
|
|
762
963
|
const wallEnd = rawEnd < wallStart ? wallStart : rawEnd;
|
|
763
964
|
if (range && (wallEnd < range.start || wallStart >= range.end)) continue;
|
|
764
|
-
let day =
|
|
965
|
+
let day = startOfDay3(range && wallStart < range.start ? range.start : wallStart);
|
|
765
966
|
const stop = range && wallEnd > range.end ? range.end : wallEnd;
|
|
766
967
|
do {
|
|
767
|
-
const next =
|
|
968
|
+
const next = addDays2(day, 1);
|
|
768
969
|
const start = wallStart > day ? wallStart : day;
|
|
769
970
|
const end = wallEnd < next ? wallEnd : next;
|
|
770
971
|
if (end > start || wallStart.getTime() === wallEnd.getTime()) {
|
|
@@ -781,25 +982,153 @@ function segmentsByDisplayDay(events, tz, range) {
|
|
|
781
982
|
});
|
|
782
983
|
}
|
|
783
984
|
|
|
784
|
-
// src/components/
|
|
785
|
-
import React5 from "react";
|
|
985
|
+
// src/components/AllDayBar.tsx
|
|
986
|
+
import React5, { useRef, useState as useState2 } from "react";
|
|
786
987
|
import { useDraggable } from "@dnd-kit/core";
|
|
787
988
|
import { CSS } from "@dnd-kit/utilities";
|
|
989
|
+
import { addDays as addDays3, differenceInCalendarDays as differenceInCalendarDays2, format as format7 } from "date-fns";
|
|
990
|
+
var AllDayBarImpl = ({
|
|
991
|
+
segment,
|
|
992
|
+
rowDays,
|
|
993
|
+
laneHeight,
|
|
994
|
+
timezone,
|
|
995
|
+
locale,
|
|
996
|
+
translations,
|
|
997
|
+
readonly,
|
|
998
|
+
onEventClick,
|
|
999
|
+
onEventContextMenu,
|
|
1000
|
+
onDayEventResize
|
|
1001
|
+
}) => {
|
|
1002
|
+
const { event, startCol, span, lane, continuesBefore, continuesAfter } = segment;
|
|
1003
|
+
const columns = rowDays.length;
|
|
1004
|
+
const { firstDay, lastDay } = dayEventSpan(event, timezone);
|
|
1005
|
+
const segmentOffset = differenceInCalendarDays2(rowDays[startCol], firstDay);
|
|
1006
|
+
const dragData = useRef({ event, grabDayOffset: segmentOffset });
|
|
1007
|
+
dragData.current.event = event;
|
|
1008
|
+
const dragDisabled = readonly || isEventDragDisabled(event);
|
|
1009
|
+
const { attributes, listeners, setNodeRef, transform, isDragging } = useDraggable({
|
|
1010
|
+
id: `${event.id}@day@${format7(rowDays[0], "yyyy-MM-dd")}`,
|
|
1011
|
+
data: dragData.current,
|
|
1012
|
+
disabled: dragDisabled
|
|
1013
|
+
});
|
|
1014
|
+
const [resizeCols, setResizeCols] = useState2(0);
|
|
1015
|
+
const ignoreClick = useRef(false);
|
|
1016
|
+
const canResize = !readonly && !continuesAfter && !isEventResizeDisabled(event) && !!onDayEventResize;
|
|
1017
|
+
const shownSpan = Math.max(1, Math.min(span + resizeCols, columns - startCol));
|
|
1018
|
+
const handlePointerDownCapture = (e) => {
|
|
1019
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
1020
|
+
const dayWithin = rect.width > 0 ? Math.floor((e.clientX - rect.left) / rect.width * span) : 0;
|
|
1021
|
+
dragData.current.grabDayOffset = segmentOffset + Math.min(Math.max(dayWithin, 0), span - 1);
|
|
1022
|
+
};
|
|
1023
|
+
const handleResizeStart = (e) => {
|
|
1024
|
+
e.stopPropagation();
|
|
1025
|
+
e.preventDefault();
|
|
1026
|
+
const bar = e.currentTarget.parentElement;
|
|
1027
|
+
const columnWidth = bar.getBoundingClientRect().width / span || 1;
|
|
1028
|
+
const startX = e.clientX;
|
|
1029
|
+
let delta = 0;
|
|
1030
|
+
const onMove = (moveEvent) => {
|
|
1031
|
+
delta = Math.round((moveEvent.clientX - startX) / columnWidth);
|
|
1032
|
+
setResizeCols(delta);
|
|
1033
|
+
};
|
|
1034
|
+
const stop = () => {
|
|
1035
|
+
document.removeEventListener("pointermove", onMove);
|
|
1036
|
+
document.removeEventListener("pointerup", onUp);
|
|
1037
|
+
document.removeEventListener("pointercancel", stop);
|
|
1038
|
+
setResizeCols(0);
|
|
1039
|
+
};
|
|
1040
|
+
const onUp = () => {
|
|
1041
|
+
stop();
|
|
1042
|
+
ignoreClick.current = true;
|
|
1043
|
+
setTimeout(() => {
|
|
1044
|
+
ignoreClick.current = false;
|
|
1045
|
+
}, 0);
|
|
1046
|
+
if (delta !== 0) onDayEventResize?.(event, addDays3(rowDays[startCol + span - 1], delta));
|
|
1047
|
+
};
|
|
1048
|
+
document.addEventListener("pointermove", onMove);
|
|
1049
|
+
document.addEventListener("pointerup", onUp);
|
|
1050
|
+
document.addEventListener("pointercancel", stop);
|
|
1051
|
+
};
|
|
1052
|
+
const color = event.color || "hsl(var(--primary))";
|
|
1053
|
+
const dateFormat = "d MMM";
|
|
1054
|
+
const label = `${event.title}, ${format7(firstDay, dateFormat, { locale })}${lastDay > firstDay ? ` \u2013 ${format7(lastDay, dateFormat, { locale })}` : ""}`;
|
|
1055
|
+
return /* @__PURE__ */ React5.createElement(
|
|
1056
|
+
"div",
|
|
1057
|
+
{
|
|
1058
|
+
ref: setNodeRef,
|
|
1059
|
+
...listeners,
|
|
1060
|
+
...attributes,
|
|
1061
|
+
onPointerDownCapture: handlePointerDownCapture,
|
|
1062
|
+
role: "button",
|
|
1063
|
+
"aria-label": label,
|
|
1064
|
+
className: cn(
|
|
1065
|
+
"group absolute px-[2px] select-none",
|
|
1066
|
+
dragDisabled ? "cursor-pointer" : "cursor-grab active:cursor-grabbing touch-none"
|
|
1067
|
+
),
|
|
1068
|
+
style: {
|
|
1069
|
+
left: `${startCol / columns * 100}%`,
|
|
1070
|
+
width: `${shownSpan / columns * 100}%`,
|
|
1071
|
+
top: lane * laneHeight,
|
|
1072
|
+
height: laneHeight,
|
|
1073
|
+
transform: CSS.Translate.toString(transform),
|
|
1074
|
+
opacity: isDragging ? 0 : void 0,
|
|
1075
|
+
zIndex: isDragging ? 100 : 1
|
|
1076
|
+
},
|
|
1077
|
+
onClick: (e) => {
|
|
1078
|
+
e.stopPropagation();
|
|
1079
|
+
if (ignoreClick.current) {
|
|
1080
|
+
ignoreClick.current = false;
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
onEventClick?.(event);
|
|
1084
|
+
},
|
|
1085
|
+
onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0
|
|
1086
|
+
},
|
|
1087
|
+
/* @__PURE__ */ React5.createElement(
|
|
1088
|
+
"div",
|
|
1089
|
+
{
|
|
1090
|
+
className: cn(
|
|
1091
|
+
"relative h-[calc(100%-4px)] mt-[2px] flex items-center gap-1 px-1.5 text-[11px] font-semibold text-white overflow-hidden shadow-sm",
|
|
1092
|
+
continuesBefore ? "rounded-l-none" : "rounded-l-md",
|
|
1093
|
+
continuesAfter ? "rounded-r-none" : "rounded-r-md"
|
|
1094
|
+
),
|
|
1095
|
+
style: { backgroundColor: color }
|
|
1096
|
+
},
|
|
1097
|
+
continuesBefore && /* @__PURE__ */ React5.createElement("span", { "aria-label": translations?.continuesBefore }, "\u2039"),
|
|
1098
|
+
/* @__PURE__ */ React5.createElement("span", { className: "truncate" }, event.title),
|
|
1099
|
+
continuesAfter && /* @__PURE__ */ React5.createElement("span", { className: "ml-auto", "aria-label": translations?.continuesAfter }, "\u203A"),
|
|
1100
|
+
canResize && /* @__PURE__ */ React5.createElement(
|
|
1101
|
+
"div",
|
|
1102
|
+
{
|
|
1103
|
+
"data-testid": "all-day-resize",
|
|
1104
|
+
className: "absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize opacity-0 group-hover:opacity-100 bg-black/20",
|
|
1105
|
+
onPointerDown: handleResizeStart
|
|
1106
|
+
}
|
|
1107
|
+
)
|
|
1108
|
+
)
|
|
1109
|
+
);
|
|
1110
|
+
};
|
|
1111
|
+
var AllDayBar = React5.memo(AllDayBarImpl);
|
|
1112
|
+
|
|
1113
|
+
// src/components/dnd/DraggableEvent.tsx
|
|
1114
|
+
import React6 from "react";
|
|
1115
|
+
import { useDraggable as useDraggable2 } from "@dnd-kit/core";
|
|
1116
|
+
import { CSS as CSS2 } from "@dnd-kit/utilities";
|
|
788
1117
|
var DraggableEventImpl = ({ event, dragId, grabOffsetMs, children, className, style: propStyle, ...props }) => {
|
|
789
1118
|
const dragDisabled = isEventDragDisabled(event);
|
|
790
|
-
const { attributes, listeners, setNodeRef, transform, isDragging } =
|
|
1119
|
+
const { attributes, listeners, setNodeRef, transform, isDragging } = useDraggable2({
|
|
791
1120
|
id: dragId ?? event.id,
|
|
792
1121
|
data: { event, grabOffsetMs },
|
|
793
1122
|
disabled: dragDisabled
|
|
794
1123
|
});
|
|
795
1124
|
const style = {
|
|
796
1125
|
...propStyle,
|
|
797
|
-
transform:
|
|
1126
|
+
transform: CSS2.Translate.toString(transform),
|
|
798
1127
|
zIndex: isDragging ? 100 : propStyle?.zIndex,
|
|
799
1128
|
// Hide the original while dragging: the DragOverlay ghost is what the user follows.
|
|
800
1129
|
opacity: isDragging ? 0 : propStyle?.opacity
|
|
801
1130
|
};
|
|
802
|
-
return /* @__PURE__ */
|
|
1131
|
+
return /* @__PURE__ */ React6.createElement(
|
|
803
1132
|
"div",
|
|
804
1133
|
{
|
|
805
1134
|
ref: setNodeRef,
|
|
@@ -812,10 +1141,10 @@ var DraggableEventImpl = ({ event, dragId, grabOffsetMs, children, className, st
|
|
|
812
1141
|
children
|
|
813
1142
|
);
|
|
814
1143
|
};
|
|
815
|
-
var DraggableEvent =
|
|
1144
|
+
var DraggableEvent = React6.memo(DraggableEventImpl);
|
|
816
1145
|
|
|
817
1146
|
// src/components/dnd/DroppableCell.tsx
|
|
818
|
-
import
|
|
1147
|
+
import React7 from "react";
|
|
819
1148
|
import { useDroppable } from "@dnd-kit/core";
|
|
820
1149
|
var QUARTER_HOVER = [
|
|
821
1150
|
"hover:bg-blue-50/50 dark:hover:bg-blue-900/10",
|
|
@@ -830,13 +1159,13 @@ var QUARTER_ACTIVE = [
|
|
|
830
1159
|
"bg-blue-100/80 dark:bg-blue-900/40 ring-2 ring-primary ring-inset"
|
|
831
1160
|
];
|
|
832
1161
|
var quarterOf = (date) => Math.min(3, Math.floor(date.getMinutes() / 15));
|
|
833
|
-
var DroppableCellImpl = ({ id, date, resourceId, children, className, style, onClick, onSlotClick }) => {
|
|
1162
|
+
var DroppableCellImpl = ({ id, date, resourceId, allDayRow, children, className, style, onClick, onSlotClick }) => {
|
|
834
1163
|
const { isOver, setNodeRef } = useDroppable({
|
|
835
1164
|
id,
|
|
836
|
-
data: { date, resourceId }
|
|
1165
|
+
data: { date, resourceId, allDayRow }
|
|
837
1166
|
});
|
|
838
1167
|
const quarter = quarterOf(date);
|
|
839
|
-
return /* @__PURE__ */
|
|
1168
|
+
return /* @__PURE__ */ React7.createElement(
|
|
840
1169
|
"div",
|
|
841
1170
|
{
|
|
842
1171
|
ref: setNodeRef,
|
|
@@ -858,13 +1187,13 @@ var shallowEqualStyle = (a, b) => {
|
|
|
858
1187
|
const keys = Object.keys(a);
|
|
859
1188
|
return keys.length === Object.keys(b).length && keys.every((key) => a[key] === b[key]);
|
|
860
1189
|
};
|
|
861
|
-
var DroppableCell =
|
|
1190
|
+
var DroppableCell = React7.memo(
|
|
862
1191
|
DroppableCellImpl,
|
|
863
|
-
(prev, next) => prev.id === next.id && prev.date.getTime() === next.date.getTime() && prev.resourceId === next.resourceId && prev.children === next.children && prev.className === next.className && prev.onClick === next.onClick && prev.onSlotClick === next.onSlotClick && shallowEqualStyle(prev.style, next.style)
|
|
1192
|
+
(prev, next) => prev.id === next.id && prev.date.getTime() === next.date.getTime() && prev.resourceId === next.resourceId && prev.allDayRow === next.allDayRow && prev.children === next.children && prev.className === next.className && prev.onClick === next.onClick && prev.onSlotClick === next.onSlotClick && shallowEqualStyle(prev.style, next.style)
|
|
864
1193
|
);
|
|
865
1194
|
|
|
866
1195
|
// src/views/MonthView.tsx
|
|
867
|
-
var EventItem =
|
|
1196
|
+
var EventItem = React8.memo(({ event, onEventClick, onEventContextMenu }) => /* @__PURE__ */ React8.createElement(DraggableEvent, { event }, /* @__PURE__ */ React8.createElement(
|
|
868
1197
|
"div",
|
|
869
1198
|
{
|
|
870
1199
|
className: cn(
|
|
@@ -880,61 +1209,183 @@ var EventItem = React7.memo(({ event, onEventClick }) => /* @__PURE__ */ React7.
|
|
|
880
1209
|
onClick: (e) => {
|
|
881
1210
|
e.stopPropagation();
|
|
882
1211
|
onEventClick?.(event);
|
|
883
|
-
}
|
|
1212
|
+
},
|
|
1213
|
+
onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0
|
|
884
1214
|
},
|
|
885
|
-
/* @__PURE__ */
|
|
1215
|
+
/* @__PURE__ */ React8.createElement("span", { className: "font-medium" }, event.title)
|
|
886
1216
|
)));
|
|
887
1217
|
EventItem.displayName = "EventItem";
|
|
1218
|
+
var ROW_HEIGHT = 130;
|
|
1219
|
+
var LANE_HEIGHT = 20;
|
|
1220
|
+
var MAX_LANES = 3;
|
|
1221
|
+
var MAX_ITEMS = 4;
|
|
1222
|
+
var BARS_TOP = 38;
|
|
1223
|
+
var CELL_CHROME = 16 + 28 + 6;
|
|
1224
|
+
var ITEM_STEP = 29 + 4;
|
|
1225
|
+
var MORE_HEIGHT = 20;
|
|
1226
|
+
function timedSlots(visibleLanes, timedCount, hiddenBars) {
|
|
1227
|
+
if (visibleLanes === 0) return Math.min(timedCount, MAX_ITEMS);
|
|
1228
|
+
const room = ROW_HEIGHT - CELL_CHROME - visibleLanes * LANE_HEIGHT;
|
|
1229
|
+
if (hiddenBars === 0 && timedCount * ITEM_STEP - 4 <= room) return timedCount;
|
|
1230
|
+
return Math.max(0, Math.floor((room - MORE_HEIGHT) / ITEM_STEP));
|
|
1231
|
+
}
|
|
888
1232
|
var MonthView = ({
|
|
889
1233
|
currentDate,
|
|
890
1234
|
events,
|
|
891
1235
|
onEventClick,
|
|
892
1236
|
onDateClick,
|
|
893
1237
|
timezone,
|
|
894
|
-
locale
|
|
1238
|
+
locale,
|
|
1239
|
+
translations,
|
|
1240
|
+
onEventContextMenu,
|
|
1241
|
+
onDayEventResize,
|
|
1242
|
+
readonly
|
|
895
1243
|
}) => {
|
|
896
1244
|
const weekStartsOn = resolveWeekStartsOn(locale, 1);
|
|
897
1245
|
const days = useMemo(() => getMonthGrid(currentDate, weekStartsOn), [currentDate, weekStartsOn]);
|
|
898
1246
|
const weekDays = useMemo(() => getWeekDays(currentDate, weekStartsOn), [currentDate, weekStartsOn]);
|
|
899
|
-
const
|
|
1247
|
+
const weeks = useMemo(
|
|
1248
|
+
() => Array.from({ length: Math.ceil(days.length / 7) }, (_, i) => days.slice(i * 7, i * 7 + 7)),
|
|
1249
|
+
[days]
|
|
1250
|
+
);
|
|
1251
|
+
const { dayEvents, timedEvents } = partitionDayEvents(events, timezone);
|
|
1252
|
+
const eventsByDay = eventsByStartDay(timedEvents, timezone);
|
|
900
1253
|
const today = displayToday(timezone);
|
|
901
|
-
return /* @__PURE__ */
|
|
1254
|
+
return /* @__PURE__ */ React8.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] scrollbar-hide border-border/50 rounded-2xl overflow-hidden min-w-[800px] md:min-w-0 shadow-sm" }, /* @__PURE__ */ React8.createElement("div", { className: "overflow-y-auto flex-1 relative" }, /* @__PURE__ */ React8.createElement("div", { className: "grid grid-cols-7 border-b-[0.5px] border-border/50 bg-gradient-to-r from-muted/30 via-muted/40 to-muted/30 sticky top-0 z-20 backdrop-blur-sm" }, weekDays.map((day) => /* @__PURE__ */ React8.createElement(
|
|
902
1255
|
"div",
|
|
903
1256
|
{
|
|
904
1257
|
key: day.toISOString(),
|
|
905
1258
|
className: "py-3 text-center text-xs font-semibold text-muted-foreground border-r-[0.5px] border-border/30 last:border-r-0 uppercase tracking-wider"
|
|
906
1259
|
},
|
|
907
|
-
|
|
908
|
-
))),
|
|
909
|
-
const
|
|
910
|
-
const
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
1260
|
+
format8(day, "EEE", { locale })
|
|
1261
|
+
))), weeks.map((week) => {
|
|
1262
|
+
const { segments, laneCount } = layoutDayRow(week, dayEvents, timezone);
|
|
1263
|
+
const visibleLanes = Math.min(laneCount, MAX_LANES);
|
|
1264
|
+
return /* @__PURE__ */ React8.createElement("div", { key: week[0].toISOString(), className: "relative grid grid-cols-7", style: { height: ROW_HEIGHT } }, week.map((day, column) => {
|
|
1265
|
+
const dayKey2 = format8(day, "yyyy-MM-dd");
|
|
1266
|
+
const dayTimed = eventsByDay.get(dayKey2) || [];
|
|
1267
|
+
const barsOnDay = segments.filter((s) => column >= s.startCol && column < s.startCol + s.span);
|
|
1268
|
+
const hiddenBars = barsOnDay.filter((s) => s.lane >= MAX_LANES).length;
|
|
1269
|
+
const shown = timedSlots(visibleLanes, dayTimed.length, hiddenBars);
|
|
1270
|
+
const hidden = hiddenBars + dayTimed.length - shown;
|
|
1271
|
+
const total = barsOnDay.length + dayTimed.length;
|
|
1272
|
+
const isCurrentMonth = isSameMonth2(day, currentDate);
|
|
1273
|
+
const cellId = day.toISOString();
|
|
1274
|
+
return /* @__PURE__ */ React8.createElement(
|
|
1275
|
+
DroppableCell,
|
|
1276
|
+
{
|
|
1277
|
+
key: cellId,
|
|
1278
|
+
id: cellId,
|
|
1279
|
+
date: day,
|
|
1280
|
+
className: cn(
|
|
1281
|
+
"h-full p-2 border-b-[0.5px] border-r-[0.5px] border-border/30 last:border-r-0 relative transition-all duration-200 hover:bg-accent/5 flex flex-col gap-1.5 overflow-hidden group",
|
|
1282
|
+
!isCurrentMonth && "bg-muted/5 text-muted-foreground/60",
|
|
1283
|
+
isSameDay3(day, today) && "bg-primary/5 ring-1 ring-inset ring-primary/20"
|
|
1284
|
+
),
|
|
1285
|
+
onClick: () => onDateClick?.(day)
|
|
1286
|
+
},
|
|
1287
|
+
/* @__PURE__ */ React8.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React8.createElement("div", { className: cn(
|
|
1288
|
+
"text-sm font-semibold w-7 h-7 flex items-center justify-center rounded-full transition-all duration-200",
|
|
1289
|
+
isSameDay3(day, today) ? "bg-primary text-primary-foreground shadow-md shadow-primary/30" : "group-hover:bg-accent"
|
|
1290
|
+
) }, format8(day, "d", { locale })), total > 0 && /* @__PURE__ */ React8.createElement("div", { className: "text-[10px] font-medium text-muted-foreground/60 bg-muted/50 px-1.5 py-0.5 rounded-full" }, total)),
|
|
1291
|
+
visibleLanes > 0 && /* @__PURE__ */ React8.createElement("div", { className: "shrink-0", style: { height: visibleLanes * LANE_HEIGHT - 6 } }),
|
|
1292
|
+
/* @__PURE__ */ React8.createElement("div", { className: "flex-1 flex flex-col gap-1 scrollbar-hide overflow-y-auto overflow-x-hidden" }, dayTimed.slice(0, shown).map((event) => /* @__PURE__ */ React8.createElement(EventItem, { key: `${event.id}-${dayKey2}`, event, onEventClick, onEventContextMenu })), hidden > 0 && // "+N more" counts hidden bars and hidden timed events, and opens the day.
|
|
1293
|
+
/* @__PURE__ */ React8.createElement(
|
|
1294
|
+
"button",
|
|
1295
|
+
{
|
|
1296
|
+
type: "button",
|
|
1297
|
+
className: "shrink-0 text-[10px] leading-4 text-primary font-semibold text-center py-0.5 px-2 rounded-md bg-primary/5 hover:bg-primary/10 cursor-pointer transition-colors",
|
|
1298
|
+
onClick: (e) => {
|
|
1299
|
+
e.stopPropagation();
|
|
1300
|
+
onDateClick?.(day);
|
|
1301
|
+
}
|
|
1302
|
+
},
|
|
1303
|
+
interpolate(translations?.moreEvents || "+{n} more", { n: hidden })
|
|
1304
|
+
))
|
|
1305
|
+
);
|
|
1306
|
+
}), /* @__PURE__ */ React8.createElement("div", { className: "absolute inset-x-0 pointer-events-none", style: { top: BARS_TOP, height: visibleLanes * LANE_HEIGHT } }, segments.filter((s) => s.lane < MAX_LANES).map((segment) => /* @__PURE__ */ React8.createElement("div", { key: `${segment.event.id}-${week[0].toISOString()}`, className: "pointer-events-auto" }, /* @__PURE__ */ React8.createElement(
|
|
1307
|
+
AllDayBar,
|
|
915
1308
|
{
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
) }, format7(day, "d", { locale })), dayEvents.length > 0 && /* @__PURE__ */ React7.createElement("div", { className: "text-[10px] font-medium text-muted-foreground/60 bg-muted/50 px-1.5 py-0.5 rounded-full" }, dayEvents.length)),
|
|
930
|
-
/* @__PURE__ */ React7.createElement("div", { className: "flex-1 flex flex-col gap-1 scrollbar-hide overflow-y-auto overflow-x-hidden" }, dayEvents.slice(0, 4).map((event) => /* @__PURE__ */ React7.createElement(EventItem, { key: `${event.id}-${dayKey2}`, event, onEventClick })), dayEvents.length > 4 && /* @__PURE__ */ React7.createElement("div", { className: "text-[10px] text-primary font-semibold text-center py-1 px-2 rounded-md bg-primary/5 hover:bg-primary/10 cursor-pointer transition-colors" }, "+", dayEvents.length - 4, " more"))
|
|
931
|
-
);
|
|
932
|
-
}))));
|
|
1309
|
+
segment,
|
|
1310
|
+
rowDays: week,
|
|
1311
|
+
laneHeight: LANE_HEIGHT,
|
|
1312
|
+
timezone,
|
|
1313
|
+
locale,
|
|
1314
|
+
translations,
|
|
1315
|
+
readonly,
|
|
1316
|
+
onEventClick,
|
|
1317
|
+
onEventContextMenu,
|
|
1318
|
+
onDayEventResize
|
|
1319
|
+
}
|
|
1320
|
+
)))));
|
|
1321
|
+
})));
|
|
933
1322
|
};
|
|
934
1323
|
|
|
935
1324
|
// src/views/WeekView.tsx
|
|
936
|
-
import
|
|
937
|
-
import { addDays as
|
|
1325
|
+
import React11 from "react";
|
|
1326
|
+
import { addDays as addDays5, format as format10, differenceInMinutes, isSameDay as isSameDay4 } from "date-fns";
|
|
1327
|
+
|
|
1328
|
+
// src/components/AllDayRow.tsx
|
|
1329
|
+
import React9, { useCallback, useEffect as useEffect2, useState as useState3 } from "react";
|
|
1330
|
+
import { format as format9 } from "date-fns";
|
|
1331
|
+
var LANE_HEIGHT2 = 22;
|
|
1332
|
+
var AllDayRowImpl = ({
|
|
1333
|
+
days,
|
|
1334
|
+
dayEvents,
|
|
1335
|
+
timezone,
|
|
1336
|
+
locale,
|
|
1337
|
+
translations,
|
|
1338
|
+
readonly,
|
|
1339
|
+
gutterClassName,
|
|
1340
|
+
maxLanes = 2,
|
|
1341
|
+
onEventClick,
|
|
1342
|
+
onEventContextMenu,
|
|
1343
|
+
onDayEventResize,
|
|
1344
|
+
onSlotClick
|
|
1345
|
+
}) => {
|
|
1346
|
+
const [expanded, setExpanded] = useState3(false);
|
|
1347
|
+
const rowKey = days.length ? format9(days[0], "yyyy-MM-dd") : "";
|
|
1348
|
+
useEffect2(() => setExpanded(false), [rowKey]);
|
|
1349
|
+
const handleSlotClick = useCallback((day) => onSlotClick?.(day), [onSlotClick]);
|
|
1350
|
+
const { segments, laneCount } = layoutDayRow(days, dayEvents, timezone);
|
|
1351
|
+
const visibleLanes = expanded ? laneCount : Math.min(laneCount, maxLanes);
|
|
1352
|
+
const hidden = segments.filter((segment) => segment.lane >= visibleLanes).length;
|
|
1353
|
+
const height = Math.max(visibleLanes, 1) * LANE_HEIGHT2 + 4;
|
|
1354
|
+
return /* @__PURE__ */ React9.createElement("div", { className: "flex border-b-[0.5px] border-border/50 bg-background", "data-all-day-row": true }, /* @__PURE__ */ React9.createElement("div", { className: cn("flex-none flex flex-col items-end justify-start gap-0.5 pr-2 pt-1 text-[10px] text-muted-foreground border-r-[0.5px] border-border/30", gutterClassName) }, /* @__PURE__ */ React9.createElement("span", null, translations?.allDay || "All Day"), laneCount > maxLanes && /* @__PURE__ */ React9.createElement(
|
|
1355
|
+
"button",
|
|
1356
|
+
{
|
|
1357
|
+
type: "button",
|
|
1358
|
+
className: "text-primary font-semibold hover:underline",
|
|
1359
|
+
onClick: () => setExpanded(!expanded)
|
|
1360
|
+
},
|
|
1361
|
+
expanded ? translations?.showLess || "Show less" : interpolate(translations?.moreEvents || "+{n} more", { n: hidden })
|
|
1362
|
+
)), /* @__PURE__ */ React9.createElement("div", { className: "flex-1 relative", style: { height } }, /* @__PURE__ */ React9.createElement("div", { className: "absolute inset-0 grid", style: { gridTemplateColumns: `repeat(${days.length}, minmax(0, 1fr))` } }, days.map((day, index) => /* @__PURE__ */ React9.createElement(
|
|
1363
|
+
DroppableCell,
|
|
1364
|
+
{
|
|
1365
|
+
key: day.toISOString(),
|
|
1366
|
+
id: `all-day-${day.toISOString()}`,
|
|
1367
|
+
date: day,
|
|
1368
|
+
allDayRow: true,
|
|
1369
|
+
className: cn("h-full", index > 0 && "border-l-[0.5px] border-border/30"),
|
|
1370
|
+
onSlotClick: readonly || !onSlotClick ? void 0 : handleSlotClick
|
|
1371
|
+
}
|
|
1372
|
+
))), /* @__PURE__ */ React9.createElement("div", { className: "absolute inset-x-0 top-0 pointer-events-none", style: { height } }, segments.filter((segment) => segment.lane < visibleLanes).map((segment) => /* @__PURE__ */ React9.createElement("div", { key: `${segment.event.id}-${rowKey}`, className: "pointer-events-auto" }, /* @__PURE__ */ React9.createElement(
|
|
1373
|
+
AllDayBar,
|
|
1374
|
+
{
|
|
1375
|
+
segment,
|
|
1376
|
+
rowDays: days,
|
|
1377
|
+
laneHeight: LANE_HEIGHT2,
|
|
1378
|
+
timezone,
|
|
1379
|
+
locale,
|
|
1380
|
+
translations,
|
|
1381
|
+
readonly,
|
|
1382
|
+
onEventClick,
|
|
1383
|
+
onEventContextMenu,
|
|
1384
|
+
onDayEventResize
|
|
1385
|
+
}
|
|
1386
|
+
))))));
|
|
1387
|
+
};
|
|
1388
|
+
var AllDayRow = React9.memo(AllDayRowImpl);
|
|
938
1389
|
|
|
939
1390
|
// src/core/layout.ts
|
|
940
1391
|
var layoutCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -975,9 +1426,10 @@ function layoutDayEvents(segments) {
|
|
|
975
1426
|
}
|
|
976
1427
|
|
|
977
1428
|
// src/components/dnd/ResizableEvent.tsx
|
|
978
|
-
import
|
|
1429
|
+
import React10, { useState as useState4, useRef as useRef2, useCallback as useCallback2 } from "react";
|
|
979
1430
|
|
|
980
1431
|
// src/core/dnd.ts
|
|
1432
|
+
import { addDays as addDays4, differenceInCalendarDays as differenceInCalendarDays3, startOfDay as startOfDay4 } from "date-fns";
|
|
981
1433
|
function computeDrop({ event, overDate, overResourceId, grabOffsetMs = 0, view, tz }) {
|
|
982
1434
|
let wallStart;
|
|
983
1435
|
if (view === "month") {
|
|
@@ -998,6 +1450,23 @@ function computeResizeEnd(event, deltaMinutes, minDuration = 15) {
|
|
|
998
1450
|
const minEnd = event.start.getTime() + minDuration * 6e4;
|
|
999
1451
|
return new Date(Math.max(event.end.getTime() + deltaMinutes * 6e4, minEnd));
|
|
1000
1452
|
}
|
|
1453
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
1454
|
+
var shiftDays = (date, days, event, tz) => event.allDay ? addDays4(date, days) : fromDisplay(addDays4(toDisplay(date, tz), days), tz);
|
|
1455
|
+
function computeDayMove(event, overDay, grabDayOffset, tz) {
|
|
1456
|
+
const { firstDay } = dayEventSpan(event, tz);
|
|
1457
|
+
const days = differenceInCalendarDays3(addDays4(startOfDay4(overDay), -grabDayOffset), firstDay);
|
|
1458
|
+
if (days === 0) return null;
|
|
1459
|
+
return { start: shiftDays(event.start, days, event, tz), end: shiftDays(event.end, days, event, tz) };
|
|
1460
|
+
}
|
|
1461
|
+
function computeDayResize(event, newLastDay, tz) {
|
|
1462
|
+
const { firstDay, lastDay } = dayEventSpan(event, tz);
|
|
1463
|
+
const target = startOfDay4(newLastDay) < firstDay ? firstDay : startOfDay4(newLastDay);
|
|
1464
|
+
const days = differenceInCalendarDays3(target, lastDay);
|
|
1465
|
+
if (days === 0) return null;
|
|
1466
|
+
if (event.allDay) return addDays4(target, 1);
|
|
1467
|
+
const end = new Date(Math.max(shiftDays(event.end, days, event, tz).getTime(), event.start.getTime() + DAY_MS));
|
|
1468
|
+
return end.getTime() === event.end.getTime() ? null : end;
|
|
1469
|
+
}
|
|
1001
1470
|
|
|
1002
1471
|
// src/components/dnd/ResizableEvent.tsx
|
|
1003
1472
|
var ResizableEvent = ({
|
|
@@ -1011,13 +1480,13 @@ var ResizableEvent = ({
|
|
|
1011
1480
|
readonly
|
|
1012
1481
|
}) => {
|
|
1013
1482
|
const resizeLocked = readonly || isEventResizeDisabled(event);
|
|
1014
|
-
const [isResizing, setIsResizing] =
|
|
1015
|
-
const [resizeHeight, setResizeHeight] =
|
|
1016
|
-
const containerRef =
|
|
1017
|
-
const startYRef =
|
|
1018
|
-
const startHeightRef =
|
|
1019
|
-
const resizeHeightRef =
|
|
1020
|
-
const handleResizeStart =
|
|
1483
|
+
const [isResizing, setIsResizing] = useState4(false);
|
|
1484
|
+
const [resizeHeight, setResizeHeight] = useState4(null);
|
|
1485
|
+
const containerRef = useRef2(null);
|
|
1486
|
+
const startYRef = useRef2(0);
|
|
1487
|
+
const startHeightRef = useRef2(0);
|
|
1488
|
+
const resizeHeightRef = useRef2(null);
|
|
1489
|
+
const handleResizeStart = useCallback2((e) => {
|
|
1021
1490
|
e.preventDefault();
|
|
1022
1491
|
e.stopPropagation();
|
|
1023
1492
|
const clientY = "touches" in e ? e.touches[0].clientY : e.clientY;
|
|
@@ -1056,10 +1525,10 @@ var ResizableEvent = ({
|
|
|
1056
1525
|
document.addEventListener("touchmove", handleMove, { passive: false });
|
|
1057
1526
|
document.addEventListener("touchend", handleEnd);
|
|
1058
1527
|
}, [event, hourHeight, minDuration, onResize]);
|
|
1059
|
-
const handlePointerDown =
|
|
1528
|
+
const handlePointerDown = useCallback2((e) => {
|
|
1060
1529
|
e.stopPropagation();
|
|
1061
1530
|
}, []);
|
|
1062
|
-
return /* @__PURE__ */
|
|
1531
|
+
return /* @__PURE__ */ React10.createElement(
|
|
1063
1532
|
"div",
|
|
1064
1533
|
{
|
|
1065
1534
|
ref: containerRef,
|
|
@@ -1070,7 +1539,7 @@ var ResizableEvent = ({
|
|
|
1070
1539
|
}
|
|
1071
1540
|
},
|
|
1072
1541
|
children,
|
|
1073
|
-
/* @__PURE__ */
|
|
1542
|
+
/* @__PURE__ */ React10.createElement(
|
|
1074
1543
|
"div",
|
|
1075
1544
|
{
|
|
1076
1545
|
className: cn(
|
|
@@ -1083,12 +1552,12 @@ var ResizableEvent = ({
|
|
|
1083
1552
|
onMouseDown: resizeLocked ? void 0 : handleResizeStart,
|
|
1084
1553
|
onTouchStart: resizeLocked ? void 0 : handleResizeStart
|
|
1085
1554
|
},
|
|
1086
|
-
/* @__PURE__ */
|
|
1555
|
+
/* @__PURE__ */ React10.createElement("div", { className: cn(
|
|
1087
1556
|
"w-8 h-1 rounded-full transition-all",
|
|
1088
1557
|
isResizing ? "bg-primary" : "bg-muted-foreground/30 group-hover:bg-primary/50"
|
|
1089
1558
|
) })
|
|
1090
1559
|
),
|
|
1091
|
-
isResizing && /* @__PURE__ */
|
|
1560
|
+
isResizing && /* @__PURE__ */ React10.createElement("div", { className: "absolute inset-0 border-2 border-primary border-dashed rounded-md pointer-events-none bg-primary/5" })
|
|
1092
1561
|
);
|
|
1093
1562
|
};
|
|
1094
1563
|
|
|
@@ -1110,29 +1579,34 @@ var WeekViewImpl = ({
|
|
|
1110
1579
|
onEventResize,
|
|
1111
1580
|
timezone,
|
|
1112
1581
|
locale,
|
|
1113
|
-
readonly
|
|
1582
|
+
readonly,
|
|
1583
|
+
onEventContextMenu,
|
|
1584
|
+
onDayEventResize,
|
|
1585
|
+
onAllDaySlotClick,
|
|
1586
|
+
translations
|
|
1114
1587
|
}) => {
|
|
1115
|
-
const weekDays =
|
|
1588
|
+
const weekDays = React11.useMemo(
|
|
1116
1589
|
() => getWeekDays(currentDate, resolveWeekStartsOn(locale, 1)),
|
|
1117
1590
|
[currentDate, locale]
|
|
1118
1591
|
);
|
|
1119
|
-
const visibleRange =
|
|
1120
|
-
() => ({ start: weekDays[0], end:
|
|
1592
|
+
const visibleRange = React11.useMemo(
|
|
1593
|
+
() => ({ start: weekDays[0], end: addDays5(weekDays[weekDays.length - 1], 1) }),
|
|
1121
1594
|
[weekDays]
|
|
1122
1595
|
);
|
|
1123
|
-
const scrollContainerRef =
|
|
1124
|
-
const [now, setNow] =
|
|
1125
|
-
|
|
1596
|
+
const scrollContainerRef = React11.useRef(null);
|
|
1597
|
+
const [now, setNow] = React11.useState(() => /* @__PURE__ */ new Date());
|
|
1598
|
+
React11.useEffect(() => {
|
|
1126
1599
|
const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
1127
1600
|
return () => clearInterval(interval);
|
|
1128
1601
|
}, []);
|
|
1129
|
-
|
|
1602
|
+
React11.useEffect(() => {
|
|
1130
1603
|
if (scrollContainerRef.current) {
|
|
1131
1604
|
const offsetHour = 4;
|
|
1132
1605
|
scrollContainerRef.current.scrollTop = (toDisplay(/* @__PURE__ */ new Date(), timezone).getHours() - offsetHour) * HOUR_HEIGHT;
|
|
1133
1606
|
}
|
|
1134
1607
|
}, [timezone]);
|
|
1135
|
-
const
|
|
1608
|
+
const { dayEvents, timedEvents } = partitionDayEvents(events, timezone);
|
|
1609
|
+
const segmentsByDay = segmentsByDisplayDay(timedEvents, timezone, visibleRange);
|
|
1136
1610
|
const today = displayToday(timezone, now);
|
|
1137
1611
|
const zonedNow = toDisplay(now, timezone);
|
|
1138
1612
|
const nowTop = minutesSinceDisplayMidnight(now, timezone) / 60 * HOUR_HEIGHT;
|
|
@@ -1140,42 +1614,57 @@ var WeekViewImpl = ({
|
|
|
1140
1614
|
const zone = resolveTimeZone(timezone);
|
|
1141
1615
|
const zoneLabel = timeZoneAbbreviation(now, zone) || zone || "LOC";
|
|
1142
1616
|
const formats = timeFormats(locale);
|
|
1143
|
-
return /* @__PURE__ */
|
|
1617
|
+
return /* @__PURE__ */ React11.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden min-w-[800px] md:min-w-0 shadow-sm" }, /* @__PURE__ */ React11.createElement(
|
|
1144
1618
|
"div",
|
|
1145
1619
|
{
|
|
1146
1620
|
ref: scrollContainerRef,
|
|
1147
1621
|
className: "flex-1 overflow-y-auto scrollbar-hide relative bg-background scroll-smooth"
|
|
1148
1622
|
},
|
|
1149
|
-
/* @__PURE__ */
|
|
1623
|
+
/* @__PURE__ */ React11.createElement("div", { className: "sticky top-0 z-20" }, /* @__PURE__ */ React11.createElement("div", { className: "flex border-b-[0.5px] border-border/50 bg-gradient-to-r from-muted/20 via-background to-muted/20 backdrop-blur-sm" }, /* @__PURE__ */ React11.createElement("div", { className: "flex-none p-3 text-center text-xs font-semibold text-muted-foreground w-16 flex items-center justify-center border-r-[0.5px] border-border/30 bg-muted/10" }, /* @__PURE__ */ React11.createElement("div", { className: "flex flex-col items-center justify-center leading-tight" }, /* @__PURE__ */ React11.createElement("span", null, format10(zonedNow, "HH:mm")), /* @__PURE__ */ React11.createElement("span", { className: "text-[10px] opacity-75" }, "(", zoneLabel, ")"))), /* @__PURE__ */ React11.createElement("div", { className: "flex-1 grid grid-cols-7" }, weekDays.map((day, index) => /* @__PURE__ */ React11.createElement("div", { key: day.toISOString(), className: cn("py-3 px-2 text-center", index > 0 && "border-l-[0.5px] border-border/30") }, /* @__PURE__ */ React11.createElement("div", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1.5" }, format10(day, "EEE", { locale })), /* @__PURE__ */ React11.createElement("div", { className: cn(
|
|
1150
1624
|
"w-9 h-9 flex items-center justify-center rounded-xl mx-auto text-sm font-semibold transition-all duration-200",
|
|
1151
1625
|
isSameDay4(day, today) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30 scale-110" : "text-foreground hover:bg-accent/80"
|
|
1152
|
-
) },
|
|
1153
|
-
|
|
1626
|
+
) }, format10(day, "d", { locale })))))), /* @__PURE__ */ React11.createElement(
|
|
1627
|
+
AllDayRow,
|
|
1628
|
+
{
|
|
1629
|
+
days: weekDays,
|
|
1630
|
+
dayEvents,
|
|
1631
|
+
timezone,
|
|
1632
|
+
locale,
|
|
1633
|
+
translations,
|
|
1634
|
+
readonly,
|
|
1635
|
+
gutterClassName: "w-16",
|
|
1636
|
+
onEventClick,
|
|
1637
|
+
onEventContextMenu,
|
|
1638
|
+
onDayEventResize,
|
|
1639
|
+
onSlotClick: onAllDaySlotClick
|
|
1640
|
+
}
|
|
1641
|
+
)),
|
|
1642
|
+
/* @__PURE__ */ React11.createElement(
|
|
1154
1643
|
"div",
|
|
1155
1644
|
{
|
|
1156
1645
|
className: "flex min-w-full relative",
|
|
1157
1646
|
style: { height: HOURS.length * HOUR_HEIGHT }
|
|
1158
1647
|
},
|
|
1159
|
-
/* @__PURE__ */
|
|
1648
|
+
/* @__PURE__ */ React11.createElement("div", { className: "flex-none w-16 border-r-[0.5px] border-border/30 relative bg-muted/5" }, HOURS.map((hour) => /* @__PURE__ */ React11.createElement(
|
|
1160
1649
|
"div",
|
|
1161
1650
|
{
|
|
1162
1651
|
key: hour,
|
|
1163
1652
|
className: "relative w-full text-[11px] text-muted-foreground/80 text-right pr-3 font-medium tabular-nums box-border",
|
|
1164
1653
|
style: { height: HOUR_HEIGHT }
|
|
1165
1654
|
},
|
|
1166
|
-
/* @__PURE__ */
|
|
1167
|
-
)), showsToday && /* @__PURE__ */
|
|
1655
|
+
/* @__PURE__ */ React11.createElement("span", { className: "block -translate-y-1/2" }, hour !== 0 && format10(slotDate(currentDate, hour, 0), formats.hour, { locale }))
|
|
1656
|
+
)), showsToday && /* @__PURE__ */ React11.createElement(
|
|
1168
1657
|
"div",
|
|
1169
1658
|
{
|
|
1170
1659
|
className: "absolute left-0 w-full pointer-events-none z-30 flex justify-end pr-2",
|
|
1171
1660
|
style: { top: `${nowTop}px` }
|
|
1172
1661
|
},
|
|
1173
|
-
/* @__PURE__ */
|
|
1662
|
+
/* @__PURE__ */ React11.createElement("span", { className: "text-[10px] font-bold text-primary-foreground bg-primary px-1.5 py-0.5 rounded-md shadow-md -translate-y-1/2 backdrop-blur-none" }, format10(zonedNow, formats.compact, { locale }))
|
|
1174
1663
|
)),
|
|
1175
|
-
/* @__PURE__ */
|
|
1176
|
-
const dayKey2 =
|
|
1664
|
+
/* @__PURE__ */ React11.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, weekDays.map((day, dayIndex) => {
|
|
1665
|
+
const dayKey2 = format10(day, "yyyy-MM-dd");
|
|
1177
1666
|
const positioned = layoutDayEvents(segmentsByDay.get(dayKey2) ?? NO_SEGMENTS);
|
|
1178
|
-
return /* @__PURE__ */
|
|
1667
|
+
return /* @__PURE__ */ React11.createElement("div", { key: dayKey2, className: cn("relative h-full", dayIndex > 0 && "border-l-[0.5px] border-border/30") }, HOURS.map((hour) => /* @__PURE__ */ React11.createElement(
|
|
1179
1668
|
"div",
|
|
1180
1669
|
{
|
|
1181
1670
|
key: hour,
|
|
@@ -1184,7 +1673,7 @@ var WeekViewImpl = ({
|
|
|
1184
1673
|
},
|
|
1185
1674
|
QUARTERS.map((minute) => {
|
|
1186
1675
|
const cellDate = slotDate(day, hour, minute);
|
|
1187
|
-
return /* @__PURE__ */
|
|
1676
|
+
return /* @__PURE__ */ React11.createElement(
|
|
1188
1677
|
DroppableCell,
|
|
1189
1678
|
{
|
|
1190
1679
|
key: minute,
|
|
@@ -1210,7 +1699,7 @@ var WeekViewImpl = ({
|
|
|
1210
1699
|
const height = durationMinutes / 60 * HOUR_HEIGHT;
|
|
1211
1700
|
const isShortEvent = durationMinutes < 60;
|
|
1212
1701
|
const isLastSegment = end.getTime() === zonedEventEnd.getTime();
|
|
1213
|
-
return /* @__PURE__ */
|
|
1702
|
+
return /* @__PURE__ */ React11.createElement(
|
|
1214
1703
|
DraggableEvent,
|
|
1215
1704
|
{
|
|
1216
1705
|
key: `${event.id}-${dayKey2}`,
|
|
@@ -1227,7 +1716,7 @@ var WeekViewImpl = ({
|
|
|
1227
1716
|
paddingRight: columns > 1 ? "2px" : "0"
|
|
1228
1717
|
}
|
|
1229
1718
|
},
|
|
1230
|
-
/* @__PURE__ */
|
|
1719
|
+
/* @__PURE__ */ React11.createElement(
|
|
1231
1720
|
ResizableEvent,
|
|
1232
1721
|
{
|
|
1233
1722
|
readonly: readonly || !isLastSegment,
|
|
@@ -1237,7 +1726,7 @@ var WeekViewImpl = ({
|
|
|
1237
1726
|
className: "h-full",
|
|
1238
1727
|
style: { height: "100%" }
|
|
1239
1728
|
},
|
|
1240
|
-
/* @__PURE__ */
|
|
1729
|
+
/* @__PURE__ */ React11.createElement(
|
|
1241
1730
|
"div",
|
|
1242
1731
|
{
|
|
1243
1732
|
className: cn(
|
|
@@ -1260,33 +1749,34 @@ var WeekViewImpl = ({
|
|
|
1260
1749
|
e.stopPropagation();
|
|
1261
1750
|
onEventClick?.(event);
|
|
1262
1751
|
},
|
|
1752
|
+
onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
|
|
1263
1753
|
title: columns > 1 ? `${event.title} (${column + 1}/${columns})` : void 0
|
|
1264
1754
|
},
|
|
1265
|
-
/* @__PURE__ */
|
|
1755
|
+
/* @__PURE__ */ React11.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ React11.createElement("div", { className: cn(
|
|
1266
1756
|
"font-semibold truncate text-foreground/90 leading-tight",
|
|
1267
1757
|
isShortEvent ? "text-xs text-center" : "text-xs"
|
|
1268
|
-
) }, event.title), !isShortEvent && /* @__PURE__ */
|
|
1758
|
+
) }, event.title), !isShortEvent && /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement("div", { className: "text-[10px] text-muted-foreground truncate mt-0.5 font-medium leading-tight" }, format10(zonedEventStart, formats.time, { locale }), " - ", format10(zonedEventEnd, formats.time, { locale })), event.description && height > 50 && /* @__PURE__ */ React11.createElement("div", { className: "text-[10px] text-muted-foreground/80 truncate mt-1 leading-tight opacity-80" }, event.description)), columns > 1 && !isShortEvent && /* @__PURE__ */ React11.createElement("div", { className: "absolute top-1 right-1 bg-background/80 backdrop-blur-sm rounded-full w-4 h-4 flex items-center justify-center text-[9px] font-bold text-muted-foreground border border-border shadow-sm" }, columns))
|
|
1269
1759
|
)
|
|
1270
1760
|
)
|
|
1271
1761
|
);
|
|
1272
|
-
}), isSameDay4(day, today) && /* @__PURE__ */
|
|
1762
|
+
}), isSameDay4(day, today) && /* @__PURE__ */ React11.createElement(
|
|
1273
1763
|
"div",
|
|
1274
1764
|
{
|
|
1275
1765
|
className: "absolute left-0 right-0 z-20 pointer-events-none flex items-center",
|
|
1276
1766
|
style: { top: `${nowTop}px` }
|
|
1277
1767
|
},
|
|
1278
|
-
/* @__PURE__ */
|
|
1279
|
-
/* @__PURE__ */
|
|
1768
|
+
/* @__PURE__ */ React11.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
|
|
1769
|
+
/* @__PURE__ */ React11.createElement("div", { className: "absolute -left-1.5 w-3 h-3 bg-primary rounded-full shadow-lg shadow-primary/40 ring-2 ring-background animate-pulse" })
|
|
1280
1770
|
));
|
|
1281
1771
|
}))
|
|
1282
1772
|
)
|
|
1283
1773
|
));
|
|
1284
1774
|
};
|
|
1285
|
-
var WeekView =
|
|
1775
|
+
var WeekView = React11.memo(WeekViewImpl);
|
|
1286
1776
|
|
|
1287
1777
|
// src/views/DayView.tsx
|
|
1288
|
-
import
|
|
1289
|
-
import { addDays as
|
|
1778
|
+
import React12 from "react";
|
|
1779
|
+
import { addDays as addDays6, format as format11, differenceInMinutes as differenceInMinutes2, isSameDay as isSameDay5, startOfDay as startOfDay5 } from "date-fns";
|
|
1290
1780
|
var HOUR_HEIGHT2 = 80;
|
|
1291
1781
|
var HOURS2 = Array.from({ length: 24 }, (_, i) => i);
|
|
1292
1782
|
var QUARTERS2 = [0, 15, 30, 45];
|
|
@@ -1304,46 +1794,67 @@ var DayViewImpl = ({
|
|
|
1304
1794
|
onEventResize,
|
|
1305
1795
|
timezone,
|
|
1306
1796
|
locale,
|
|
1307
|
-
readonly
|
|
1797
|
+
readonly,
|
|
1798
|
+
onEventContextMenu,
|
|
1799
|
+
translations,
|
|
1800
|
+
onDayEventResize,
|
|
1801
|
+
onAllDaySlotClick
|
|
1308
1802
|
}) => {
|
|
1309
|
-
const visibleRange =
|
|
1310
|
-
const start =
|
|
1311
|
-
return { start, end:
|
|
1803
|
+
const visibleRange = React12.useMemo(() => {
|
|
1804
|
+
const start = startOfDay5(currentDate);
|
|
1805
|
+
return { start, end: addDays6(start, 1) };
|
|
1312
1806
|
}, [currentDate]);
|
|
1313
|
-
const scrollContainerRef =
|
|
1314
|
-
const [now, setNow] =
|
|
1315
|
-
|
|
1807
|
+
const scrollContainerRef = React12.useRef(null);
|
|
1808
|
+
const [now, setNow] = React12.useState(() => /* @__PURE__ */ new Date());
|
|
1809
|
+
React12.useEffect(() => {
|
|
1316
1810
|
const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
1317
1811
|
return () => clearInterval(interval);
|
|
1318
1812
|
}, []);
|
|
1319
|
-
|
|
1813
|
+
React12.useEffect(() => {
|
|
1320
1814
|
if (scrollContainerRef.current) {
|
|
1321
1815
|
const offsetHour = 3;
|
|
1322
1816
|
scrollContainerRef.current.scrollTop = (toDisplay(/* @__PURE__ */ new Date(), timezone).getHours() - offsetHour) * HOUR_HEIGHT2;
|
|
1323
1817
|
}
|
|
1324
1818
|
}, [timezone]);
|
|
1325
|
-
const dayKey2 =
|
|
1326
|
-
const
|
|
1819
|
+
const dayKey2 = format11(currentDate, "yyyy-MM-dd");
|
|
1820
|
+
const { dayEvents, timedEvents } = partitionDayEvents(events, timezone);
|
|
1821
|
+
const rowDays = React12.useMemo(() => [visibleRange.start], [visibleRange]);
|
|
1822
|
+
const positioned = layoutDayEvents(segmentsByDisplayDay(timedEvents, timezone, visibleRange).get(dayKey2) ?? NO_SEGMENTS2);
|
|
1327
1823
|
const isToday2 = isSameDay5(currentDate, displayToday(timezone, now));
|
|
1328
1824
|
const zonedNow = toDisplay(now, timezone);
|
|
1329
1825
|
const nowTop = minutesSinceDisplayMidnight(now, timezone) / 60 * HOUR_HEIGHT2;
|
|
1330
1826
|
const formats = timeFormats(locale);
|
|
1331
|
-
return /* @__PURE__ */
|
|
1827
|
+
return /* @__PURE__ */ React12.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden shadow-sm" }, /* @__PURE__ */ React12.createElement("div", { className: "px-6 py-4 border-b-[0.5px] border-border/50 bg-gradient-to-r from-muted/20 via-background to-muted/20 text-center shrink-0" }, /* @__PURE__ */ React12.createElement("div", { className: "flex items-center justify-center gap-3" }, /* @__PURE__ */ React12.createElement("h2", { className: "text-xl font-semibold capitalize text-foreground" }, format11(currentDate, "EEEE, MMMM d, yyyy", { locale })), isToday2 && /* @__PURE__ */ React12.createElement("span", { className: "text-xs font-semibold bg-primary text-primary-foreground px-3 py-1 rounded-full shadow-md shadow-primary/20" }, translations?.today || "Today"))), /* @__PURE__ */ React12.createElement(
|
|
1828
|
+
AllDayRow,
|
|
1829
|
+
{
|
|
1830
|
+
days: rowDays,
|
|
1831
|
+
dayEvents,
|
|
1832
|
+
timezone,
|
|
1833
|
+
locale,
|
|
1834
|
+
translations,
|
|
1835
|
+
readonly,
|
|
1836
|
+
gutterClassName: "w-20",
|
|
1837
|
+
onEventClick,
|
|
1838
|
+
onEventContextMenu,
|
|
1839
|
+
onDayEventResize,
|
|
1840
|
+
onSlotClick: onAllDaySlotClick
|
|
1841
|
+
}
|
|
1842
|
+
), /* @__PURE__ */ React12.createElement("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto relative" }, /* @__PURE__ */ React12.createElement("div", { className: "flex relative", style: { height: HOURS2.length * HOUR_HEIGHT2 } }, /* @__PURE__ */ React12.createElement("div", { className: "w-20 bg-muted/5 border-r-[0.5px] border-border/30 relative" }, HOURS2.map((hour) => /* @__PURE__ */ React12.createElement(
|
|
1332
1843
|
"div",
|
|
1333
1844
|
{
|
|
1334
1845
|
key: hour,
|
|
1335
1846
|
className: "relative w-full",
|
|
1336
1847
|
style: { height: HOUR_HEIGHT2 }
|
|
1337
1848
|
},
|
|
1338
|
-
hour !== 0 && /* @__PURE__ */
|
|
1339
|
-
)), isToday2 && /* @__PURE__ */
|
|
1849
|
+
hour !== 0 && /* @__PURE__ */ React12.createElement("span", { className: "absolute w-full text-center -top-3 left-1/2 -translate-x-1/2 text-[11px] text-muted-foreground/80 font-medium tabular-nums bg-background px-1.5 py-0.5 rounded-md" }, format11(slotDate2(currentDate, hour, 0), formats.hour, { locale }))
|
|
1850
|
+
)), isToday2 && /* @__PURE__ */ React12.createElement(
|
|
1340
1851
|
"div",
|
|
1341
1852
|
{
|
|
1342
1853
|
className: "absolute left-0 w-full pointer-events-none z-30 flex justify-end pr-2",
|
|
1343
1854
|
style: { top: `${nowTop}px` }
|
|
1344
1855
|
},
|
|
1345
|
-
/* @__PURE__ */
|
|
1346
|
-
)), /* @__PURE__ */
|
|
1856
|
+
/* @__PURE__ */ React12.createElement("span", { className: "text-[10px] font-bold text-white bg-primary px-2 py-1 rounded-lg shadow-md shadow-primary/30 -translate-y-1/2" }, format11(zonedNow, formats.time, { locale }))
|
|
1857
|
+
)), /* @__PURE__ */ React12.createElement("div", { className: "flex-1 relative" }, HOURS2.map((hour) => /* @__PURE__ */ React12.createElement(
|
|
1347
1858
|
"div",
|
|
1348
1859
|
{
|
|
1349
1860
|
key: hour,
|
|
@@ -1352,7 +1863,7 @@ var DayViewImpl = ({
|
|
|
1352
1863
|
},
|
|
1353
1864
|
QUARTERS2.map((minute) => {
|
|
1354
1865
|
const cellDate = slotDate2(currentDate, hour, minute);
|
|
1355
|
-
return /* @__PURE__ */
|
|
1866
|
+
return /* @__PURE__ */ React12.createElement(
|
|
1356
1867
|
DroppableCell,
|
|
1357
1868
|
{
|
|
1358
1869
|
key: minute,
|
|
@@ -1378,7 +1889,7 @@ var DayViewImpl = ({
|
|
|
1378
1889
|
const height = durationMinutes / 60 * HOUR_HEIGHT2;
|
|
1379
1890
|
const isShortEvent = durationMinutes < 45;
|
|
1380
1891
|
const isLastSegment = end.getTime() === zonedEnd.getTime();
|
|
1381
|
-
return /* @__PURE__ */
|
|
1892
|
+
return /* @__PURE__ */ React12.createElement(
|
|
1382
1893
|
DraggableEvent,
|
|
1383
1894
|
{
|
|
1384
1895
|
key: `${event.id}-${dayKey2}`,
|
|
@@ -1394,7 +1905,7 @@ var DayViewImpl = ({
|
|
|
1394
1905
|
paddingRight: columns > 1 ? "2px" : "0"
|
|
1395
1906
|
}
|
|
1396
1907
|
},
|
|
1397
|
-
/* @__PURE__ */
|
|
1908
|
+
/* @__PURE__ */ React12.createElement(
|
|
1398
1909
|
ResizableEvent,
|
|
1399
1910
|
{
|
|
1400
1911
|
readonly: readonly || !isLastSegment,
|
|
@@ -1404,7 +1915,7 @@ var DayViewImpl = ({
|
|
|
1404
1915
|
className: "h-full",
|
|
1405
1916
|
style: { height: "100%" }
|
|
1406
1917
|
},
|
|
1407
|
-
/* @__PURE__ */
|
|
1918
|
+
/* @__PURE__ */ React12.createElement(
|
|
1408
1919
|
"div",
|
|
1409
1920
|
{
|
|
1410
1921
|
className: cn(
|
|
@@ -1425,42 +1936,43 @@ var DayViewImpl = ({
|
|
|
1425
1936
|
e.stopPropagation();
|
|
1426
1937
|
onEventClick?.(event);
|
|
1427
1938
|
},
|
|
1939
|
+
onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
|
|
1428
1940
|
title: columns > 1 ? `${event.title} (${column + 1}/${columns})` : void 0
|
|
1429
1941
|
},
|
|
1430
|
-
/* @__PURE__ */
|
|
1942
|
+
/* @__PURE__ */ React12.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ React12.createElement("div", { className: cn(
|
|
1431
1943
|
"font-semibold truncate leading-tight",
|
|
1432
1944
|
isShortEvent ? "text-xs" : "text-sm",
|
|
1433
1945
|
event.color ? "text-foreground" : "text-foreground/90"
|
|
1434
|
-
) }, event.title), !isShortEvent && /* @__PURE__ */
|
|
1946
|
+
) }, event.title), !isShortEvent && /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement("div", { className: "text-xs text-muted-foreground mt-0.5 font-medium" }, format11(zonedStart, formats.time, { locale }), " - ", format11(zonedEnd, formats.time, { locale })), event.description && height > 60 && /* @__PURE__ */ React12.createElement("div", { className: "text-xs text-muted-foreground/80 mt-1 line-clamp-2" }, event.description)), columns > 1 && !isShortEvent && /* @__PURE__ */ React12.createElement("div", { className: "absolute top-1.5 right-1.5 bg-background/90 backdrop-blur-sm rounded-full w-5 h-5 flex items-center justify-center text-[10px] font-bold text-muted-foreground border border-border shadow-sm" }, columns))
|
|
1435
1947
|
)
|
|
1436
1948
|
)
|
|
1437
1949
|
);
|
|
1438
|
-
}), isToday2 && /* @__PURE__ */
|
|
1950
|
+
}), isToday2 && /* @__PURE__ */ React12.createElement(
|
|
1439
1951
|
"div",
|
|
1440
1952
|
{
|
|
1441
1953
|
className: "absolute left-0 right-0 z-20 pointer-events-none flex items-center",
|
|
1442
1954
|
style: { top: `${nowTop}px` }
|
|
1443
1955
|
},
|
|
1444
|
-
/* @__PURE__ */
|
|
1445
|
-
/* @__PURE__ */
|
|
1956
|
+
/* @__PURE__ */ React12.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
|
|
1957
|
+
/* @__PURE__ */ React12.createElement("div", { className: "absolute -left-1.5 w-3 h-3 bg-primary rounded-full shadow-lg shadow-primary/40 ring-2 ring-background animate-pulse" })
|
|
1446
1958
|
)))));
|
|
1447
1959
|
};
|
|
1448
|
-
var DayView =
|
|
1960
|
+
var DayView = React12.memo(DayViewImpl);
|
|
1449
1961
|
|
|
1450
1962
|
// src/views/AgendaView.tsx
|
|
1451
|
-
import
|
|
1452
|
-
import { format as
|
|
1963
|
+
import React14, { useMemo as useMemo2 } from "react";
|
|
1964
|
+
import { format as format12, isSameDay as isSameDay6, addDays as addDays7, startOfDay as startOfDay6, differenceInMinutes as differenceInMinutes3 } from "date-fns";
|
|
1453
1965
|
|
|
1454
1966
|
// src/components/EmptyState.tsx
|
|
1455
|
-
import
|
|
1967
|
+
import React13 from "react";
|
|
1456
1968
|
import { Plus as Plus2 } from "lucide-react";
|
|
1457
|
-
var AgendaEmptyState = ({ onCreateEvent, translations }) => /* @__PURE__ */
|
|
1969
|
+
var AgendaEmptyState = ({ onCreateEvent, translations }) => /* @__PURE__ */ React13.createElement("div", { className: "flex flex-col items-center justify-center h-full min-h-[400px] py-12" }, /* @__PURE__ */ React13.createElement("div", { className: "relative mb-8" }, /* @__PURE__ */ React13.createElement("div", { className: "p-8 bg-gradient-to-br from-green-50 to-blue-50 dark:from-green-900/10 dark:to-blue-900/10 rounded-3xl border border-border/30" }, /* @__PURE__ */ React13.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React13.createElement("div", { className: "w-12 h-12 rounded-2xl bg-green-100 dark:bg-green-900/30 flex items-center justify-center" }, /* @__PURE__ */ React13.createElement("svg", { className: "w-6 h-6 text-green-600 dark:text-green-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2 }, /* @__PURE__ */ React13.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }))), /* @__PURE__ */ React13.createElement("div", { className: "text-left" }, /* @__PURE__ */ React13.createElement("div", { className: "font-medium text-foreground" }, translations?.allCaughtUp || "All caught up!"), /* @__PURE__ */ React13.createElement("div", { className: "text-sm text-muted-foreground" }, translations?.noEventsScheduled || "No events scheduled"))))), /* @__PURE__ */ React13.createElement("div", { className: "text-center max-w-sm" }, /* @__PURE__ */ React13.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, translations?.noUpcoming || "Your schedule is clear"), /* @__PURE__ */ React13.createElement("p", { className: "text-sm text-muted-foreground mb-6" }, translations?.noUpcomingHint || "No upcoming events to show. Create a new event to start planning."), onCreateEvent && /* @__PURE__ */ React13.createElement(
|
|
1458
1970
|
"button",
|
|
1459
1971
|
{
|
|
1460
1972
|
onClick: onCreateEvent,
|
|
1461
1973
|
className: "inline-flex items-center gap-2 px-5 py-2.5 bg-primary text-primary-foreground rounded-xl font-medium text-sm shadow-lg shadow-primary/20 hover:shadow-xl hover:shadow-primary/30 hover:scale-105 active:scale-95 transition-all duration-200"
|
|
1462
1974
|
},
|
|
1463
|
-
/* @__PURE__ */
|
|
1975
|
+
/* @__PURE__ */ React13.createElement(Plus2, { className: "w-4 h-4" }),
|
|
1464
1976
|
translations?.createEvent || "Create Event"
|
|
1465
1977
|
)));
|
|
1466
1978
|
|
|
@@ -1477,8 +1989,8 @@ var formatDuration = (start, end) => {
|
|
|
1477
1989
|
};
|
|
1478
1990
|
var getDateLabel = (date, today, locale, translations) => {
|
|
1479
1991
|
if (isSameDay6(date, today)) return translations?.today || "Today";
|
|
1480
|
-
if (isSameDay6(date,
|
|
1481
|
-
return
|
|
1992
|
+
if (isSameDay6(date, addDays7(today, 1))) return translations?.tomorrow || "Tomorrow";
|
|
1993
|
+
return format12(date, "EEEE", { locale });
|
|
1482
1994
|
};
|
|
1483
1995
|
var AgendaView = ({
|
|
1484
1996
|
currentDate,
|
|
@@ -1487,7 +1999,8 @@ var AgendaView = ({
|
|
|
1487
1999
|
onCreateEvent,
|
|
1488
2000
|
locale,
|
|
1489
2001
|
translations,
|
|
1490
|
-
timezone
|
|
2002
|
+
timezone,
|
|
2003
|
+
onEventContextMenu
|
|
1491
2004
|
}) => {
|
|
1492
2005
|
const is24h = uses24HourClock(locale);
|
|
1493
2006
|
const { time: timePattern, compact: compactTimePattern } = timeFormats(locale);
|
|
@@ -1496,8 +2009,8 @@ var AgendaView = ({
|
|
|
1496
2009
|
const byDay = eventsByStartDay(events, timezone);
|
|
1497
2010
|
const groups = [];
|
|
1498
2011
|
for (let i = 0; i < 30; i++) {
|
|
1499
|
-
const day =
|
|
1500
|
-
const dayEvents = byDay.get(
|
|
2012
|
+
const day = addDays7(startOfDay6(currentDate), i);
|
|
2013
|
+
const dayEvents = byDay.get(format12(day, "yyyy-MM-dd"));
|
|
1501
2014
|
if (dayEvents?.length) {
|
|
1502
2015
|
groups.push({ date: day, events: [...dayEvents].sort((a, b) => a.start.getTime() - b.start.getTime()) });
|
|
1503
2016
|
}
|
|
@@ -1517,7 +2030,7 @@ var AgendaView = ({
|
|
|
1517
2030
|
hidden: { opacity: 0, x: -20 },
|
|
1518
2031
|
show: { opacity: 1, x: 0 }
|
|
1519
2032
|
};
|
|
1520
|
-
return /* @__PURE__ */
|
|
2033
|
+
return /* @__PURE__ */ React14.createElement("div", { className: "flex flex-col h-full bg-background overflow-y-auto" }, groupedEvents.length === 0 ? /* @__PURE__ */ React14.createElement(AgendaEmptyState, { onCreateEvent, translations }) : /* @__PURE__ */ React14.createElement(
|
|
1521
2034
|
motion.div,
|
|
1522
2035
|
{
|
|
1523
2036
|
className: "max-w-3xl mx-auto w-full pb-10 px-4 md:px-6",
|
|
@@ -1525,25 +2038,26 @@ var AgendaView = ({
|
|
|
1525
2038
|
initial: "hidden",
|
|
1526
2039
|
animate: "show"
|
|
1527
2040
|
},
|
|
1528
|
-
groupedEvents.map((group) => /* @__PURE__ */
|
|
2041
|
+
groupedEvents.map((group) => /* @__PURE__ */ React14.createElement(
|
|
1529
2042
|
motion.div,
|
|
1530
2043
|
{
|
|
1531
2044
|
key: group.date.toISOString(),
|
|
1532
2045
|
className: "relative",
|
|
1533
2046
|
variants: item
|
|
1534
2047
|
},
|
|
1535
|
-
/* @__PURE__ */
|
|
2048
|
+
/* @__PURE__ */ React14.createElement("div", { className: "sticky top-0 bg-background/95 backdrop-blur-md py-4 z-10 border-b border-border/50" }, /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React14.createElement("div", { className: cn(
|
|
1536
2049
|
"flex flex-col items-center justify-center w-16 h-16 rounded-2xl transition-all",
|
|
1537
2050
|
isSameDay6(group.date, today) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30" : "bg-muted/50 text-foreground"
|
|
1538
|
-
) }, /* @__PURE__ */
|
|
2051
|
+
) }, /* @__PURE__ */ React14.createElement("span", { className: "text-2xl font-bold leading-none" }, format12(group.date, "d")), /* @__PURE__ */ React14.createElement("span", { className: "text-xs font-medium uppercase tracking-wide opacity-80" }, format12(group.date, "MMM", { locale }))), /* @__PURE__ */ React14.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React14.createElement("span", { className: cn(
|
|
1539
2052
|
"text-lg font-semibold",
|
|
1540
2053
|
isSameDay6(group.date, today) && "text-primary"
|
|
1541
|
-
) }, getDateLabel(group.date, today, locale, translations)), /* @__PURE__ */
|
|
1542
|
-
/* @__PURE__ */
|
|
2054
|
+
) }, getDateLabel(group.date, today, locale, translations)), /* @__PURE__ */ React14.createElement("span", { className: "text-sm text-muted-foreground" }, group.events.length, " ", group.events.length !== 1 ? translations?.eventPlural || "events" : translations?.eventSingular || "event")))),
|
|
2055
|
+
/* @__PURE__ */ React14.createElement("div", { className: "py-4 space-y-3" }, group.events.map((event) => /* @__PURE__ */ React14.createElement(
|
|
1543
2056
|
motion.div,
|
|
1544
2057
|
{
|
|
1545
2058
|
key: event.id,
|
|
1546
2059
|
onClick: () => onEventClick?.(event),
|
|
2060
|
+
onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
|
|
1547
2061
|
className: cn(
|
|
1548
2062
|
"group relative flex gap-4 p-4 rounded-2xl border border-border/40",
|
|
1549
2063
|
"hover:border-primary/40 hover:shadow-lg hover:shadow-primary/5",
|
|
@@ -1553,30 +2067,30 @@ var AgendaView = ({
|
|
|
1553
2067
|
whileHover: { scale: 1.01, y: -2 },
|
|
1554
2068
|
transition: { duration: 0.2 }
|
|
1555
2069
|
},
|
|
1556
|
-
/* @__PURE__ */
|
|
2070
|
+
/* @__PURE__ */ React14.createElement(
|
|
1557
2071
|
"div",
|
|
1558
2072
|
{
|
|
1559
2073
|
className: "absolute left-0 top-3 bottom-3 w-1 rounded-full",
|
|
1560
2074
|
style: { backgroundColor: event.color || "var(--primary)" }
|
|
1561
2075
|
}
|
|
1562
2076
|
),
|
|
1563
|
-
/* @__PURE__ */
|
|
1564
|
-
/* @__PURE__ */
|
|
2077
|
+
/* @__PURE__ */ React14.createElement("div", { className: "flex flex-col items-center min-w-[70px] pl-2" }, event.allDay ? /* @__PURE__ */ React14.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ React14.createElement("span", { className: "text-xs font-semibold text-muted-foreground bg-muted/80 px-2.5 py-1 rounded-full" }, translations?.allDay || "All Day")) : /* @__PURE__ */ React14.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ React14.createElement("span", { className: "text-base font-semibold text-foreground" }, format12(toDisplay(event.start, timezone), compactTimePattern, { locale })), !is24h && /* @__PURE__ */ React14.createElement("span", { className: "text-xs text-muted-foreground uppercase" }, format12(toDisplay(event.start, timezone), "a")), /* @__PURE__ */ React14.createElement("div", { className: "w-px h-3 bg-border my-1" }), /* @__PURE__ */ React14.createElement("span", { className: "text-xs text-muted-foreground/70 font-medium" }, formatDuration(event.start, event.end)))),
|
|
2078
|
+
/* @__PURE__ */ React14.createElement("div", { className: "flex-1 min-w-0 space-y-2" }, /* @__PURE__ */ React14.createElement("div", { className: "flex items-start justify-between gap-2" }, /* @__PURE__ */ React14.createElement("h4", { className: "text-base font-semibold text-foreground group-hover:text-primary transition-colors line-clamp-1" }, event.title), /* @__PURE__ */ React14.createElement(
|
|
1565
2079
|
"div",
|
|
1566
2080
|
{
|
|
1567
2081
|
className: "w-3 h-3 rounded-full shrink-0 mt-1.5",
|
|
1568
2082
|
style: { backgroundColor: event.color || "var(--primary)" }
|
|
1569
2083
|
}
|
|
1570
|
-
)), event.description && /* @__PURE__ */
|
|
1571
|
-
/* @__PURE__ */
|
|
2084
|
+
)), event.description && /* @__PURE__ */ React14.createElement("p", { className: "text-sm text-muted-foreground line-clamp-2 leading-relaxed" }, event.description), /* @__PURE__ */ React14.createElement("div", { className: "flex flex-wrap items-center gap-3 pt-1" }, !event.allDay && /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React14.createElement(Clock, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React14.createElement("span", null, format12(toDisplay(event.start, timezone), timePattern, { locale }), " - ", format12(toDisplay(event.end, timezone), timePattern, { locale }))), event.guests && event.guests.length > 0 && /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React14.createElement(Users, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React14.createElement("span", null, event.guests.length, " ", event.guests.length !== 1 ? translations?.guestsCount || "guests" : translations?.guestCount || "guest")), event.attachments && event.attachments.length > 0 && /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React14.createElement(Paperclip, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React14.createElement("span", null, event.attachments.length)), event.reminders && event.reminders.length > 0 && /* @__PURE__ */ React14.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React14.createElement(Bell, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React14.createElement("span", null, event.reminders.length)))),
|
|
2085
|
+
/* @__PURE__ */ React14.createElement("div", { className: "absolute right-4 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity" }, /* @__PURE__ */ React14.createElement("svg", { className: "w-5 h-5 text-muted-foreground", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ React14.createElement("path", { d: "M9 18l6-6-6-6" })))
|
|
1572
2086
|
)))
|
|
1573
2087
|
))
|
|
1574
2088
|
));
|
|
1575
2089
|
};
|
|
1576
2090
|
|
|
1577
2091
|
// src/views/ResourceView.tsx
|
|
1578
|
-
import
|
|
1579
|
-
import { format as
|
|
2092
|
+
import React15, { useRef as useRef3 } from "react";
|
|
2093
|
+
import { format as format13, startOfDay as startOfDay7, differenceInMinutes as differenceInMinutes4 } from "date-fns";
|
|
1580
2094
|
var ResourceView = ({
|
|
1581
2095
|
currentDate,
|
|
1582
2096
|
events,
|
|
@@ -1584,16 +2098,18 @@ var ResourceView = ({
|
|
|
1584
2098
|
onEventClick,
|
|
1585
2099
|
onTimeSlotClick,
|
|
1586
2100
|
locale,
|
|
1587
|
-
timezone
|
|
2101
|
+
timezone,
|
|
2102
|
+
translations,
|
|
2103
|
+
onEventContextMenu
|
|
1588
2104
|
}) => {
|
|
1589
|
-
const containerRef =
|
|
2105
|
+
const containerRef = useRef3(null);
|
|
1590
2106
|
const hours = Array.from({ length: 24 }, (_, i) => i);
|
|
1591
2107
|
const hourWidth = 100;
|
|
1592
2108
|
const timeFormat = timeFormats(locale).hour;
|
|
1593
2109
|
const getEventStyle = (event) => {
|
|
1594
2110
|
const start = toDisplay(event.start, timezone);
|
|
1595
2111
|
const end = toDisplay(event.end, timezone);
|
|
1596
|
-
const dayStart =
|
|
2112
|
+
const dayStart = startOfDay7(currentDate);
|
|
1597
2113
|
const startMinutes = differenceInMinutes4(start, dayStart);
|
|
1598
2114
|
const durationMinutes = differenceInMinutes4(end, start);
|
|
1599
2115
|
const left = startMinutes / 60 * hourWidth;
|
|
@@ -1604,19 +2120,19 @@ var ResourceView = ({
|
|
|
1604
2120
|
// Min width for visibility
|
|
1605
2121
|
};
|
|
1606
2122
|
};
|
|
1607
|
-
return /* @__PURE__ */
|
|
2123
|
+
return /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col h-full bg-background overflow-hidden" }, /* @__PURE__ */ React15.createElement("div", { className: "flex border-b border-border bg-muted/20" }, /* @__PURE__ */ React15.createElement("div", { className: "w-48 shrink-0 border-r border-border p-4 font-semibold text-sm bg-background sticky left-0 z-20" }, translations?.resource || "Resources"), /* @__PURE__ */ React15.createElement("div", { className: "flex overflow-hidden" }, /* @__PURE__ */ React15.createElement("div", { className: "flex relative", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ React15.createElement(
|
|
1608
2124
|
"div",
|
|
1609
2125
|
{
|
|
1610
2126
|
key: hour,
|
|
1611
2127
|
className: "border-r border-border/50 text-xs text-muted-foreground p-2 font-medium shrink-0",
|
|
1612
2128
|
style: { width: hourWidth }
|
|
1613
2129
|
},
|
|
1614
|
-
|
|
1615
|
-
))))), /* @__PURE__ */
|
|
2130
|
+
format13((/* @__PURE__ */ new Date()).setHours(hour, 0, 0, 0), timeFormat, { locale })
|
|
2131
|
+
))))), /* @__PURE__ */ React15.createElement("div", { className: "flex-1 overflow-auto relative", ref: containerRef }, /* @__PURE__ */ React15.createElement("div", { className: "min-w-fit" }, resources.map((resource) => {
|
|
1616
2132
|
const resourceEvents = events.filter(
|
|
1617
2133
|
(e) => e.resourceId === resource.id && isSameDisplayDay(e.start, currentDate, timezone)
|
|
1618
2134
|
);
|
|
1619
|
-
return /* @__PURE__ */
|
|
2135
|
+
return /* @__PURE__ */ React15.createElement("div", { key: resource.id, className: "flex border-b border-border min-h-[100px]" }, /* @__PURE__ */ React15.createElement("div", { className: "w-48 shrink-0 border-r border-border p-4 bg-background sticky left-0 z-10 flex items-center gap-3" }, resource.avatar ? /* @__PURE__ */ React15.createElement("img", { src: resource.avatar, alt: resource.label, className: "w-8 h-8 rounded-full object-cover" }) : /* @__PURE__ */ React15.createElement("div", { className: "w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center text-xs font-bold text-primary" }, resource.label.substring(0, 2).toUpperCase()), /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium" }, resource.label), /* @__PURE__ */ React15.createElement("span", { className: "text-xs text-muted-foreground" }, interpolate(translations?.idLabel || "ID: {id}", { id: resource.id })))), /* @__PURE__ */ React15.createElement("div", { className: "relative flex", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ React15.createElement(
|
|
1620
2136
|
"div",
|
|
1621
2137
|
{
|
|
1622
2138
|
key: hour,
|
|
@@ -1627,7 +2143,7 @@ var ResourceView = ({
|
|
|
1627
2143
|
const slotDate3 = new Date(currentDate);
|
|
1628
2144
|
slotDate3.setHours(hour, minute, 0, 0);
|
|
1629
2145
|
const slotId = `${resource.id}-${slotDate3.toISOString()}`;
|
|
1630
|
-
return /* @__PURE__ */
|
|
2146
|
+
return /* @__PURE__ */ React15.createElement(
|
|
1631
2147
|
DroppableCell,
|
|
1632
2148
|
{
|
|
1633
2149
|
key: minute,
|
|
@@ -1639,7 +2155,7 @@ var ResourceView = ({
|
|
|
1639
2155
|
}
|
|
1640
2156
|
);
|
|
1641
2157
|
})
|
|
1642
|
-
)), resourceEvents.map((event) => /* @__PURE__ */
|
|
2158
|
+
)), resourceEvents.map((event) => /* @__PURE__ */ React15.createElement(
|
|
1643
2159
|
DraggableEvent,
|
|
1644
2160
|
{
|
|
1645
2161
|
key: event.id,
|
|
@@ -1648,6 +2164,7 @@ var ResourceView = ({
|
|
|
1648
2164
|
e.stopPropagation();
|
|
1649
2165
|
onEventClick?.(event);
|
|
1650
2166
|
},
|
|
2167
|
+
onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
|
|
1651
2168
|
className: "absolute top-2 bottom-2 rounded-md px-2 py-1 text-xs font-medium border shadow-sm cursor-pointer overflow-hidden hover:brightness-95 transition-all z-10",
|
|
1652
2169
|
style: {
|
|
1653
2170
|
...getEventStyle(event),
|
|
@@ -1656,16 +2173,16 @@ var ResourceView = ({
|
|
|
1656
2173
|
color: "#fff"
|
|
1657
2174
|
}
|
|
1658
2175
|
},
|
|
1659
|
-
/* @__PURE__ */
|
|
2176
|
+
/* @__PURE__ */ React15.createElement("div", { className: "truncate" }, event.title)
|
|
1660
2177
|
))));
|
|
1661
2178
|
}))));
|
|
1662
2179
|
};
|
|
1663
2180
|
|
|
1664
2181
|
// src/components/EventModal.tsx
|
|
1665
|
-
import
|
|
2182
|
+
import React17, { useState as useState5, useEffect as useEffect4, useInsertionEffect, useRef as useRef5 } from "react";
|
|
1666
2183
|
|
|
1667
2184
|
// src/components/ui/Modal.tsx
|
|
1668
|
-
import
|
|
2185
|
+
import React16, { useEffect as useEffect3, useRef as useRef4 } from "react";
|
|
1669
2186
|
import { X } from "lucide-react";
|
|
1670
2187
|
var Modal = ({
|
|
1671
2188
|
isOpen,
|
|
@@ -1673,10 +2190,11 @@ var Modal = ({
|
|
|
1673
2190
|
title,
|
|
1674
2191
|
children,
|
|
1675
2192
|
className,
|
|
1676
|
-
hideHeader = false
|
|
2193
|
+
hideHeader = false,
|
|
2194
|
+
closeLabel = "Close"
|
|
1677
2195
|
}) => {
|
|
1678
|
-
const overlayRef =
|
|
1679
|
-
|
|
2196
|
+
const overlayRef = useRef4(null);
|
|
2197
|
+
useEffect3(() => {
|
|
1680
2198
|
const handleEscape = (e) => {
|
|
1681
2199
|
if (e.key === "Escape") {
|
|
1682
2200
|
onClose();
|
|
@@ -1690,14 +2208,14 @@ var Modal = ({
|
|
|
1690
2208
|
};
|
|
1691
2209
|
}, [isOpen, onClose]);
|
|
1692
2210
|
if (!isOpen) return null;
|
|
1693
|
-
return /* @__PURE__ */
|
|
2211
|
+
return /* @__PURE__ */ React16.createElement("div", { className: "absolute inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-md animate-in fade-in duration-300" }, /* @__PURE__ */ React16.createElement(
|
|
1694
2212
|
"div",
|
|
1695
2213
|
{
|
|
1696
2214
|
ref: overlayRef,
|
|
1697
2215
|
className: "absolute inset-0",
|
|
1698
2216
|
onClick: onClose
|
|
1699
2217
|
}
|
|
1700
|
-
), /* @__PURE__ */
|
|
2218
|
+
), /* @__PURE__ */ React16.createElement(
|
|
1701
2219
|
"div",
|
|
1702
2220
|
{
|
|
1703
2221
|
className: cn(
|
|
@@ -1705,7 +2223,7 @@ var Modal = ({
|
|
|
1705
2223
|
className
|
|
1706
2224
|
)
|
|
1707
2225
|
},
|
|
1708
|
-
!hideHeader && /* @__PURE__ */
|
|
2226
|
+
!hideHeader && /* @__PURE__ */ React16.createElement("div", { className: "flex items-center justify-between px-6 py-4 border-b border-border/50 shrink-0 bg-gradient-to-r from-muted/20 to-background" }, /* @__PURE__ */ React16.createElement("h3", { className: "text-lg font-semibold text-foreground" }, title), /* @__PURE__ */ React16.createElement(
|
|
1709
2227
|
Button,
|
|
1710
2228
|
{
|
|
1711
2229
|
variant: "ghost",
|
|
@@ -1713,15 +2231,15 @@ var Modal = ({
|
|
|
1713
2231
|
onClick: onClose,
|
|
1714
2232
|
className: "h-9 w-9 p-0 rounded-xl hover:bg-accent/80 transition-all duration-200"
|
|
1715
2233
|
},
|
|
1716
|
-
/* @__PURE__ */
|
|
1717
|
-
/* @__PURE__ */
|
|
2234
|
+
/* @__PURE__ */ React16.createElement(X, { className: "h-4 w-4" }),
|
|
2235
|
+
/* @__PURE__ */ React16.createElement("span", { className: "sr-only" }, closeLabel)
|
|
1718
2236
|
)),
|
|
1719
|
-
/* @__PURE__ */
|
|
2237
|
+
/* @__PURE__ */ React16.createElement("div", { className: cn("overflow-y-auto flex-1", !hideHeader && "p-6") }, children)
|
|
1720
2238
|
));
|
|
1721
2239
|
};
|
|
1722
2240
|
|
|
1723
2241
|
// src/components/EventModal.tsx
|
|
1724
|
-
import { format as
|
|
2242
|
+
import { addDays as addDays8, differenceInCalendarDays as differenceInCalendarDays4, format as format14, differenceInMinutes as differenceInMinutes5, startOfDay as startOfDay8 } from "date-fns";
|
|
1725
2243
|
import { motion as motion2, AnimatePresence } from "framer-motion";
|
|
1726
2244
|
import {
|
|
1727
2245
|
Clock as Clock2,
|
|
@@ -1744,18 +2262,7 @@ import {
|
|
|
1744
2262
|
Tag,
|
|
1745
2263
|
ExternalLink
|
|
1746
2264
|
} from "lucide-react";
|
|
1747
|
-
var REMINDER_OPTIONS = [
|
|
1748
|
-
{ value: 0, label: "At time of event" },
|
|
1749
|
-
{ value: 5, label: "5 minutes before" },
|
|
1750
|
-
{ value: 10, label: "10 minutes before" },
|
|
1751
|
-
{ value: 15, label: "15 minutes before" },
|
|
1752
|
-
{ value: 30, label: "30 minutes before" },
|
|
1753
|
-
{ value: 60, label: "1 hour before" },
|
|
1754
|
-
{ value: 120, label: "2 hours before" },
|
|
1755
|
-
{ value: 1440, label: "1 day before" },
|
|
1756
|
-
{ value: 2880, label: "2 days before" },
|
|
1757
|
-
{ value: 10080, label: "1 week before" }
|
|
1758
|
-
];
|
|
2265
|
+
var REMINDER_OPTIONS = [0, 5, 10, 15, 30, 60, 120, 1440, 2880, 10080];
|
|
1759
2266
|
var COLOR_PALETTE = [
|
|
1760
2267
|
"#3b82f6",
|
|
1761
2268
|
// Blue
|
|
@@ -1778,6 +2285,30 @@ var COLOR_PALETTE = [
|
|
|
1778
2285
|
"#6366f1"
|
|
1779
2286
|
// Indigo
|
|
1780
2287
|
];
|
|
2288
|
+
var EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2289
|
+
var mergeGuests = (current, added) => {
|
|
2290
|
+
const seen = new Set(current.map((email) => email.toLowerCase()));
|
|
2291
|
+
const merged = [...current];
|
|
2292
|
+
for (const email of added) {
|
|
2293
|
+
if (!seen.has(email.toLowerCase())) {
|
|
2294
|
+
seen.add(email.toLowerCase());
|
|
2295
|
+
merged.push(email);
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
return merged;
|
|
2299
|
+
};
|
|
2300
|
+
var reminderLabel = (minutes, t) => {
|
|
2301
|
+
if (minutes === 0) return t.reminderAtTime;
|
|
2302
|
+
if (minutes === 10080) return t.reminderWeek;
|
|
2303
|
+
if (minutes === 1440) return t.reminderDay;
|
|
2304
|
+
if (minutes % 1440 === 0) return interpolate(t.reminderDays, { n: minutes / 1440 });
|
|
2305
|
+
if (minutes === 60) return t.reminderHour;
|
|
2306
|
+
if (minutes % 60 === 0) return interpolate(t.reminderHours, { n: minutes / 60 });
|
|
2307
|
+
return interpolate(t.reminderMinutes, { n: minutes });
|
|
2308
|
+
};
|
|
2309
|
+
var avatarHue = (email) => [...email].reduce((hash, char) => (hash * 31 + char.charCodeAt(0)) % 360, 7);
|
|
2310
|
+
var mapsUrl = (location) => `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(location)}`;
|
|
2311
|
+
var isSafeUrl = (url) => /^(https?:|mailto:|blob:|\/|\.\/|\.\.\/|[^:]*$)/i.test(url.trim());
|
|
1781
2312
|
var EventModal = ({
|
|
1782
2313
|
isOpen,
|
|
1783
2314
|
onClose,
|
|
@@ -1785,10 +2316,17 @@ var EventModal = ({
|
|
|
1785
2316
|
initialDate,
|
|
1786
2317
|
onSave,
|
|
1787
2318
|
onDelete,
|
|
1788
|
-
calendars
|
|
2319
|
+
calendars,
|
|
2320
|
+
translations: t,
|
|
2321
|
+
locale,
|
|
2322
|
+
initialAllDay
|
|
1789
2323
|
}) => {
|
|
1790
|
-
const [mode, setMode] =
|
|
1791
|
-
const
|
|
2324
|
+
const [mode, setMode] = useState5("create");
|
|
2325
|
+
const translationsRef = useRef5(t);
|
|
2326
|
+
useInsertionEffect(() => {
|
|
2327
|
+
translationsRef.current = t;
|
|
2328
|
+
});
|
|
2329
|
+
const [formData, setFormData] = useState5({
|
|
1792
2330
|
title: "",
|
|
1793
2331
|
description: "",
|
|
1794
2332
|
location: "",
|
|
@@ -1800,22 +2338,18 @@ var EventModal = ({
|
|
|
1800
2338
|
type: void 0,
|
|
1801
2339
|
recurrence: void 0,
|
|
1802
2340
|
attachments: [],
|
|
1803
|
-
reminders: [
|
|
2341
|
+
reminders: []
|
|
1804
2342
|
});
|
|
1805
|
-
const [isCalendarDropdownOpen, setIsCalendarDropdownOpen] =
|
|
1806
|
-
const [isColorPickerOpen, setIsColorPickerOpen] =
|
|
1807
|
-
const [isReminderDropdownOpen, setIsReminderDropdownOpen] =
|
|
1808
|
-
const [
|
|
1809
|
-
const
|
|
1810
|
-
|
|
1811
|
-
"
|
|
1812
|
-
"charlie@example.com",
|
|
1813
|
-
"diana@example.com",
|
|
1814
|
-
"evan@example.com"
|
|
1815
|
-
];
|
|
1816
|
-
const [selectedGuests, setSelectedGuests] = useState3([]);
|
|
1817
|
-
useEffect3(() => {
|
|
2343
|
+
const [isCalendarDropdownOpen, setIsCalendarDropdownOpen] = useState5(false);
|
|
2344
|
+
const [isColorPickerOpen, setIsColorPickerOpen] = useState5(false);
|
|
2345
|
+
const [isReminderDropdownOpen, setIsReminderDropdownOpen] = useState5(false);
|
|
2346
|
+
const [guestInput, setGuestInput] = useState5("");
|
|
2347
|
+
const [guestError, setGuestError] = useState5(false);
|
|
2348
|
+
useEffect4(() => {
|
|
2349
|
+
const defaultReminders = () => [{ id: "1", type: "notification", time: 30, label: reminderLabel(30, translationsRef.current) }];
|
|
1818
2350
|
if (isOpen) {
|
|
2351
|
+
setGuestInput("");
|
|
2352
|
+
setGuestError(false);
|
|
1819
2353
|
if (event) {
|
|
1820
2354
|
setMode("view");
|
|
1821
2355
|
setFormData({
|
|
@@ -1823,39 +2357,52 @@ var EventModal = ({
|
|
|
1823
2357
|
start: new Date(event.start),
|
|
1824
2358
|
end: new Date(event.end),
|
|
1825
2359
|
attachments: event.attachments || [],
|
|
1826
|
-
reminders: event.reminders ||
|
|
2360
|
+
reminders: event.reminders || defaultReminders(),
|
|
2361
|
+
guests: event.guests || []
|
|
1827
2362
|
});
|
|
1828
|
-
setSelectedGuests(event.guests || []);
|
|
1829
2363
|
} else {
|
|
1830
2364
|
setMode("create");
|
|
1831
|
-
const
|
|
1832
|
-
const
|
|
1833
|
-
end
|
|
2365
|
+
const base = initialDate || /* @__PURE__ */ new Date();
|
|
2366
|
+
const start = initialAllDay ? startOfDay8(base) : base;
|
|
2367
|
+
const end = initialAllDay ? addDays8(start, 1) : new Date(base.getTime() + 60 * 60 * 1e3);
|
|
1834
2368
|
setFormData({
|
|
1835
2369
|
title: "",
|
|
1836
2370
|
description: "",
|
|
1837
2371
|
location: "",
|
|
1838
2372
|
start,
|
|
1839
2373
|
end,
|
|
1840
|
-
allDay:
|
|
2374
|
+
allDay: !!initialAllDay,
|
|
1841
2375
|
color: "#3b82f6",
|
|
1842
2376
|
calendarId: calendars?.[0]?.id,
|
|
1843
2377
|
attachments: [],
|
|
1844
|
-
reminders:
|
|
2378
|
+
reminders: defaultReminders(),
|
|
2379
|
+
guests: []
|
|
1845
2380
|
});
|
|
1846
|
-
setSelectedGuests([]);
|
|
1847
2381
|
}
|
|
1848
2382
|
}
|
|
1849
|
-
}, [isOpen, event, initialDate, calendars]);
|
|
1850
|
-
const
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
2383
|
+
}, [isOpen, event, initialDate, calendars, initialAllDay]);
|
|
2384
|
+
const guests = formData.guests || [];
|
|
2385
|
+
const addGuests = (raw) => {
|
|
2386
|
+
const entries = raw.split(/[\s,;]+/).filter(Boolean);
|
|
2387
|
+
const valid = entries.filter((entry) => EMAIL.test(entry));
|
|
2388
|
+
const invalid = entries.filter((entry) => !EMAIL.test(entry));
|
|
2389
|
+
if (valid.length > 0) {
|
|
2390
|
+
setFormData((prev) => ({ ...prev, guests: mergeGuests(prev.guests || [], valid) }));
|
|
2391
|
+
}
|
|
2392
|
+
setGuestInput(invalid.join(", "));
|
|
2393
|
+
setGuestError(invalid.length > 0);
|
|
2394
|
+
return invalid.length === 0;
|
|
2395
|
+
};
|
|
2396
|
+
const removeGuest = (email) => {
|
|
2397
|
+
setFormData((prev) => ({ ...prev, guests: (prev.guests || []).filter((g) => g !== email) }));
|
|
1856
2398
|
};
|
|
1857
2399
|
const handleSubmit = (e) => {
|
|
1858
2400
|
e.preventDefault();
|
|
2401
|
+
const pending = guestInput.split(/[\s,;]+/).filter(Boolean);
|
|
2402
|
+
if (pending.some((entry) => !EMAIL.test(entry))) {
|
|
2403
|
+
addGuests(guestInput);
|
|
2404
|
+
return;
|
|
2405
|
+
}
|
|
1859
2406
|
let eventColor = formData.color;
|
|
1860
2407
|
if (formData.calendarId && calendars) {
|
|
1861
2408
|
const selectedCal = calendars.find((c) => c.id === formData.calendarId);
|
|
@@ -1863,8 +2410,10 @@ var EventModal = ({
|
|
|
1863
2410
|
eventColor = selectedCal.color;
|
|
1864
2411
|
}
|
|
1865
2412
|
}
|
|
2413
|
+
const finalGuests = mergeGuests(guests, pending);
|
|
1866
2414
|
onSave({
|
|
1867
2415
|
...formData,
|
|
2416
|
+
guests: finalGuests,
|
|
1868
2417
|
color: eventColor,
|
|
1869
2418
|
id: event?.id
|
|
1870
2419
|
});
|
|
@@ -1878,9 +2427,38 @@ var EventModal = ({
|
|
|
1878
2427
|
};
|
|
1879
2428
|
const formatDateForInput = (date) => {
|
|
1880
2429
|
if (!date) return "";
|
|
1881
|
-
return
|
|
2430
|
+
return format14(date, "yyyy-MM-dd'T'HH:mm");
|
|
2431
|
+
};
|
|
2432
|
+
const allDaySpan = formData.allDay && formData.start && formData.end ? dayEventSpan({ ...formData, allDay: true }) : null;
|
|
2433
|
+
const handleAllDayToggle = () => {
|
|
2434
|
+
if (!formData.start || !formData.end) return;
|
|
2435
|
+
if (!formData.allDay) {
|
|
2436
|
+
const firstDay = startOfDay8(formData.start);
|
|
2437
|
+
const lastDay = startOfDay8(new Date(Math.max(formData.end.getTime() - 1, formData.start.getTime())));
|
|
2438
|
+
setFormData((prev) => ({ ...prev, allDay: true, start: firstDay, end: addDays8(lastDay, 1) }));
|
|
2439
|
+
} else {
|
|
2440
|
+
const start = new Date(formData.start);
|
|
2441
|
+
start.setHours(9, 0, 0, 0);
|
|
2442
|
+
setFormData((prev) => ({ ...prev, allDay: false, start, end: new Date(start.getTime() + 60 * 60 * 1e3) }));
|
|
2443
|
+
}
|
|
2444
|
+
};
|
|
2445
|
+
const handleAllDayDateChange = (field, value) => {
|
|
2446
|
+
const [y, m, d] = value.split("-").map(Number);
|
|
2447
|
+
if (!y || !m || !d || !allDaySpan) return;
|
|
2448
|
+
const day = new Date(y, m - 1, d);
|
|
2449
|
+
if (field === "start") {
|
|
2450
|
+
const days = differenceInCalendarDays4(allDaySpan.lastDay, allDaySpan.firstDay);
|
|
2451
|
+
setFormData((prev) => ({ ...prev, start: day, end: addDays8(day, days + 1) }));
|
|
2452
|
+
} else {
|
|
2453
|
+
const firstDay = day < allDaySpan.firstDay ? day : allDaySpan.firstDay;
|
|
2454
|
+
setFormData((prev) => ({ ...prev, start: firstDay, end: addDays8(day, 1) }));
|
|
2455
|
+
}
|
|
1882
2456
|
};
|
|
1883
2457
|
const handleDateChange = (field, value) => {
|
|
2458
|
+
if (formData.allDay) {
|
|
2459
|
+
handleAllDayDateChange(field, value);
|
|
2460
|
+
return;
|
|
2461
|
+
}
|
|
1884
2462
|
const date = new Date(value);
|
|
1885
2463
|
if (isNaN(date.getTime())) return;
|
|
1886
2464
|
if (field === "start") {
|
|
@@ -1898,12 +2476,12 @@ var EventModal = ({
|
|
|
1898
2476
|
}
|
|
1899
2477
|
}
|
|
1900
2478
|
};
|
|
1901
|
-
const addReminder = (minutes
|
|
2479
|
+
const addReminder = (minutes) => {
|
|
1902
2480
|
const newReminder = {
|
|
1903
|
-
id: Math.random().toString(36).
|
|
2481
|
+
id: Math.random().toString(36).slice(2, 11),
|
|
1904
2482
|
type: "notification",
|
|
1905
2483
|
time: minutes,
|
|
1906
|
-
label
|
|
2484
|
+
label: reminderLabel(minutes, t)
|
|
1907
2485
|
};
|
|
1908
2486
|
setFormData((prev) => ({
|
|
1909
2487
|
...prev,
|
|
@@ -1917,25 +2495,28 @@ var EventModal = ({
|
|
|
1917
2495
|
reminders: prev.reminders?.filter((r) => r.id !== id)
|
|
1918
2496
|
}));
|
|
1919
2497
|
};
|
|
1920
|
-
const handleDownload = (attachment) => {
|
|
1921
|
-
const element = document.createElement("a");
|
|
1922
|
-
const file = new Blob(["Dummy content for " + attachment.name], { type: "text/plain" });
|
|
1923
|
-
element.href = URL.createObjectURL(file);
|
|
1924
|
-
element.download = attachment.name;
|
|
1925
|
-
document.body.appendChild(element);
|
|
1926
|
-
element.click();
|
|
1927
|
-
document.body.removeChild(element);
|
|
1928
|
-
};
|
|
1929
2498
|
const getDurationText = () => {
|
|
1930
2499
|
if (!formData.start || !formData.end) return "";
|
|
2500
|
+
if (allDaySpan) {
|
|
2501
|
+
const days = differenceInCalendarDays4(allDaySpan.lastDay, allDaySpan.firstDay) + 1;
|
|
2502
|
+
return days === 1 ? t.durationDay : interpolate(t.durationDays, { n: days });
|
|
2503
|
+
}
|
|
1931
2504
|
const mins = differenceInMinutes5(formData.end, formData.start);
|
|
1932
|
-
if (mins < 60) return
|
|
2505
|
+
if (mins < 60) return interpolate(t.durationMinutes, { n: mins });
|
|
1933
2506
|
const hours = Math.floor(mins / 60);
|
|
1934
2507
|
const remainingMins = mins % 60;
|
|
1935
|
-
if (remainingMins === 0) return
|
|
1936
|
-
return
|
|
2508
|
+
if (remainingMins === 0) return interpolate(t.durationHours, { n: hours });
|
|
2509
|
+
return interpolate(t.durationHoursMinutes, { h: hours, m: remainingMins });
|
|
2510
|
+
};
|
|
2511
|
+
const { time: timeFormat } = timeFormats(locale);
|
|
2512
|
+
const viewEvent = event && { ...event, start: new Date(event.start), end: new Date(event.end) };
|
|
2513
|
+
const viewSpan = viewEvent && isDayEvent(viewEvent) ? dayEventSpan(viewEvent) : null;
|
|
2514
|
+
const renderAttachment = (att) => {
|
|
2515
|
+
const content = /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "p-2 bg-primary/10 rounded-lg" }, /* @__PURE__ */ React17.createElement(File, { className: "w-4 h-4 text-primary" })), /* @__PURE__ */ React17.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React17.createElement("p", { className: "text-sm font-medium text-foreground truncate" }, att.name), /* @__PURE__ */ React17.createElement("p", { className: "text-xs text-muted-foreground" }, att.size)), att.url && /* @__PURE__ */ React17.createElement(Download, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" }));
|
|
2516
|
+
const className = "flex items-center gap-3 p-3 rounded-xl border border-border/30 bg-muted/20 transition-all group";
|
|
2517
|
+
return att.url && isSafeUrl(att.url) ? /* @__PURE__ */ React17.createElement("a", { key: att.id, href: att.url, target: "_blank", rel: "noopener noreferrer", download: att.name, className: cn(className, "hover:bg-muted/40 cursor-pointer") }, content) : /* @__PURE__ */ React17.createElement("div", { key: att.id, className }, content);
|
|
1937
2518
|
};
|
|
1938
|
-
const renderViewMode = () => /* @__PURE__ */
|
|
2519
|
+
const renderViewMode = () => /* @__PURE__ */ React17.createElement("div", { className: "flex flex-col bg-background overflow-hidden w-full max-h-[90vh]" }, /* @__PURE__ */ React17.createElement(
|
|
1939
2520
|
"div",
|
|
1940
2521
|
{
|
|
1941
2522
|
className: "relative px-6 pt-6 pb-8",
|
|
@@ -1943,50 +2524,56 @@ var EventModal = ({
|
|
|
1943
2524
|
background: `linear-gradient(135deg, ${event?.color || "#3b82f6"}15 0%, transparent 100%)`
|
|
1944
2525
|
}
|
|
1945
2526
|
},
|
|
1946
|
-
/* @__PURE__ */
|
|
2527
|
+
/* @__PURE__ */ React17.createElement("div", { className: "flex items-center justify-between mb-6" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement(
|
|
1947
2528
|
"div",
|
|
1948
2529
|
{
|
|
1949
2530
|
className: "w-3 h-3 rounded-full",
|
|
1950
2531
|
style: { backgroundColor: event?.color || "#3b82f6" }
|
|
1951
2532
|
}
|
|
1952
|
-
), /* @__PURE__ */
|
|
2533
|
+
), /* @__PURE__ */ React17.createElement("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider" }, calendars?.find((c) => c.id === event?.calendarId)?.label || t.event)), /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React17.createElement(
|
|
1953
2534
|
"button",
|
|
1954
2535
|
{
|
|
1955
2536
|
onClick: () => setMode("edit"),
|
|
1956
2537
|
className: "p-2 hover:bg-background/80 rounded-lg transition-all text-muted-foreground hover:text-foreground",
|
|
1957
|
-
title:
|
|
2538
|
+
title: t.edit,
|
|
2539
|
+
"aria-label": t.edit
|
|
1958
2540
|
},
|
|
1959
|
-
/* @__PURE__ */
|
|
1960
|
-
), /* @__PURE__ */
|
|
2541
|
+
/* @__PURE__ */ React17.createElement(Edit2, { className: "w-4 h-4" })
|
|
2542
|
+
), /* @__PURE__ */ React17.createElement(
|
|
1961
2543
|
"button",
|
|
1962
2544
|
{
|
|
1963
2545
|
onClick: handleDelete,
|
|
1964
2546
|
className: "p-2 hover:bg-destructive/10 rounded-lg transition-all text-muted-foreground hover:text-destructive",
|
|
1965
|
-
title:
|
|
2547
|
+
title: t.delete,
|
|
2548
|
+
"aria-label": t.delete
|
|
1966
2549
|
},
|
|
1967
|
-
/* @__PURE__ */
|
|
1968
|
-
), /* @__PURE__ */
|
|
2550
|
+
/* @__PURE__ */ React17.createElement(Trash2, { className: "w-4 h-4" })
|
|
2551
|
+
), /* @__PURE__ */ React17.createElement(
|
|
1969
2552
|
"button",
|
|
1970
2553
|
{
|
|
1971
2554
|
onClick: onClose,
|
|
1972
2555
|
className: "p-2 hover:bg-background/80 rounded-lg transition-all text-muted-foreground hover:text-foreground",
|
|
1973
|
-
title:
|
|
2556
|
+
title: t.close,
|
|
2557
|
+
"aria-label": t.close
|
|
1974
2558
|
},
|
|
1975
|
-
/* @__PURE__ */
|
|
2559
|
+
/* @__PURE__ */ React17.createElement(X2, { className: "w-4 h-4" })
|
|
1976
2560
|
))),
|
|
1977
|
-
/* @__PURE__ */
|
|
1978
|
-
/* @__PURE__ */
|
|
1979
|
-
), /* @__PURE__ */
|
|
1980
|
-
motion2.
|
|
2561
|
+
/* @__PURE__ */ React17.createElement("h1", { className: "text-2xl font-bold text-foreground mb-3 leading-tight" }, event?.title || t.noTitle),
|
|
2562
|
+
/* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-3 text-sm" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-background/60 backdrop-blur-sm rounded-lg border border-border/30" }, /* @__PURE__ */ React17.createElement(Calendar2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React17.createElement("span", { className: "font-medium" }, viewSpan && viewSpan.lastDay > viewSpan.firstDay ? `${format14(viewSpan.firstDay, "EEE d MMM", { locale })} \u2013 ${format14(viewSpan.lastDay, "EEE d MMM", { locale })}` : event?.start && format14(new Date(event.start), "EEE, MMM d", { locale }))), event?.allDay ? /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-primary/10 rounded-lg border border-primary/20" }, /* @__PURE__ */ React17.createElement("span", { className: "font-medium text-primary" }, t.allDay)) : /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-background/60 backdrop-blur-sm rounded-lg border border-border/30" }, /* @__PURE__ */ React17.createElement(Clock2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React17.createElement("span", { className: "font-medium" }, event?.start && format14(new Date(event.start), timeFormat, { locale }), " \u2013 ", event?.end && format14(new Date(event.end), timeFormat, { locale }))))
|
|
2563
|
+
), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pb-6 space-y-4 overflow-y-auto flex-1" }, event?.location && /* @__PURE__ */ React17.createElement(
|
|
2564
|
+
motion2.a,
|
|
1981
2565
|
{
|
|
2566
|
+
href: mapsUrl(event.location),
|
|
2567
|
+
target: "_blank",
|
|
2568
|
+
rel: "noopener noreferrer",
|
|
1982
2569
|
initial: { opacity: 0, y: 10 },
|
|
1983
2570
|
animate: { opacity: 1, y: 0 },
|
|
1984
2571
|
className: "flex items-start gap-3 p-4 rounded-2xl bg-muted/30 border border-border/30 group hover:bg-muted/50 transition-all cursor-pointer"
|
|
1985
2572
|
},
|
|
1986
|
-
/* @__PURE__ */
|
|
1987
|
-
/* @__PURE__ */
|
|
1988
|
-
/* @__PURE__ */
|
|
1989
|
-
), event?.guests && event.guests.length > 0 && /* @__PURE__ */
|
|
2573
|
+
/* @__PURE__ */ React17.createElement("div", { className: "p-2 bg-primary/10 rounded-xl" }, /* @__PURE__ */ React17.createElement(MapPin, { className: "w-5 h-5 text-primary" })),
|
|
2574
|
+
/* @__PURE__ */ React17.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React17.createElement("p", { className: "text-sm font-medium text-foreground" }, event.location), /* @__PURE__ */ React17.createElement("p", { className: "text-xs text-muted-foreground mt-0.5" }, t.openInMaps)),
|
|
2575
|
+
/* @__PURE__ */ React17.createElement(ExternalLink, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
|
|
2576
|
+
), event?.guests && event.guests.length > 0 && /* @__PURE__ */ React17.createElement(
|
|
1990
2577
|
motion2.div,
|
|
1991
2578
|
{
|
|
1992
2579
|
initial: { opacity: 0, y: 10 },
|
|
@@ -1994,24 +2581,24 @@ var EventModal = ({
|
|
|
1994
2581
|
transition: { delay: 0.05 },
|
|
1995
2582
|
className: "space-y-3"
|
|
1996
2583
|
},
|
|
1997
|
-
/* @__PURE__ */
|
|
1998
|
-
/* @__PURE__ */
|
|
2584
|
+
/* @__PURE__ */ React17.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement(Users2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React17.createElement("span", { className: "text-sm font-medium text-foreground" }, event.guests.length, " ", event.guests.length > 1 ? t.guests : t.guestSingular))),
|
|
2585
|
+
/* @__PURE__ */ React17.createElement("div", { className: "flex flex-wrap gap-2" }, event.guests.map((email) => /* @__PURE__ */ React17.createElement(
|
|
1999
2586
|
"div",
|
|
2000
2587
|
{
|
|
2001
|
-
key:
|
|
2002
|
-
className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-muted/30 border border-border/30
|
|
2588
|
+
key: email,
|
|
2589
|
+
className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-muted/30 border border-border/30"
|
|
2003
2590
|
},
|
|
2004
|
-
/* @__PURE__ */
|
|
2591
|
+
/* @__PURE__ */ React17.createElement(
|
|
2005
2592
|
"div",
|
|
2006
2593
|
{
|
|
2007
2594
|
className: "w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold text-white",
|
|
2008
|
-
style: { backgroundColor: `hsl(${
|
|
2595
|
+
style: { backgroundColor: `hsl(${avatarHue(email)}, 70%, 50%)` }
|
|
2009
2596
|
},
|
|
2010
2597
|
email[0].toUpperCase()
|
|
2011
2598
|
),
|
|
2012
|
-
/* @__PURE__ */
|
|
2599
|
+
/* @__PURE__ */ React17.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React17.createElement("p", { className: "text-sm font-medium text-foreground" }, email.split("@")[0]), /* @__PURE__ */ React17.createElement("p", { className: "text-xs text-muted-foreground truncate" }, email))
|
|
2013
2600
|
)))
|
|
2014
|
-
), event?.reminders && event.reminders.length > 0 && /* @__PURE__ */
|
|
2601
|
+
), event?.reminders && event.reminders.length > 0 && /* @__PURE__ */ React17.createElement(
|
|
2015
2602
|
motion2.div,
|
|
2016
2603
|
{
|
|
2017
2604
|
initial: { opacity: 0, y: 10 },
|
|
@@ -2019,16 +2606,16 @@ var EventModal = ({
|
|
|
2019
2606
|
transition: { delay: 0.1 },
|
|
2020
2607
|
className: "flex items-center gap-3"
|
|
2021
2608
|
},
|
|
2022
|
-
/* @__PURE__ */
|
|
2023
|
-
/* @__PURE__ */
|
|
2609
|
+
/* @__PURE__ */ React17.createElement("div", { className: "p-2 bg-amber-500/10 rounded-xl" }, /* @__PURE__ */ React17.createElement(Bell2, { className: "w-4 h-4 text-amber-500" })),
|
|
2610
|
+
/* @__PURE__ */ React17.createElement("div", { className: "flex flex-wrap gap-2" }, event.reminders.map((reminder) => /* @__PURE__ */ React17.createElement(
|
|
2024
2611
|
"span",
|
|
2025
2612
|
{
|
|
2026
2613
|
key: reminder.id,
|
|
2027
2614
|
className: "text-xs font-medium px-2.5 py-1 rounded-full bg-amber-500/10 text-amber-600 dark:text-amber-400"
|
|
2028
2615
|
},
|
|
2029
|
-
reminder.label ||
|
|
2616
|
+
reminder.label || reminderLabel(reminder.time, t)
|
|
2030
2617
|
)))
|
|
2031
|
-
), event?.description && /* @__PURE__ */
|
|
2618
|
+
), event?.description && /* @__PURE__ */ React17.createElement(
|
|
2032
2619
|
motion2.div,
|
|
2033
2620
|
{
|
|
2034
2621
|
initial: { opacity: 0, y: 10 },
|
|
@@ -2036,9 +2623,9 @@ var EventModal = ({
|
|
|
2036
2623
|
transition: { delay: 0.15 },
|
|
2037
2624
|
className: "space-y-2"
|
|
2038
2625
|
},
|
|
2039
|
-
/* @__PURE__ */
|
|
2040
|
-
/* @__PURE__ */
|
|
2041
|
-
), event?.attachments && event.attachments.length > 0 && /* @__PURE__ */
|
|
2626
|
+
/* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement(AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React17.createElement("span", { className: "text-sm font-medium text-foreground" }, t.notesLabel)),
|
|
2627
|
+
/* @__PURE__ */ React17.createElement("div", { className: "text-sm text-foreground/80 whitespace-pre-wrap leading-relaxed pl-6 p-3 rounded-xl bg-muted/20 border border-border/30" }, event.description)
|
|
2628
|
+
), event?.attachments && event.attachments.length > 0 && /* @__PURE__ */ React17.createElement(
|
|
2042
2629
|
motion2.div,
|
|
2043
2630
|
{
|
|
2044
2631
|
initial: { opacity: 0, y: 10 },
|
|
@@ -2046,27 +2633,18 @@ var EventModal = ({
|
|
|
2046
2633
|
transition: { delay: 0.2 },
|
|
2047
2634
|
className: "space-y-2"
|
|
2048
2635
|
},
|
|
2049
|
-
/* @__PURE__ */
|
|
2050
|
-
/* @__PURE__ */
|
|
2051
|
-
"div",
|
|
2052
|
-
{
|
|
2053
|
-
key: att.id,
|
|
2054
|
-
onClick: () => handleDownload(att),
|
|
2055
|
-
className: "flex items-center gap-3 p-3 rounded-xl border border-border/30 bg-muted/20 hover:bg-muted/40 transition-all cursor-pointer group"
|
|
2056
|
-
},
|
|
2057
|
-
/* @__PURE__ */ React15.createElement("div", { className: "p-2 bg-primary/10 rounded-lg" }, /* @__PURE__ */ React15.createElement(File, { className: "w-4 h-4 text-primary" })),
|
|
2058
|
-
/* @__PURE__ */ React15.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React15.createElement("p", { className: "text-sm font-medium text-foreground truncate" }, att.name), /* @__PURE__ */ React15.createElement("p", { className: "text-xs text-muted-foreground" }, att.size)),
|
|
2059
|
-
/* @__PURE__ */ React15.createElement(Download, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
|
|
2060
|
-
)))
|
|
2636
|
+
/* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement(Paperclip2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React17.createElement("span", { className: "text-sm font-medium text-foreground" }, t.attachments)),
|
|
2637
|
+
/* @__PURE__ */ React17.createElement("div", { className: "grid gap-2" }, event.attachments.map(renderAttachment))
|
|
2061
2638
|
)));
|
|
2062
|
-
const renderEditMode = () => /* @__PURE__ */
|
|
2639
|
+
const renderEditMode = () => /* @__PURE__ */ React17.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col bg-background overflow-hidden w-full max-h-[85vh]" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center justify-between px-5 py-4 border-b border-border/50 shrink-0" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React17.createElement(
|
|
2063
2640
|
"button",
|
|
2064
2641
|
{
|
|
2065
2642
|
type: "button",
|
|
2066
2643
|
onClick: () => setIsColorPickerOpen(!isColorPickerOpen),
|
|
2067
|
-
className: "relative p-1"
|
|
2644
|
+
className: "relative p-1",
|
|
2645
|
+
"aria-label": t.eventColor
|
|
2068
2646
|
},
|
|
2069
|
-
/* @__PURE__ */
|
|
2647
|
+
/* @__PURE__ */ React17.createElement(
|
|
2070
2648
|
"div",
|
|
2071
2649
|
{
|
|
2072
2650
|
className: "w-5 h-5 rounded-full cursor-pointer hover:scale-110 transition-transform",
|
|
@@ -2076,11 +2654,12 @@ var EventModal = ({
|
|
|
2076
2654
|
}
|
|
2077
2655
|
}
|
|
2078
2656
|
),
|
|
2079
|
-
isColorPickerOpen && /* @__PURE__ */
|
|
2657
|
+
isColorPickerOpen && /* @__PURE__ */ React17.createElement("div", { className: "absolute top-full left-0 mt-2 p-2 bg-background border border-border rounded-xl shadow-xl z-50 flex flex-wrap gap-1.5 w-[180px]" }, COLOR_PALETTE.map((color) => /* @__PURE__ */ React17.createElement(
|
|
2080
2658
|
"button",
|
|
2081
2659
|
{
|
|
2082
2660
|
key: color,
|
|
2083
2661
|
type: "button",
|
|
2662
|
+
"aria-label": color,
|
|
2084
2663
|
onClick: () => {
|
|
2085
2664
|
setFormData((prev) => ({ ...prev, color }));
|
|
2086
2665
|
setIsColorPickerOpen(false);
|
|
@@ -2092,15 +2671,16 @@ var EventModal = ({
|
|
|
2092
2671
|
style: { backgroundColor: color, color }
|
|
2093
2672
|
}
|
|
2094
2673
|
)))
|
|
2095
|
-
), /* @__PURE__ */
|
|
2674
|
+
), /* @__PURE__ */ React17.createElement("h2", { className: "text-lg font-semibold text-foreground" }, mode === "edit" ? t.editEvent : t.newEvent)), /* @__PURE__ */ React17.createElement(
|
|
2096
2675
|
"button",
|
|
2097
2676
|
{
|
|
2098
2677
|
type: "button",
|
|
2099
2678
|
onClick: onClose,
|
|
2100
|
-
className: "p-2 hover:bg-accent rounded-xl transition-all text-muted-foreground hover:text-foreground"
|
|
2679
|
+
className: "p-2 hover:bg-accent rounded-xl transition-all text-muted-foreground hover:text-foreground",
|
|
2680
|
+
"aria-label": t.close
|
|
2101
2681
|
},
|
|
2102
|
-
/* @__PURE__ */
|
|
2103
|
-
)), /* @__PURE__ */
|
|
2682
|
+
/* @__PURE__ */ React17.createElement(X2, { className: "w-4 h-4" })
|
|
2683
|
+
)), /* @__PURE__ */ React17.createElement("div", { className: "flex-1 overflow-y-auto" }, /* @__PURE__ */ React17.createElement("div", { className: "px-5 py-4 space-y-5" }, /* @__PURE__ */ React17.createElement("div", null, /* @__PURE__ */ React17.createElement(
|
|
2104
2684
|
"input",
|
|
2105
2685
|
{
|
|
2106
2686
|
type: "text",
|
|
@@ -2109,132 +2689,160 @@ var EventModal = ({
|
|
|
2109
2689
|
className: "w-full text-xl font-semibold border-0 border-b-2 border-transparent focus:border-primary bg-transparent px-0 py-2 placeholder-muted-foreground/50 transition-all text-foreground focus:outline-none",
|
|
2110
2690
|
value: formData.title,
|
|
2111
2691
|
onChange: (e) => setFormData({ ...formData, title: e.target.value }),
|
|
2112
|
-
placeholder:
|
|
2692
|
+
placeholder: t.title,
|
|
2693
|
+
"aria-label": t.title
|
|
2113
2694
|
}
|
|
2114
|
-
)), /* @__PURE__ */
|
|
2695
|
+
)), /* @__PURE__ */ React17.createElement("div", { className: "flex items-center justify-between px-1" }, /* @__PURE__ */ React17.createElement("span", { id: "calendarkit-all-day-label", className: "text-sm font-medium text-foreground" }, t.allDay), /* @__PURE__ */ React17.createElement(
|
|
2696
|
+
"button",
|
|
2697
|
+
{
|
|
2698
|
+
type: "button",
|
|
2699
|
+
role: "switch",
|
|
2700
|
+
"aria-checked": !!formData.allDay,
|
|
2701
|
+
"aria-labelledby": "calendarkit-all-day-label",
|
|
2702
|
+
onClick: handleAllDayToggle,
|
|
2703
|
+
className: cn(
|
|
2704
|
+
"relative inline-flex h-6 w-11 shrink-0 rounded-full border-2 border-transparent transition-colors cursor-pointer",
|
|
2705
|
+
formData.allDay ? "bg-primary" : "bg-muted"
|
|
2706
|
+
)
|
|
2707
|
+
},
|
|
2708
|
+
/* @__PURE__ */ React17.createElement(
|
|
2709
|
+
"span",
|
|
2710
|
+
{
|
|
2711
|
+
className: cn(
|
|
2712
|
+
"pointer-events-none inline-block h-5 w-5 rounded-full bg-background shadow transition-transform",
|
|
2713
|
+
formData.allDay ? "translate-x-5" : "translate-x-0"
|
|
2714
|
+
)
|
|
2715
|
+
}
|
|
2716
|
+
)
|
|
2717
|
+
)), /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-3 p-4 rounded-2xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React17.createElement("div", { className: "p-2 bg-primary/10 rounded-xl shrink-0" }, /* @__PURE__ */ React17.createElement(Clock2, { className: "w-5 h-5 text-primary" })), /* @__PURE__ */ React17.createElement("div", { className: "flex-1 grid grid-cols-2 gap-3" }, /* @__PURE__ */ React17.createElement("div", null, /* @__PURE__ */ React17.createElement("label", { htmlFor: "calendarkit-event-start", className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, t.start), /* @__PURE__ */ React17.createElement(
|
|
2115
2718
|
"input",
|
|
2116
2719
|
{
|
|
2117
|
-
|
|
2720
|
+
id: "calendarkit-event-start",
|
|
2721
|
+
type: allDaySpan ? "date" : "datetime-local",
|
|
2118
2722
|
className: "w-full bg-background border border-border/50 rounded-xl px-3 py-2 text-sm font-medium text-foreground focus:border-primary focus:ring-2 focus:ring-primary/20 transition-all",
|
|
2119
|
-
value: formatDateForInput(formData.start),
|
|
2723
|
+
value: allDaySpan ? format14(allDaySpan.firstDay, "yyyy-MM-dd") : formatDateForInput(formData.start),
|
|
2120
2724
|
onChange: (e) => handleDateChange("start", e.target.value)
|
|
2121
2725
|
}
|
|
2122
|
-
)), /* @__PURE__ */
|
|
2726
|
+
)), /* @__PURE__ */ React17.createElement("div", null, /* @__PURE__ */ React17.createElement("label", { htmlFor: "calendarkit-event-end", className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, t.end), /* @__PURE__ */ React17.createElement(
|
|
2123
2727
|
"input",
|
|
2124
2728
|
{
|
|
2125
|
-
|
|
2729
|
+
id: "calendarkit-event-end",
|
|
2730
|
+
type: allDaySpan ? "date" : "datetime-local",
|
|
2126
2731
|
className: "w-full bg-background border border-border/50 rounded-xl px-3 py-2 text-sm font-medium text-foreground focus:border-primary focus:ring-2 focus:ring-primary/20 transition-all",
|
|
2127
|
-
value: formatDateForInput(formData.end),
|
|
2732
|
+
value: allDaySpan ? format14(allDaySpan.lastDay, "yyyy-MM-dd") : formatDateForInput(formData.end),
|
|
2128
2733
|
onChange: (e) => handleDateChange("end", e.target.value)
|
|
2129
2734
|
}
|
|
2130
|
-
)))), getDurationText() && /* @__PURE__ */
|
|
2735
|
+
)))), getDurationText() && /* @__PURE__ */ React17.createElement("div", { className: "flex justify-center" }, /* @__PURE__ */ React17.createElement("span", { className: "text-xs font-medium px-3 py-1 rounded-full bg-primary/10 text-primary" }, getDurationText())), /* @__PURE__ */ React17.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement(Bell2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React17.createElement("span", { className: "text-sm font-medium text-foreground" }, t.reminders)), /* @__PURE__ */ React17.createElement("div", { className: "relative" }, /* @__PURE__ */ React17.createElement(
|
|
2131
2736
|
"button",
|
|
2132
2737
|
{
|
|
2133
2738
|
type: "button",
|
|
2134
2739
|
onClick: () => setIsReminderDropdownOpen(!isReminderDropdownOpen),
|
|
2135
2740
|
className: "flex items-center gap-1 text-xs font-medium text-primary hover:text-primary/80 transition-colors"
|
|
2136
2741
|
},
|
|
2137
|
-
/* @__PURE__ */
|
|
2138
|
-
|
|
2139
|
-
), isReminderDropdownOpen && /* @__PURE__ */
|
|
2742
|
+
/* @__PURE__ */ React17.createElement(Plus3, { className: "w-3.5 h-3.5" }),
|
|
2743
|
+
t.add
|
|
2744
|
+
), isReminderDropdownOpen && /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsReminderDropdownOpen(false) }), /* @__PURE__ */ React17.createElement("div", { className: "absolute right-0 top-full mt-1 w-48 bg-background border border-border rounded-xl shadow-xl z-50 py-1 max-h-60 overflow-y-auto" }, REMINDER_OPTIONS.map((minutes) => /* @__PURE__ */ React17.createElement(
|
|
2140
2745
|
"button",
|
|
2141
2746
|
{
|
|
2142
|
-
key:
|
|
2747
|
+
key: minutes,
|
|
2143
2748
|
type: "button",
|
|
2144
|
-
onClick: () => addReminder(
|
|
2749
|
+
onClick: () => addReminder(minutes),
|
|
2145
2750
|
className: "w-full px-3 py-2 text-left text-sm hover:bg-accent transition-colors"
|
|
2146
2751
|
},
|
|
2147
|
-
|
|
2148
|
-
)))))), formData.reminders && formData.reminders.length > 0 && /* @__PURE__ */
|
|
2752
|
+
reminderLabel(minutes, t)
|
|
2753
|
+
)))))), formData.reminders && formData.reminders.length > 0 && /* @__PURE__ */ React17.createElement("div", { className: "flex flex-wrap gap-2" }, formData.reminders.map((reminder) => /* @__PURE__ */ React17.createElement(
|
|
2149
2754
|
"div",
|
|
2150
2755
|
{
|
|
2151
2756
|
key: reminder.id,
|
|
2152
2757
|
className: "flex items-center gap-2 px-3 py-1.5 rounded-full bg-amber-500/10 border border-amber-500/20"
|
|
2153
2758
|
},
|
|
2154
|
-
/* @__PURE__ */
|
|
2155
|
-
/* @__PURE__ */
|
|
2156
|
-
/* @__PURE__ */
|
|
2759
|
+
/* @__PURE__ */ React17.createElement(BellRing, { className: "w-3.5 h-3.5 text-amber-500" }),
|
|
2760
|
+
/* @__PURE__ */ React17.createElement("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400" }, reminder.label || reminderLabel(reminder.time, t)),
|
|
2761
|
+
/* @__PURE__ */ React17.createElement(
|
|
2157
2762
|
"button",
|
|
2158
2763
|
{
|
|
2159
2764
|
type: "button",
|
|
2160
2765
|
onClick: () => removeReminder(reminder.id),
|
|
2161
|
-
className: "p-0.5 hover:bg-amber-500/20 rounded-full transition-colors"
|
|
2766
|
+
className: "p-0.5 hover:bg-amber-500/20 rounded-full transition-colors",
|
|
2767
|
+
"aria-label": t.removeReminder
|
|
2162
2768
|
},
|
|
2163
|
-
/* @__PURE__ */
|
|
2769
|
+
/* @__PURE__ */ React17.createElement(X2, { className: "w-3 h-3 text-amber-500" })
|
|
2164
2770
|
)
|
|
2165
|
-
)))), /* @__PURE__ */
|
|
2166
|
-
"
|
|
2167
|
-
{
|
|
2168
|
-
type: "button",
|
|
2169
|
-
onClick: () => setIsGuestsDropdownOpen(!isGuestsDropdownOpen),
|
|
2170
|
-
className: "w-full flex items-center justify-between px-4 py-3 bg-muted/20 border border-border/30 rounded-xl text-sm text-left hover:bg-muted/30 transition-all"
|
|
2171
|
-
},
|
|
2172
|
-
/* @__PURE__ */ React15.createElement("span", { className: selectedGuests.length > 0 ? "text-foreground font-medium" : "text-muted-foreground" }, selectedGuests.length > 0 ? `${selectedGuests.length} guest${selectedGuests.length > 1 ? "s" : ""} added` : "Add guests"),
|
|
2173
|
-
/* @__PURE__ */ React15.createElement(ChevronDown2, { className: cn("w-4 h-4 text-muted-foreground transition-transform", isGuestsDropdownOpen && "rotate-180") })
|
|
2174
|
-
), isGuestsDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsGuestsDropdownOpen(false) }), /* @__PURE__ */ React15.createElement("div", { className: "absolute z-50 w-full mt-2 bg-background border border-border rounded-xl shadow-xl max-h-48 overflow-y-auto" }, fakeGuests.map((email) => /* @__PURE__ */ React15.createElement(
|
|
2175
|
-
"div",
|
|
2771
|
+
)))), /* @__PURE__ */ React17.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement(Users2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React17.createElement("label", { htmlFor: "calendarkit-event-guest", className: "text-sm font-medium text-foreground" }, t.guests)), /* @__PURE__ */ React17.createElement(
|
|
2772
|
+
"input",
|
|
2176
2773
|
{
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(
|
|
2186
|
-
"div",
|
|
2187
|
-
{
|
|
2188
|
-
className: "w-7 h-7 rounded-full flex items-center justify-center text-xs font-semibold text-white",
|
|
2189
|
-
style: { backgroundColor: `hsl(${fakeGuests.indexOf(email) * 60}, 70%, 50%)` }
|
|
2774
|
+
id: "calendarkit-event-guest",
|
|
2775
|
+
type: "text",
|
|
2776
|
+
inputMode: "email",
|
|
2777
|
+
autoComplete: "email",
|
|
2778
|
+
value: guestInput,
|
|
2779
|
+
onChange: (e) => {
|
|
2780
|
+
setGuestInput(e.target.value);
|
|
2781
|
+
setGuestError(false);
|
|
2190
2782
|
},
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2783
|
+
onKeyDown: (e) => {
|
|
2784
|
+
if (e.key === "Enter" || e.key === ",") {
|
|
2785
|
+
e.preventDefault();
|
|
2786
|
+
addGuests(guestInput);
|
|
2787
|
+
}
|
|
2788
|
+
},
|
|
2789
|
+
onBlur: () => guestInput.trim() && addGuests(guestInput),
|
|
2790
|
+
placeholder: t.addGuestPlaceholder,
|
|
2791
|
+
"aria-invalid": guestError,
|
|
2792
|
+
className: cn(
|
|
2793
|
+
"w-full px-4 py-3 bg-muted/20 border rounded-xl text-sm text-foreground placeholder-muted-foreground focus:outline-none focus:border-primary transition-all",
|
|
2794
|
+
guestError ? "border-destructive" : "border-border/30"
|
|
2795
|
+
)
|
|
2796
|
+
}
|
|
2797
|
+
), guestError && /* @__PURE__ */ React17.createElement("p", { role: "alert", className: "text-xs text-destructive" }, t.invalidEmail), guests.length > 0 && /* @__PURE__ */ React17.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, guests.map((email) => /* @__PURE__ */ React17.createElement(
|
|
2194
2798
|
"div",
|
|
2195
2799
|
{
|
|
2196
2800
|
key: email,
|
|
2197
2801
|
className: "flex items-center gap-2 pl-1 pr-2 py-1 bg-muted/30 border border-border/30 rounded-full"
|
|
2198
2802
|
},
|
|
2199
|
-
/* @__PURE__ */
|
|
2803
|
+
/* @__PURE__ */ React17.createElement(
|
|
2200
2804
|
"div",
|
|
2201
2805
|
{
|
|
2202
2806
|
className: "w-6 h-6 rounded-full flex items-center justify-center text-xs font-semibold text-white",
|
|
2203
|
-
style: { backgroundColor: `hsl(${
|
|
2807
|
+
style: { backgroundColor: `hsl(${avatarHue(email)}, 70%, 50%)` }
|
|
2204
2808
|
},
|
|
2205
2809
|
email[0].toUpperCase()
|
|
2206
2810
|
),
|
|
2207
|
-
/* @__PURE__ */
|
|
2208
|
-
/* @__PURE__ */
|
|
2811
|
+
/* @__PURE__ */ React17.createElement("span", { className: "text-xs font-medium text-foreground" }, email),
|
|
2812
|
+
/* @__PURE__ */ React17.createElement(
|
|
2209
2813
|
"button",
|
|
2210
2814
|
{
|
|
2211
2815
|
type: "button",
|
|
2212
|
-
onClick: () =>
|
|
2213
|
-
className: "p-0.5 hover:bg-destructive/10 rounded-full transition-colors"
|
|
2816
|
+
onClick: () => removeGuest(email),
|
|
2817
|
+
className: "p-0.5 hover:bg-destructive/10 rounded-full transition-colors",
|
|
2818
|
+
"aria-label": interpolate(t.removeGuest, { email })
|
|
2214
2819
|
},
|
|
2215
|
-
/* @__PURE__ */
|
|
2820
|
+
/* @__PURE__ */ React17.createElement(X2, { className: "w-3 h-3 text-muted-foreground" })
|
|
2216
2821
|
)
|
|
2217
|
-
)))), /* @__PURE__ */
|
|
2822
|
+
)))), /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React17.createElement(MapPin, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ React17.createElement(
|
|
2218
2823
|
"input",
|
|
2219
2824
|
{
|
|
2220
2825
|
type: "text",
|
|
2221
2826
|
className: "flex-1 bg-transparent text-sm text-foreground placeholder-muted-foreground focus:outline-none",
|
|
2222
|
-
placeholder:
|
|
2827
|
+
placeholder: t.addLocation,
|
|
2828
|
+
"aria-label": t.addLocation,
|
|
2223
2829
|
value: formData.location || "",
|
|
2224
2830
|
onChange: (e) => setFormData({ ...formData, location: e.target.value })
|
|
2225
2831
|
}
|
|
2226
|
-
)), /* @__PURE__ */
|
|
2832
|
+
)), /* @__PURE__ */ React17.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement(AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React17.createElement("span", { className: "text-sm font-medium text-foreground" }, t.notesLabel)), /* @__PURE__ */ React17.createElement(
|
|
2227
2833
|
"textarea",
|
|
2228
2834
|
{
|
|
2229
2835
|
className: "w-full bg-muted/20 border border-border/30 rounded-xl px-4 py-3 text-sm min-h-[100px] resize-none text-foreground placeholder-muted-foreground focus:border-primary focus:ring-2 focus:ring-primary/20 transition-all",
|
|
2230
|
-
placeholder:
|
|
2836
|
+
placeholder: t.addNotes,
|
|
2837
|
+
"aria-label": t.notesLabel,
|
|
2231
2838
|
value: formData.description || "",
|
|
2232
2839
|
onChange: (e) => setFormData({ ...formData, description: e.target.value })
|
|
2233
2840
|
}
|
|
2234
|
-
)), /* @__PURE__ */
|
|
2841
|
+
)), /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React17.createElement(Repeat, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ React17.createElement(
|
|
2235
2842
|
"select",
|
|
2236
2843
|
{
|
|
2237
2844
|
className: "flex-1 bg-transparent text-sm text-foreground focus:outline-none cursor-pointer",
|
|
2845
|
+
"aria-label": t.repeat,
|
|
2238
2846
|
value: formData.recurrence?.freq || "",
|
|
2239
2847
|
onChange: (e) => {
|
|
2240
2848
|
if (e.target.value === "") {
|
|
@@ -2250,28 +2858,28 @@ var EventModal = ({
|
|
|
2250
2858
|
}
|
|
2251
2859
|
}
|
|
2252
2860
|
},
|
|
2253
|
-
/* @__PURE__ */
|
|
2254
|
-
/* @__PURE__ */
|
|
2255
|
-
/* @__PURE__ */
|
|
2256
|
-
/* @__PURE__ */
|
|
2257
|
-
/* @__PURE__ */
|
|
2258
|
-
)), /* @__PURE__ */
|
|
2861
|
+
/* @__PURE__ */ React17.createElement("option", { value: "" }, t.doesNotRepeat),
|
|
2862
|
+
/* @__PURE__ */ React17.createElement("option", { value: "DAILY" }, t.daily),
|
|
2863
|
+
/* @__PURE__ */ React17.createElement("option", { value: "WEEKLY" }, t.weekly),
|
|
2864
|
+
/* @__PURE__ */ React17.createElement("option", { value: "MONTHLY" }, t.monthly),
|
|
2865
|
+
/* @__PURE__ */ React17.createElement("option", { value: "YEARLY" }, t.yearly)
|
|
2866
|
+
)), calendars && calendars.length > 0 && /* @__PURE__ */ React17.createElement("div", { className: "flex items-center justify-between p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement(Tag, { className: "w-5 h-5 text-muted-foreground" }), /* @__PURE__ */ React17.createElement("span", { className: "text-sm text-foreground" }, t.calendar)), /* @__PURE__ */ React17.createElement("div", { className: "relative" }, /* @__PURE__ */ React17.createElement(
|
|
2259
2867
|
"button",
|
|
2260
2868
|
{
|
|
2261
2869
|
type: "button",
|
|
2262
2870
|
onClick: () => setIsCalendarDropdownOpen(!isCalendarDropdownOpen),
|
|
2263
2871
|
className: "flex items-center gap-2 px-3 py-1.5 bg-background border border-border/50 rounded-lg text-sm hover:bg-accent/50 transition-all"
|
|
2264
2872
|
},
|
|
2265
|
-
/* @__PURE__ */
|
|
2873
|
+
/* @__PURE__ */ React17.createElement(
|
|
2266
2874
|
"div",
|
|
2267
2875
|
{
|
|
2268
2876
|
className: "w-3 h-3 rounded-full",
|
|
2269
|
-
style: { backgroundColor: calendars
|
|
2877
|
+
style: { backgroundColor: calendars.find((c) => c.id === formData.calendarId)?.color || "#3b82f6" }
|
|
2270
2878
|
}
|
|
2271
2879
|
),
|
|
2272
|
-
/* @__PURE__ */
|
|
2273
|
-
/* @__PURE__ */
|
|
2274
|
-
), isCalendarDropdownOpen && /* @__PURE__ */
|
|
2880
|
+
/* @__PURE__ */ React17.createElement("span", { className: "font-medium" }, calendars.find((c) => c.id === formData.calendarId)?.label || t.select),
|
|
2881
|
+
/* @__PURE__ */ React17.createElement(ChevronDown2, { className: "w-3.5 h-3.5 text-muted-foreground" })
|
|
2882
|
+
), isCalendarDropdownOpen && /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsCalendarDropdownOpen(false) }), /* @__PURE__ */ React17.createElement("div", { className: "absolute right-0 bottom-full mb-2 w-48 bg-background border border-border rounded-xl shadow-xl z-50 py-1" }, calendars.map((cal) => /* @__PURE__ */ React17.createElement(
|
|
2275
2883
|
"button",
|
|
2276
2884
|
{
|
|
2277
2885
|
key: cal.id,
|
|
@@ -2286,35 +2894,35 @@ var EventModal = ({
|
|
|
2286
2894
|
setIsCalendarDropdownOpen(false);
|
|
2287
2895
|
}
|
|
2288
2896
|
},
|
|
2289
|
-
/* @__PURE__ */
|
|
2290
|
-
/* @__PURE__ */
|
|
2291
|
-
formData.calendarId === cal.id && /* @__PURE__ */
|
|
2292
|
-
)))))))), /* @__PURE__ */
|
|
2897
|
+
/* @__PURE__ */ React17.createElement("div", { className: "w-3 h-3 rounded-full", style: { backgroundColor: cal.color } }),
|
|
2898
|
+
/* @__PURE__ */ React17.createElement("span", { className: "flex-1 text-sm" }, cal.label),
|
|
2899
|
+
formData.calendarId === cal.id && /* @__PURE__ */ React17.createElement(Check, { className: "w-4 h-4 text-primary" })
|
|
2900
|
+
)))))))), /* @__PURE__ */ React17.createElement("div", { className: "px-5 py-4 border-t border-border/50 flex items-center justify-between bg-muted/10 shrink-0" }, mode === "edit" && /* @__PURE__ */ React17.createElement(
|
|
2293
2901
|
"button",
|
|
2294
2902
|
{
|
|
2295
2903
|
type: "button",
|
|
2296
2904
|
onClick: handleDelete,
|
|
2297
2905
|
className: "flex items-center gap-2 px-4 py-2 text-destructive hover:bg-destructive/10 rounded-xl transition-all text-sm font-medium"
|
|
2298
2906
|
},
|
|
2299
|
-
/* @__PURE__ */
|
|
2300
|
-
|
|
2301
|
-
), mode === "create" && /* @__PURE__ */
|
|
2907
|
+
/* @__PURE__ */ React17.createElement(Trash2, { className: "w-4 h-4" }),
|
|
2908
|
+
t.delete
|
|
2909
|
+
), mode === "create" && /* @__PURE__ */ React17.createElement("div", null), /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement(
|
|
2302
2910
|
"button",
|
|
2303
2911
|
{
|
|
2304
2912
|
type: "button",
|
|
2305
2913
|
onClick: onClose,
|
|
2306
2914
|
className: "px-4 py-2.5 text-muted-foreground hover:text-foreground font-medium text-sm rounded-xl transition-all hover:bg-accent"
|
|
2307
2915
|
},
|
|
2308
|
-
|
|
2309
|
-
), /* @__PURE__ */
|
|
2916
|
+
t.cancel
|
|
2917
|
+
), /* @__PURE__ */ React17.createElement(
|
|
2310
2918
|
"button",
|
|
2311
2919
|
{
|
|
2312
2920
|
type: "submit",
|
|
2313
2921
|
className: "px-6 py-2.5 bg-primary hover:bg-primary/90 text-primary-foreground font-semibold text-sm rounded-xl shadow-md transition-all hover:shadow-lg hover:shadow-primary/20 active:scale-95"
|
|
2314
2922
|
},
|
|
2315
|
-
mode === "edit" ?
|
|
2923
|
+
mode === "edit" ? t.saveChanges : t.createEvent
|
|
2316
2924
|
))));
|
|
2317
|
-
return /* @__PURE__ */
|
|
2925
|
+
return /* @__PURE__ */ React17.createElement(Modal, { isOpen, onClose, hideHeader: true, className: "p-0 overflow-hidden max-w-lg rounded-2xl shadow-2xl" }, /* @__PURE__ */ React17.createElement(AnimatePresence, { mode: "wait" }, mode === "view" && event ? /* @__PURE__ */ React17.createElement(
|
|
2318
2926
|
motion2.div,
|
|
2319
2927
|
{
|
|
2320
2928
|
key: "view",
|
|
@@ -2324,7 +2932,7 @@ var EventModal = ({
|
|
|
2324
2932
|
transition: { duration: 0.15 }
|
|
2325
2933
|
},
|
|
2326
2934
|
renderViewMode()
|
|
2327
|
-
) : /* @__PURE__ */
|
|
2935
|
+
) : /* @__PURE__ */ React17.createElement(
|
|
2328
2936
|
motion2.div,
|
|
2329
2937
|
{
|
|
2330
2938
|
key: "edit",
|
|
@@ -2338,10 +2946,10 @@ var EventModal = ({
|
|
|
2338
2946
|
};
|
|
2339
2947
|
|
|
2340
2948
|
// src/components/Skeleton.tsx
|
|
2341
|
-
import
|
|
2342
|
-
var Skeleton = ({ className, style }) => /* @__PURE__ */
|
|
2343
|
-
var MonthViewSkeleton = () => /* @__PURE__ */
|
|
2344
|
-
var WeekViewSkeleton = () => /* @__PURE__ */
|
|
2949
|
+
import React18 from "react";
|
|
2950
|
+
var Skeleton = ({ className, style }) => /* @__PURE__ */ React18.createElement("div", { className: cn("animate-pulse bg-muted/40 rounded", className), style });
|
|
2951
|
+
var MonthViewSkeleton = () => /* @__PURE__ */ React18.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React18.createElement("div", { className: "grid grid-cols-7 border-b border-border/50 bg-muted/10" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ React18.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-4 w-8 mx-auto" })))), /* @__PURE__ */ React18.createElement("div", { className: "grid grid-cols-7 flex-1" }, Array.from({ length: 35 }).map((_, i) => /* @__PURE__ */ React18.createElement("div", { key: i, className: "min-h-[120px] border-r border-b border-border/30 p-2" }, /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-4 w-6 mb-2" }), /* @__PURE__ */ React18.createElement("div", { className: "space-y-1" }, i * 7 % 10 > 4 && /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-5 w-full rounded-md" }), i * 3 % 10 > 6 && /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-5 w-3/4 rounded-md" }))))));
|
|
2952
|
+
var WeekViewSkeleton = () => /* @__PURE__ */ React18.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React18.createElement("div", { className: "flex border-b border-border/50 bg-muted/10" }, /* @__PURE__ */ React18.createElement("div", { className: "w-16 p-3 border-r border-border/30" }, /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-8 w-10 mx-auto" })), /* @__PURE__ */ React18.createElement("div", { className: "flex-1 grid grid-cols-7" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ React18.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-3 w-8 mx-auto mb-1" }), /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-8 w-8 mx-auto rounded-xl" }))))), /* @__PURE__ */ React18.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ React18.createElement("div", { className: "w-16 border-r border-border/30" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ React18.createElement("div", { key: i, className: "h-[60px] relative" }, /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-4 w-10 absolute right-2 -translate-y-1/2" })))), /* @__PURE__ */ React18.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, Array.from({ length: 7 }).map((_, colIdx) => /* @__PURE__ */ React18.createElement("div", { key: colIdx, className: "relative border-r border-border/30 last:border-r-0" }, Array.from({ length: 10 }).map((_2, rowIdx) => /* @__PURE__ */ React18.createElement("div", { key: rowIdx, className: "h-[60px] border-b border-dashed border-border/20" })), Math.random() > 0.3 && /* @__PURE__ */ React18.createElement(
|
|
2345
2953
|
Skeleton,
|
|
2346
2954
|
{
|
|
2347
2955
|
className: "absolute rounded-md",
|
|
@@ -2353,23 +2961,23 @@ var WeekViewSkeleton = () => /* @__PURE__ */ React16.createElement("div", { clas
|
|
|
2353
2961
|
}
|
|
2354
2962
|
}
|
|
2355
2963
|
))))));
|
|
2356
|
-
var DayViewSkeleton = () => /* @__PURE__ */
|
|
2964
|
+
var DayViewSkeleton = () => /* @__PURE__ */ React18.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React18.createElement("div", { className: "px-6 py-4 border-b border-border/50 bg-muted/10 text-center" }, /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-7 w-64 mx-auto" })), /* @__PURE__ */ React18.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ React18.createElement("div", { className: "w-20 border-r border-border/30 bg-muted/5" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ React18.createElement("div", { key: i, className: "h-[80px] relative" }, /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-4 w-12 absolute left-1/2 -translate-x-1/2 -translate-y-1/2" })))), /* @__PURE__ */ React18.createElement("div", { className: "flex-1 relative" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ React18.createElement("div", { key: i, className: "h-[80px] border-b border-dashed border-border/20" })), /* @__PURE__ */ React18.createElement(
|
|
2357
2965
|
Skeleton,
|
|
2358
2966
|
{
|
|
2359
2967
|
className: "absolute rounded-lg left-4 right-4",
|
|
2360
2968
|
style: { top: "160px", height: "120px" }
|
|
2361
2969
|
}
|
|
2362
|
-
), /* @__PURE__ */
|
|
2970
|
+
), /* @__PURE__ */ React18.createElement(
|
|
2363
2971
|
Skeleton,
|
|
2364
2972
|
{
|
|
2365
2973
|
className: "absolute rounded-lg left-4 right-4",
|
|
2366
2974
|
style: { top: "400px", height: "80px" }
|
|
2367
2975
|
}
|
|
2368
2976
|
))));
|
|
2369
|
-
var AgendaViewSkeleton = () => /* @__PURE__ */
|
|
2977
|
+
var AgendaViewSkeleton = () => /* @__PURE__ */ React18.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden p-6" }, /* @__PURE__ */ React18.createElement("div", { className: "space-y-6" }, Array.from({ length: 4 }).map((_, dayIdx) => /* @__PURE__ */ React18.createElement("div", { key: dayIdx }, /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-5 w-40 mb-4" }), /* @__PURE__ */ React18.createElement("div", { className: "space-y-3" }, Array.from({ length: 2 + Math.floor(Math.random() * 3) }).map((_2, eventIdx) => /* @__PURE__ */ React18.createElement("div", { key: eventIdx, className: "flex items-center gap-4 p-3 rounded-xl bg-muted/10" }, /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-10 w-10 rounded-lg" }), /* @__PURE__ */ React18.createElement("div", { className: "flex-1 space-y-2" }, /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-4 w-3/4" }), /* @__PURE__ */ React18.createElement(Skeleton, { className: "h-3 w-1/2" })))))))));
|
|
2370
2978
|
|
|
2371
2979
|
// src/components/ContextMenu.tsx
|
|
2372
|
-
import
|
|
2980
|
+
import React19, { useState as useState6, useCallback as useCallback3, useEffect as useEffect5, useRef as useRef6 } from "react";
|
|
2373
2981
|
import { Edit3, Trash2 as Trash22, Copy } from "lucide-react";
|
|
2374
2982
|
import { AnimatePresence as AnimatePresence2, motion as motion3 } from "framer-motion";
|
|
2375
2983
|
var EventContextMenu = ({
|
|
@@ -2382,8 +2990,8 @@ var EventContextMenu = ({
|
|
|
2382
2990
|
customActions = [],
|
|
2383
2991
|
translations
|
|
2384
2992
|
}) => {
|
|
2385
|
-
const menuRef =
|
|
2386
|
-
|
|
2993
|
+
const menuRef = useRef6(null);
|
|
2994
|
+
useEffect5(() => {
|
|
2387
2995
|
const handleKeyDown = (e) => {
|
|
2388
2996
|
if (e.key === "Escape") {
|
|
2389
2997
|
onClose();
|
|
@@ -2394,7 +3002,7 @@ var EventContextMenu = ({
|
|
|
2394
3002
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
2395
3003
|
}
|
|
2396
3004
|
}, [position, onClose]);
|
|
2397
|
-
|
|
3005
|
+
useEffect5(() => {
|
|
2398
3006
|
const handleClickOutside = (e) => {
|
|
2399
3007
|
if (menuRef.current && !menuRef.current.contains(e.target)) {
|
|
2400
3008
|
onClose();
|
|
@@ -2412,7 +3020,7 @@ var EventContextMenu = ({
|
|
|
2412
3020
|
...onEdit ? [{
|
|
2413
3021
|
id: "edit",
|
|
2414
3022
|
label: translations?.edit || "Edit",
|
|
2415
|
-
icon: /* @__PURE__ */
|
|
3023
|
+
icon: /* @__PURE__ */ React19.createElement(Edit3, { className: "w-4 h-4" }),
|
|
2416
3024
|
onClick: () => {
|
|
2417
3025
|
onEdit(event);
|
|
2418
3026
|
onClose();
|
|
@@ -2421,7 +3029,7 @@ var EventContextMenu = ({
|
|
|
2421
3029
|
...onDuplicate ? [{
|
|
2422
3030
|
id: "duplicate",
|
|
2423
3031
|
label: translations?.duplicate || "Duplicate",
|
|
2424
|
-
icon: /* @__PURE__ */
|
|
3032
|
+
icon: /* @__PURE__ */ React19.createElement(Copy, { className: "w-4 h-4" }),
|
|
2425
3033
|
onClick: () => {
|
|
2426
3034
|
onDuplicate(event);
|
|
2427
3035
|
onClose();
|
|
@@ -2431,7 +3039,7 @@ var EventContextMenu = ({
|
|
|
2431
3039
|
...onDelete ? [{
|
|
2432
3040
|
id: "delete",
|
|
2433
3041
|
label: translations?.delete || "Delete",
|
|
2434
|
-
icon: /* @__PURE__ */
|
|
3042
|
+
icon: /* @__PURE__ */ React19.createElement(Trash22, { className: "w-4 h-4" }),
|
|
2435
3043
|
onClick: () => {
|
|
2436
3044
|
onDelete(event.id);
|
|
2437
3045
|
onClose();
|
|
@@ -2443,7 +3051,7 @@ var EventContextMenu = ({
|
|
|
2443
3051
|
x: Math.min(position.x, window.innerWidth - 200),
|
|
2444
3052
|
y: Math.min(position.y, window.innerHeight - (actions.length * 44 + 80))
|
|
2445
3053
|
};
|
|
2446
|
-
return /* @__PURE__ */
|
|
3054
|
+
return /* @__PURE__ */ React19.createElement(AnimatePresence2, null, /* @__PURE__ */ React19.createElement(
|
|
2447
3055
|
motion3.div,
|
|
2448
3056
|
{
|
|
2449
3057
|
ref: menuRef,
|
|
@@ -2457,14 +3065,14 @@ var EventContextMenu = ({
|
|
|
2457
3065
|
top: adjustedPosition.y
|
|
2458
3066
|
}
|
|
2459
3067
|
},
|
|
2460
|
-
/* @__PURE__ */
|
|
3068
|
+
/* @__PURE__ */ React19.createElement("div", { className: "px-3 py-2 border-b-[0.5px] border-border bg-muted/30" }, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React19.createElement(
|
|
2461
3069
|
"div",
|
|
2462
3070
|
{
|
|
2463
3071
|
className: "w-2.5 h-2.5 rounded-full shrink-0",
|
|
2464
3072
|
style: { backgroundColor: event.color || "var(--primary)" }
|
|
2465
3073
|
}
|
|
2466
|
-
), /* @__PURE__ */
|
|
2467
|
-
/* @__PURE__ */
|
|
3074
|
+
), /* @__PURE__ */ React19.createElement("span", { className: "text-sm font-medium truncate text-foreground" }, event.title))),
|
|
3075
|
+
/* @__PURE__ */ React19.createElement("div", { className: "py-1" }, actions.map((action, index) => /* @__PURE__ */ React19.createElement(React19.Fragment, { key: action.id }, index > 0 && action.variant === "danger" && /* @__PURE__ */ React19.createElement("div", { className: "h-px bg-border my-1" }), /* @__PURE__ */ React19.createElement(
|
|
2468
3076
|
"button",
|
|
2469
3077
|
{
|
|
2470
3078
|
onClick: action.onClick,
|
|
@@ -2476,13 +3084,13 @@ var EventContextMenu = ({
|
|
|
2476
3084
|
)
|
|
2477
3085
|
},
|
|
2478
3086
|
action.icon,
|
|
2479
|
-
/* @__PURE__ */
|
|
3087
|
+
/* @__PURE__ */ React19.createElement("span", null, action.label)
|
|
2480
3088
|
))))
|
|
2481
3089
|
));
|
|
2482
3090
|
};
|
|
2483
3091
|
var useEventContextMenu = () => {
|
|
2484
|
-
const [contextMenu, setContextMenu] =
|
|
2485
|
-
const openContextMenu =
|
|
3092
|
+
const [contextMenu, setContextMenu] = useState6({ event: null, position: null });
|
|
3093
|
+
const openContextMenu = useCallback3((event, e) => {
|
|
2486
3094
|
e.preventDefault();
|
|
2487
3095
|
e.stopPropagation();
|
|
2488
3096
|
setContextMenu({
|
|
@@ -2490,7 +3098,7 @@ var useEventContextMenu = () => {
|
|
|
2490
3098
|
position: { x: e.clientX, y: e.clientY }
|
|
2491
3099
|
});
|
|
2492
3100
|
}, []);
|
|
2493
|
-
const closeContextMenu =
|
|
3101
|
+
const closeContextMenu = useCallback3(() => {
|
|
2494
3102
|
setContextMenu({ event: null, position: null });
|
|
2495
3103
|
}, []);
|
|
2496
3104
|
return {
|
|
@@ -2581,13 +3189,13 @@ function getThemeStyles(theme) {
|
|
|
2581
3189
|
}
|
|
2582
3190
|
|
|
2583
3191
|
// src/hooks/useCalendarLogic.ts
|
|
2584
|
-
import { useMemo as useMemo3, useState as
|
|
3192
|
+
import { useMemo as useMemo3, useState as useState7 } from "react";
|
|
2585
3193
|
import {
|
|
2586
|
-
addDays as
|
|
3194
|
+
addDays as addDays9,
|
|
2587
3195
|
addMonths as addMonths3,
|
|
2588
3196
|
addWeeks,
|
|
2589
3197
|
endOfMonth as endOfMonth2,
|
|
2590
|
-
format as
|
|
3198
|
+
format as format15,
|
|
2591
3199
|
startOfMonth as startOfMonth3,
|
|
2592
3200
|
startOfWeek as startOfWeek2,
|
|
2593
3201
|
subDays,
|
|
@@ -2673,16 +3281,18 @@ function cachedMonth(event, monthStart, tz) {
|
|
|
2673
3281
|
}
|
|
2674
3282
|
function expandRecurrences(events, range, anchorTz) {
|
|
2675
3283
|
const result = [];
|
|
2676
|
-
const firstMonth = startOfMonth2(toDisplay(range.start, anchorTz));
|
|
2677
|
-
const lastMonth = startOfMonth2(toDisplay(range.end, anchorTz));
|
|
2678
3284
|
for (const event of events) {
|
|
2679
3285
|
if (!event.recurrence) {
|
|
2680
3286
|
result.push(event);
|
|
2681
3287
|
continue;
|
|
2682
3288
|
}
|
|
3289
|
+
const tz = event.allDay ? void 0 : anchorTz;
|
|
3290
|
+
const lastMonth = startOfMonth2(toDisplay(range.end, tz));
|
|
3291
|
+
const duration = event.end.getTime() - event.start.getTime();
|
|
3292
|
+
const firstMonth = startOfMonth2(toDisplay(new Date(range.start.getTime() - duration), tz));
|
|
2683
3293
|
try {
|
|
2684
3294
|
for (let month = firstMonth; month <= lastMonth; month = addMonths2(month, 1)) {
|
|
2685
|
-
for (const occurrence of cachedMonth(event, fromDisplay(month,
|
|
3295
|
+
for (const occurrence of cachedMonth(event, fromDisplay(month, tz), tz)) {
|
|
2686
3296
|
if (occurrence.end >= range.start && occurrence.start <= range.end) result.push(occurrence);
|
|
2687
3297
|
}
|
|
2688
3298
|
}
|
|
@@ -2698,8 +3308,8 @@ function stripOccurrenceFields(event) {
|
|
|
2698
3308
|
return rest;
|
|
2699
3309
|
}
|
|
2700
3310
|
var shiftFloating = (instant, deltaMs, tz) => fromFloating(new Date(toFloating(instant, tz).getTime() + deltaMs), tz);
|
|
2701
|
-
var
|
|
2702
|
-
var floatingDay = (floating) => Math.floor(floating.getTime() /
|
|
3311
|
+
var DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
3312
|
+
var floatingDay = (floating) => Math.floor(floating.getTime() / DAY_MS2);
|
|
2703
3313
|
function shiftSeries(master, occurrence, newStart, newEnd, anchorTz) {
|
|
2704
3314
|
const fromFloat = toFloating(occurrence.start, anchorTz);
|
|
2705
3315
|
const toFloat = toFloating(newStart, anchorTz);
|
|
@@ -2710,6 +3320,7 @@ function shiftSeries(master, occurrence, newStart, newEnd, anchorTz) {
|
|
|
2710
3320
|
const recurrence = master.recurrence && {
|
|
2711
3321
|
...master.recurrence,
|
|
2712
3322
|
byweekday: master.recurrence.byweekday && dayDelta % 7 !== 0 ? master.recurrence.byweekday.map((d) => ((d + dayDelta) % 7 + 7) % 7) : master.recurrence.byweekday,
|
|
3323
|
+
until: master.recurrence.until && shiftFloating(master.recurrence.until, deltaMs, anchorTz),
|
|
2713
3324
|
exdates: master.recurrence.exdates?.map((d) => shiftFloating(d, deltaMs, anchorTz))
|
|
2714
3325
|
};
|
|
2715
3326
|
return stripOccurrenceFields({ ...master, start, end, recurrence });
|
|
@@ -2720,21 +3331,23 @@ function excludeOccurrence(master, occurrenceStart) {
|
|
|
2720
3331
|
}
|
|
2721
3332
|
|
|
2722
3333
|
// src/hooks/useStableCallback.ts
|
|
2723
|
-
import { useCallback as
|
|
3334
|
+
import { useCallback as useCallback4, useInsertionEffect as useInsertionEffect2, useRef as useRef7 } from "react";
|
|
2724
3335
|
function useStableCallback(fn) {
|
|
2725
|
-
const ref =
|
|
2726
|
-
|
|
2727
|
-
|
|
3336
|
+
const ref = useRef7(fn);
|
|
3337
|
+
useInsertionEffect2(() => {
|
|
3338
|
+
ref.current = fn;
|
|
3339
|
+
});
|
|
3340
|
+
return useCallback4((...args) => ref.current(...args), []);
|
|
2728
3341
|
}
|
|
2729
3342
|
|
|
2730
3343
|
// src/hooks/useCalendarLogic.ts
|
|
2731
3344
|
function expansionRange(monthStart) {
|
|
2732
3345
|
return {
|
|
2733
3346
|
start: startOfWeek2(startOfMonth3(subMonths2(monthStart, 1))),
|
|
2734
|
-
end:
|
|
3347
|
+
end: addDays9(endOfMonth2(addMonths3(monthStart, 1)), 37)
|
|
2735
3348
|
};
|
|
2736
3349
|
}
|
|
2737
|
-
var
|
|
3350
|
+
var DAY_MS3 = 24 * 60 * 60 * 1e3;
|
|
2738
3351
|
var useCalendarLogic = ({
|
|
2739
3352
|
events,
|
|
2740
3353
|
view: controlledView,
|
|
@@ -2751,17 +3364,18 @@ var useCalendarLogic = ({
|
|
|
2751
3364
|
readOnly,
|
|
2752
3365
|
timezone
|
|
2753
3366
|
}) => {
|
|
2754
|
-
const [internalView, setInternalView] =
|
|
2755
|
-
const [internalDate, setInternalDate] =
|
|
2756
|
-
const [isSidebarOpen, setIsSidebarOpen] =
|
|
2757
|
-
const [isModalOpen, setIsModalOpen] =
|
|
2758
|
-
const [selectedEvent, setSelectedEvent] =
|
|
2759
|
-
const [modalInitialDate, setModalInitialDate] =
|
|
2760
|
-
const [modalInitialResourceId, setModalInitialResourceId] =
|
|
3367
|
+
const [internalView, setInternalView] = useState7("week");
|
|
3368
|
+
const [internalDate, setInternalDate] = useState7(() => /* @__PURE__ */ new Date());
|
|
3369
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState7(true);
|
|
3370
|
+
const [isModalOpen, setIsModalOpen] = useState7(false);
|
|
3371
|
+
const [selectedEvent, setSelectedEvent] = useState7(null);
|
|
3372
|
+
const [modalInitialDate, setModalInitialDate] = useState7(void 0);
|
|
3373
|
+
const [modalInitialResourceId, setModalInitialResourceId] = useState7(void 0);
|
|
3374
|
+
const [modalInitialAllDay, setModalInitialAllDay] = useState7(false);
|
|
2761
3375
|
const view = controlledView ?? internalView;
|
|
2762
3376
|
const currentDate = controlledDate ?? internalDate;
|
|
2763
3377
|
const normalizedEvents = useMemo3(() => normalizeEvents(events), [events]);
|
|
2764
|
-
const monthKey =
|
|
3378
|
+
const monthKey = format15(currentDate, "yyyy-MM");
|
|
2765
3379
|
const range = useMemo3(() => expansionRange(/* @__PURE__ */ new Date(`${monthKey}-01T00:00:00`)), [monthKey]);
|
|
2766
3380
|
const expandedEvents = useMemo3(
|
|
2767
3381
|
() => expandRecurrences(normalizedEvents, range, timezone),
|
|
@@ -2809,10 +3423,10 @@ var useCalendarLogic = ({
|
|
|
2809
3423
|
break;
|
|
2810
3424
|
case "day":
|
|
2811
3425
|
case "resource":
|
|
2812
|
-
handleDateChange(
|
|
3426
|
+
handleDateChange(addDays9(currentDate, 1));
|
|
2813
3427
|
break;
|
|
2814
3428
|
case "agenda":
|
|
2815
|
-
handleDateChange(
|
|
3429
|
+
handleDateChange(addDays9(currentDate, 7));
|
|
2816
3430
|
break;
|
|
2817
3431
|
}
|
|
2818
3432
|
});
|
|
@@ -2828,6 +3442,15 @@ var useCalendarLogic = ({
|
|
|
2828
3442
|
setSelectedEvent(null);
|
|
2829
3443
|
setModalInitialDate(date);
|
|
2830
3444
|
setModalInitialResourceId(resourceId);
|
|
3445
|
+
setModalInitialAllDay(false);
|
|
3446
|
+
setIsModalOpen(true);
|
|
3447
|
+
});
|
|
3448
|
+
const handleAllDaySlotClick = useStableCallback((day) => {
|
|
3449
|
+
if (readOnly) return;
|
|
3450
|
+
setSelectedEvent(null);
|
|
3451
|
+
setModalInitialDate(day);
|
|
3452
|
+
setModalInitialResourceId(void 0);
|
|
3453
|
+
setModalInitialAllDay(true);
|
|
2831
3454
|
setIsModalOpen(true);
|
|
2832
3455
|
});
|
|
2833
3456
|
const handleEventClickInternal = useStableCallback((event) => {
|
|
@@ -2836,6 +3459,7 @@ var useCalendarLogic = ({
|
|
|
2836
3459
|
setSelectedEvent(event);
|
|
2837
3460
|
setModalInitialDate(void 0);
|
|
2838
3461
|
setModalInitialResourceId(void 0);
|
|
3462
|
+
setModalInitialAllDay(false);
|
|
2839
3463
|
setIsModalOpen(true);
|
|
2840
3464
|
}
|
|
2841
3465
|
});
|
|
@@ -2844,6 +3468,7 @@ var useCalendarLogic = ({
|
|
|
2844
3468
|
setSelectedEvent(null);
|
|
2845
3469
|
setModalInitialDate(/* @__PURE__ */ new Date());
|
|
2846
3470
|
setModalInitialResourceId(void 0);
|
|
3471
|
+
setModalInitialAllDay(false);
|
|
2847
3472
|
setIsModalOpen(true);
|
|
2848
3473
|
});
|
|
2849
3474
|
const handleModalSave = useStableCallback((eventData) => {
|
|
@@ -2858,7 +3483,7 @@ var useCalendarLogic = ({
|
|
|
2858
3483
|
end: master.end
|
|
2859
3484
|
};
|
|
2860
3485
|
onEventUpdate?.(
|
|
2861
|
-
shiftSeries(edited, selectedEvent, eventData.start ?? selectedEvent.start, eventData.end ?? selectedEvent.end, timezone)
|
|
3486
|
+
shiftSeries(edited, selectedEvent, eventData.start ?? selectedEvent.start, eventData.end ?? selectedEvent.end, edited.allDay ? void 0 : timezone)
|
|
2862
3487
|
);
|
|
2863
3488
|
} else if (selectedEvent) {
|
|
2864
3489
|
onEventUpdate?.({ ...eventData, id: selectedEvent.id });
|
|
@@ -2893,28 +3518,39 @@ var useCalendarLogic = ({
|
|
|
2893
3518
|
...copy,
|
|
2894
3519
|
id: `${event.originalEventId ?? event.id}-copy-${Date.now()}`,
|
|
2895
3520
|
title: `${event.title} (Copy)`,
|
|
2896
|
-
start: new Date(event.start.getTime() +
|
|
2897
|
-
end: new Date(event.end.getTime() +
|
|
3521
|
+
start: new Date(event.start.getTime() + DAY_MS3),
|
|
3522
|
+
end: new Date(event.end.getTime() + DAY_MS3)
|
|
2898
3523
|
});
|
|
2899
3524
|
});
|
|
2900
3525
|
const applyChange = (event, start, end) => {
|
|
2901
3526
|
if (!event.originalEventId) return { original: event, updated: { ...event, start, end } };
|
|
2902
3527
|
const master = masterOf(event);
|
|
2903
3528
|
if (!master) return null;
|
|
2904
|
-
return { original: master, updated: shiftSeries(master, event, start, end, timezone) };
|
|
3529
|
+
return { original: master, updated: shiftSeries(master, event, start, end, event.allDay ? void 0 : timezone) };
|
|
2905
3530
|
};
|
|
2906
3531
|
const handleDragEnd = useStableCallback((dragEvent) => {
|
|
3532
|
+
if (readOnly) return;
|
|
2907
3533
|
const { active, over } = dragEvent;
|
|
2908
3534
|
if (!over) return;
|
|
2909
3535
|
const dragged = active.data.current?.event;
|
|
2910
3536
|
const overDate = over.data.current?.date;
|
|
2911
3537
|
if (!dragged || !overDate) return;
|
|
3538
|
+
const grabDayOffset = active.data.current?.grabDayOffset;
|
|
3539
|
+
if (grabDayOffset !== void 0) {
|
|
3540
|
+
const move = computeDayMove(dragged, overDate, grabDayOffset, timezone);
|
|
3541
|
+
const dayChange = move && applyChange(dragged, move.start, move.end);
|
|
3542
|
+
if (!dayChange) return;
|
|
3543
|
+
onEventDrop?.(dayChange.original, dayChange.updated.start, dayChange.updated.end);
|
|
3544
|
+
onEventUpdate?.(dayChange.updated);
|
|
3545
|
+
return;
|
|
3546
|
+
}
|
|
2912
3547
|
const drop = computeDrop({
|
|
2913
3548
|
event: dragged,
|
|
2914
3549
|
overDate,
|
|
2915
3550
|
overResourceId: over.data.current?.resourceId,
|
|
2916
3551
|
grabOffsetMs: active.data.current?.grabOffsetMs,
|
|
2917
|
-
view
|
|
3552
|
+
// A timed event dropped in the all-day row only changes day (keeps its time), like in month view.
|
|
3553
|
+
view: over.data.current?.allDayRow ? "month" : view,
|
|
2918
3554
|
tz: timezone
|
|
2919
3555
|
});
|
|
2920
3556
|
if (!drop) return;
|
|
@@ -2924,6 +3560,14 @@ var useCalendarLogic = ({
|
|
|
2924
3560
|
onEventDrop?.(change.original, updated.start, updated.end);
|
|
2925
3561
|
onEventUpdate?.(updated);
|
|
2926
3562
|
});
|
|
3563
|
+
const handleDayEventResize = useStableCallback((event, newLastDay) => {
|
|
3564
|
+
if (readOnly) return;
|
|
3565
|
+
const end = computeDayResize(event, newLastDay, timezone);
|
|
3566
|
+
const change = end && applyChange(event, event.start, end);
|
|
3567
|
+
if (!change) return;
|
|
3568
|
+
onEventResize?.(change.original, change.updated.start, change.updated.end);
|
|
3569
|
+
onEventUpdate?.(change.updated);
|
|
3570
|
+
});
|
|
2927
3571
|
const handleEventResize = useStableCallback((event, newEnd) => {
|
|
2928
3572
|
if (readOnly) return;
|
|
2929
3573
|
const change = applyChange(event, event.start, newEnd);
|
|
@@ -2940,6 +3584,7 @@ var useCalendarLogic = ({
|
|
|
2940
3584
|
setIsModalOpen,
|
|
2941
3585
|
selectedEvent,
|
|
2942
3586
|
modalInitialDate,
|
|
3587
|
+
modalInitialAllDay,
|
|
2943
3588
|
expandedEvents,
|
|
2944
3589
|
handleViewChange,
|
|
2945
3590
|
handleDateChange,
|
|
@@ -2948,6 +3593,7 @@ var useCalendarLogic = ({
|
|
|
2948
3593
|
handleToday,
|
|
2949
3594
|
handleDateClick,
|
|
2950
3595
|
handleTimeSlotClick,
|
|
3596
|
+
handleAllDaySlotClick,
|
|
2951
3597
|
handleEventClickInternal,
|
|
2952
3598
|
handleCreateEvent,
|
|
2953
3599
|
handleModalSave,
|
|
@@ -2955,15 +3601,16 @@ var useCalendarLogic = ({
|
|
|
2955
3601
|
handleEventDelete,
|
|
2956
3602
|
handleEventDuplicate,
|
|
2957
3603
|
handleEventResize,
|
|
3604
|
+
handleDayEventResize,
|
|
2958
3605
|
handleDragEnd
|
|
2959
3606
|
};
|
|
2960
3607
|
};
|
|
2961
3608
|
|
|
2962
3609
|
// src/index.tsx
|
|
2963
|
-
import {
|
|
3610
|
+
import { format as format16, startOfWeek as startOfWeek3 } from "date-fns";
|
|
2964
3611
|
|
|
2965
3612
|
// src/hooks/useSwipeGesture.ts
|
|
2966
|
-
import { useRef as
|
|
3613
|
+
import { useRef as useRef8, useCallback as useCallback5, useEffect as useEffect6 } from "react";
|
|
2967
3614
|
var useSwipeGesture = (options) => {
|
|
2968
3615
|
const {
|
|
2969
3616
|
onSwipeLeft,
|
|
@@ -2975,9 +3622,9 @@ var useSwipeGesture = (options) => {
|
|
|
2975
3622
|
allowedTime = 500,
|
|
2976
3623
|
enabled = true
|
|
2977
3624
|
} = options;
|
|
2978
|
-
const touchInfoRef =
|
|
2979
|
-
const elementRef =
|
|
2980
|
-
const handleTouchStart =
|
|
3625
|
+
const touchInfoRef = useRef8(null);
|
|
3626
|
+
const elementRef = useRef8(null);
|
|
3627
|
+
const handleTouchStart = useCallback5((e) => {
|
|
2981
3628
|
if (!enabled) return;
|
|
2982
3629
|
const touch = e.touches[0];
|
|
2983
3630
|
touchInfoRef.current = {
|
|
@@ -2986,7 +3633,7 @@ var useSwipeGesture = (options) => {
|
|
|
2986
3633
|
startTime: Date.now()
|
|
2987
3634
|
};
|
|
2988
3635
|
}, [enabled]);
|
|
2989
|
-
const handleTouchEnd =
|
|
3636
|
+
const handleTouchEnd = useCallback5((e) => {
|
|
2990
3637
|
if (!enabled || !touchInfoRef.current) return;
|
|
2991
3638
|
const touch = e.changedTouches[0];
|
|
2992
3639
|
const { startX, startY, startTime } = touchInfoRef.current;
|
|
@@ -3010,7 +3657,7 @@ var useSwipeGesture = (options) => {
|
|
|
3010
3657
|
}
|
|
3011
3658
|
touchInfoRef.current = null;
|
|
3012
3659
|
}, [enabled, threshold, restraint, allowedTime, onSwipeLeft, onSwipeRight, onSwipeUp, onSwipeDown]);
|
|
3013
|
-
|
|
3660
|
+
useEffect6(() => {
|
|
3014
3661
|
const element = elementRef.current;
|
|
3015
3662
|
if (!element) return;
|
|
3016
3663
|
element.addEventListener("touchstart", handleTouchStart, { passive: true });
|
|
@@ -3033,6 +3680,25 @@ var useViewSwipe = (onPrev, onNext, enabled = true) => {
|
|
|
3033
3680
|
});
|
|
3034
3681
|
};
|
|
3035
3682
|
|
|
3683
|
+
// src/components/dnd/dragOverlay.ts
|
|
3684
|
+
import { pointerWithin, rectIntersection } from "@dnd-kit/core";
|
|
3685
|
+
import { differenceInMinutes as differenceInMinutes6 } from "date-fns";
|
|
3686
|
+
var dayAwareCollision = (args) => {
|
|
3687
|
+
if (args.active.data.current?.grabDayOffset !== void 0) {
|
|
3688
|
+
const underPointer = pointerWithin(args);
|
|
3689
|
+
if (underPointer.length > 0) return underPointer;
|
|
3690
|
+
}
|
|
3691
|
+
return rectIntersection(args);
|
|
3692
|
+
};
|
|
3693
|
+
function dragOverlaySize(view, event, isDayDrag) {
|
|
3694
|
+
if (isDayDrag) return {};
|
|
3695
|
+
const minutes = differenceInMinutes6(event.end, event.start);
|
|
3696
|
+
if (view === "month") return { width: "100%" };
|
|
3697
|
+
if (view === "resource") return { width: `${Math.max(minutes / 60 * 100, 4)}px`, height: 80 };
|
|
3698
|
+
if (view === "week" || view === "day") return { width: "150px", height: minutes / 60 * (view === "day" ? 80 : 60) };
|
|
3699
|
+
return { width: "150px" };
|
|
3700
|
+
}
|
|
3701
|
+
|
|
3036
3702
|
// src/index.tsx
|
|
3037
3703
|
var Scheduler = ({
|
|
3038
3704
|
events = [],
|
|
@@ -3068,10 +3734,12 @@ var Scheduler = ({
|
|
|
3068
3734
|
locale
|
|
3069
3735
|
// Date-fns locale
|
|
3070
3736
|
}) => {
|
|
3071
|
-
const [activeDragEvent, setActiveDragEvent] =
|
|
3737
|
+
const [activeDragEvent, setActiveDragEvent] = useState8(null);
|
|
3738
|
+
const [activeDayDrag, setActiveDayDrag] = useState8(false);
|
|
3072
3739
|
const {
|
|
3073
3740
|
contextMenuEvent,
|
|
3074
3741
|
contextMenuPosition,
|
|
3742
|
+
openContextMenu,
|
|
3075
3743
|
closeContextMenu
|
|
3076
3744
|
} = useEventContextMenu();
|
|
3077
3745
|
const {
|
|
@@ -3083,6 +3751,7 @@ var Scheduler = ({
|
|
|
3083
3751
|
setIsModalOpen,
|
|
3084
3752
|
selectedEvent,
|
|
3085
3753
|
modalInitialDate,
|
|
3754
|
+
modalInitialAllDay,
|
|
3086
3755
|
handleViewChange,
|
|
3087
3756
|
handleDateChange,
|
|
3088
3757
|
handlePrev,
|
|
@@ -3090,6 +3759,7 @@ var Scheduler = ({
|
|
|
3090
3759
|
handleToday,
|
|
3091
3760
|
handleDateClick,
|
|
3092
3761
|
handleTimeSlotClick,
|
|
3762
|
+
handleAllDaySlotClick,
|
|
3093
3763
|
handleEventClickInternal,
|
|
3094
3764
|
handleCreateEvent,
|
|
3095
3765
|
handleModalSave,
|
|
@@ -3097,6 +3767,7 @@ var Scheduler = ({
|
|
|
3097
3767
|
handleEventDelete,
|
|
3098
3768
|
handleEventDuplicate,
|
|
3099
3769
|
handleEventResize,
|
|
3770
|
+
handleDayEventResize,
|
|
3100
3771
|
handleDragEnd,
|
|
3101
3772
|
expandedEvents
|
|
3102
3773
|
} = useCalendarLogic({
|
|
@@ -3130,59 +3801,45 @@ var Scheduler = ({
|
|
|
3130
3801
|
const swipeRef = useViewSwipe(handlePrev, handleNext, true);
|
|
3131
3802
|
const t = useMemo4(() => resolveTranslations(language, translations), [language, translations]);
|
|
3132
3803
|
const overlayTimeFormat = timeFormats(locale).time;
|
|
3133
|
-
const handleDragStart =
|
|
3804
|
+
const handleDragStart = useCallback6((event) => {
|
|
3134
3805
|
const draggedEvent = event.active.data.current?.event;
|
|
3135
3806
|
if (draggedEvent) {
|
|
3136
3807
|
setActiveDragEvent(draggedEvent);
|
|
3808
|
+
setActiveDayDrag(event.active.data.current?.grabDayOffset !== void 0);
|
|
3137
3809
|
}
|
|
3138
3810
|
}, []);
|
|
3139
|
-
const onDragEndWrapper =
|
|
3811
|
+
const onDragEndWrapper = useCallback6((event) => {
|
|
3140
3812
|
setActiveDragEvent(null);
|
|
3141
3813
|
handleDragEnd(event);
|
|
3142
3814
|
}, [handleDragEnd]);
|
|
3143
|
-
const
|
|
3144
|
-
|
|
3145
|
-
if (view === "resource") {
|
|
3146
|
-
return 80;
|
|
3147
|
-
}
|
|
3148
|
-
if (view !== "week" && view !== "day") return void 0;
|
|
3149
|
-
const duration = differenceInMinutes6(activeDragEvent.end, activeDragEvent.start);
|
|
3150
|
-
const hourHeight = view === "day" ? 80 : 60;
|
|
3151
|
-
return duration / 60 * hourHeight;
|
|
3152
|
-
};
|
|
3153
|
-
const getDragWidth = () => {
|
|
3154
|
-
if (view === "month") return "100%";
|
|
3155
|
-
if (view === "resource" && activeDragEvent) {
|
|
3156
|
-
const duration = differenceInMinutes6(activeDragEvent.end, activeDragEvent.start);
|
|
3157
|
-
const width = duration / 60 * 100;
|
|
3158
|
-
return `${Math.max(width, 4)}px`;
|
|
3159
|
-
}
|
|
3160
|
-
return "150px";
|
|
3161
|
-
};
|
|
3815
|
+
const dragSize = activeDragEvent ? dragOverlaySize(view, activeDragEvent, activeDayDrag) : {};
|
|
3816
|
+
const activeCalendarKey = calendars ? calendars.filter((c) => c.active !== false).map((c) => c.id).join("\0") : null;
|
|
3162
3817
|
const filteredEvents = useMemo4(() => {
|
|
3163
|
-
if (
|
|
3164
|
-
const activeCalendarIds =
|
|
3165
|
-
return expandedEvents.filter((e) =>
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3818
|
+
if (activeCalendarKey === null) return expandedEvents;
|
|
3819
|
+
const activeCalendarIds = new Set(activeCalendarKey.split("\0"));
|
|
3820
|
+
return expandedEvents.filter((e) => !e.calendarId || activeCalendarIds.has(String(e.calendarId)));
|
|
3821
|
+
}, [expandedEvents, activeCalendarKey]);
|
|
3822
|
+
const periodKey = view === "month" ? format16(currentDate, "yyyy-MM") : view === "week" ? format16(startOfWeek3(currentDate, { weekStartsOn: resolveWeekStartsOn(locale, 1) }), "yyyy-MM-dd") : format16(currentDate, "yyyy-MM-dd");
|
|
3823
|
+
const slotClickHandler = readOnly ? void 0 : handleTimeSlotClick;
|
|
3824
|
+
const allDaySlotClickHandler = readOnly ? void 0 : handleAllDaySlotClick;
|
|
3825
|
+
const contextMenuHandler = readOnly ? void 0 : openContextMenu;
|
|
3826
|
+
return /* @__PURE__ */ React20.createElement(
|
|
3171
3827
|
DndContext,
|
|
3172
3828
|
{
|
|
3173
3829
|
id,
|
|
3174
3830
|
sensors: dndSensors,
|
|
3175
3831
|
onDragStart: handleDragStart,
|
|
3176
3832
|
onDragEnd: onDragEndWrapper,
|
|
3177
|
-
modifiers
|
|
3833
|
+
modifiers,
|
|
3834
|
+
collisionDetection: dayAwareCollision
|
|
3178
3835
|
},
|
|
3179
|
-
/* @__PURE__ */
|
|
3836
|
+
/* @__PURE__ */ React20.createElement(
|
|
3180
3837
|
"div",
|
|
3181
3838
|
{
|
|
3182
3839
|
className: cn("flex flex-col h-full bg-background text-foreground relative", className),
|
|
3183
3840
|
style: getThemeStyles(theme)
|
|
3184
3841
|
},
|
|
3185
|
-
/* @__PURE__ */
|
|
3842
|
+
/* @__PURE__ */ React20.createElement(
|
|
3186
3843
|
CalendarHeader,
|
|
3187
3844
|
{
|
|
3188
3845
|
currentDate,
|
|
@@ -3201,7 +3858,7 @@ var Scheduler = ({
|
|
|
3201
3858
|
locale
|
|
3202
3859
|
}
|
|
3203
3860
|
),
|
|
3204
|
-
/* @__PURE__ */
|
|
3861
|
+
/* @__PURE__ */ React20.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React20.createElement(
|
|
3205
3862
|
motion4.div,
|
|
3206
3863
|
{
|
|
3207
3864
|
className: cn(
|
|
@@ -3217,7 +3874,7 @@ var Scheduler = ({
|
|
|
3217
3874
|
ease: [0.4, 0, 0.2, 1]
|
|
3218
3875
|
}
|
|
3219
3876
|
},
|
|
3220
|
-
/* @__PURE__ */
|
|
3877
|
+
/* @__PURE__ */ React20.createElement(
|
|
3221
3878
|
Sidebar,
|
|
3222
3879
|
{
|
|
3223
3880
|
currentDate,
|
|
@@ -3234,10 +3891,10 @@ var Scheduler = ({
|
|
|
3234
3891
|
locale
|
|
3235
3892
|
}
|
|
3236
3893
|
)
|
|
3237
|
-
), /* @__PURE__ */
|
|
3894
|
+
), /* @__PURE__ */ React20.createElement("div", { className: "flex-1 flex flex-col overflow-hidden relative" }, isLoading ? /* @__PURE__ */ React20.createElement("div", { className: "flex-1 overflow-auto p-0 md:p-4" }, /* @__PURE__ */ React20.createElement("div", { className: "h-full min-w-full" }, view === "month" && /* @__PURE__ */ React20.createElement(MonthViewSkeleton, null), view === "week" && /* @__PURE__ */ React20.createElement(WeekViewSkeleton, null), view === "day" && /* @__PURE__ */ React20.createElement(DayViewSkeleton, null), view === "agenda" && /* @__PURE__ */ React20.createElement(AgendaViewSkeleton, null), view === "resource" && /* @__PURE__ */ React20.createElement(WeekViewSkeleton, null))) : /* @__PURE__ */ React20.createElement("div", { ref: swipeRef, className: "flex-1 overflow-auto p-0 md:p-4 touch-pan-y" }, /* @__PURE__ */ React20.createElement("div", { className: "h-full min-w-full" }, /* @__PURE__ */ React20.createElement(AnimatePresence3, { mode: "wait", initial: false }, /* @__PURE__ */ React20.createElement(
|
|
3238
3895
|
motion4.div,
|
|
3239
3896
|
{
|
|
3240
|
-
key: `${view}-${
|
|
3897
|
+
key: `${view}-${periodKey}-${timezone || "local"}`,
|
|
3241
3898
|
initial: { opacity: 0, scale: 0.98, y: 15 },
|
|
3242
3899
|
animate: {
|
|
3243
3900
|
opacity: 1,
|
|
@@ -3259,7 +3916,7 @@ var Scheduler = ({
|
|
|
3259
3916
|
},
|
|
3260
3917
|
className: "h-full"
|
|
3261
3918
|
},
|
|
3262
|
-
view === "month" && /* @__PURE__ */
|
|
3919
|
+
view === "month" && /* @__PURE__ */ React20.createElement(
|
|
3263
3920
|
MonthView,
|
|
3264
3921
|
{
|
|
3265
3922
|
currentDate,
|
|
@@ -3267,36 +3924,48 @@ var Scheduler = ({
|
|
|
3267
3924
|
onEventClick: handleEventClickInternal,
|
|
3268
3925
|
onDateClick: handleDateClick,
|
|
3269
3926
|
timezone,
|
|
3270
|
-
locale
|
|
3927
|
+
locale,
|
|
3928
|
+
translations: t,
|
|
3929
|
+
onEventContextMenu: contextMenuHandler,
|
|
3930
|
+
onDayEventResize: handleDayEventResize,
|
|
3931
|
+
readonly: readOnly
|
|
3271
3932
|
}
|
|
3272
3933
|
),
|
|
3273
|
-
view === "week" && /* @__PURE__ */
|
|
3934
|
+
view === "week" && /* @__PURE__ */ React20.createElement(
|
|
3274
3935
|
WeekView,
|
|
3275
3936
|
{
|
|
3276
3937
|
currentDate,
|
|
3277
3938
|
events: filteredEvents,
|
|
3278
3939
|
onEventClick: handleEventClickInternal,
|
|
3279
|
-
onTimeSlotClick:
|
|
3940
|
+
onTimeSlotClick: slotClickHandler,
|
|
3280
3941
|
onEventResize: handleEventResize,
|
|
3281
3942
|
timezone,
|
|
3282
3943
|
locale,
|
|
3283
|
-
readonly: readOnly
|
|
3944
|
+
readonly: readOnly,
|
|
3945
|
+
onEventContextMenu: contextMenuHandler,
|
|
3946
|
+
onDayEventResize: handleDayEventResize,
|
|
3947
|
+
onAllDaySlotClick: allDaySlotClickHandler,
|
|
3948
|
+
translations: t
|
|
3284
3949
|
}
|
|
3285
3950
|
),
|
|
3286
|
-
view === "day" && /* @__PURE__ */
|
|
3951
|
+
view === "day" && /* @__PURE__ */ React20.createElement(
|
|
3287
3952
|
DayView,
|
|
3288
3953
|
{
|
|
3289
3954
|
currentDate,
|
|
3290
3955
|
events: filteredEvents,
|
|
3291
3956
|
onEventClick: handleEventClickInternal,
|
|
3292
|
-
onTimeSlotClick:
|
|
3957
|
+
onTimeSlotClick: slotClickHandler,
|
|
3293
3958
|
onEventResize: handleEventResize,
|
|
3294
3959
|
timezone,
|
|
3295
3960
|
locale,
|
|
3296
|
-
readonly: readOnly
|
|
3961
|
+
readonly: readOnly,
|
|
3962
|
+
translations: t,
|
|
3963
|
+
onEventContextMenu: contextMenuHandler,
|
|
3964
|
+
onDayEventResize: handleDayEventResize,
|
|
3965
|
+
onAllDaySlotClick: allDaySlotClickHandler
|
|
3297
3966
|
}
|
|
3298
3967
|
),
|
|
3299
|
-
view === "agenda" && /* @__PURE__ */
|
|
3968
|
+
view === "agenda" && /* @__PURE__ */ React20.createElement(
|
|
3300
3969
|
AgendaView,
|
|
3301
3970
|
{
|
|
3302
3971
|
currentDate,
|
|
@@ -3305,37 +3974,42 @@ var Scheduler = ({
|
|
|
3305
3974
|
onCreateEvent: handleCreateEvent,
|
|
3306
3975
|
locale,
|
|
3307
3976
|
translations: t,
|
|
3308
|
-
timezone
|
|
3977
|
+
timezone,
|
|
3978
|
+
onEventContextMenu: contextMenuHandler
|
|
3309
3979
|
}
|
|
3310
3980
|
),
|
|
3311
|
-
view === "resource" && resources && /* @__PURE__ */
|
|
3981
|
+
view === "resource" && resources && /* @__PURE__ */ React20.createElement(
|
|
3312
3982
|
ResourceView,
|
|
3313
3983
|
{
|
|
3314
3984
|
currentDate,
|
|
3315
3985
|
events: filteredEvents,
|
|
3316
3986
|
resources,
|
|
3317
3987
|
onEventClick: handleEventClickInternal,
|
|
3318
|
-
onTimeSlotClick:
|
|
3988
|
+
onTimeSlotClick: slotClickHandler,
|
|
3319
3989
|
locale,
|
|
3320
|
-
timezone
|
|
3990
|
+
timezone,
|
|
3991
|
+
translations: t,
|
|
3992
|
+
onEventContextMenu: contextMenuHandler
|
|
3321
3993
|
}
|
|
3322
3994
|
)
|
|
3323
|
-
)))), /* @__PURE__ */
|
|
3995
|
+
)))), !readOnly && /* @__PURE__ */ React20.createElement("div", { className: "md:hidden absolute bottom-6 right-6 z-50" }, /* @__PURE__ */ React20.createElement(
|
|
3324
3996
|
"button",
|
|
3325
3997
|
{
|
|
3326
3998
|
onClick: handleCreateEvent,
|
|
3999
|
+
"aria-label": t.createEvent,
|
|
3327
4000
|
className: "w-14 h-14 bg-blue-600 rounded-full shadow-lg flex items-center justify-center text-white active:scale-90 transition-transform"
|
|
3328
4001
|
},
|
|
3329
|
-
/* @__PURE__ */
|
|
4002
|
+
/* @__PURE__ */ React20.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React20.createElement("path", { d: "M5 12h14" }), /* @__PURE__ */ React20.createElement("path", { d: "M12 5v14" }))
|
|
3330
4003
|
)))),
|
|
3331
4004
|
renderEventForm ? renderEventForm({
|
|
3332
4005
|
isOpen: isModalOpen,
|
|
3333
4006
|
onClose: () => setIsModalOpen(false),
|
|
3334
4007
|
event: selectedEvent,
|
|
3335
4008
|
initialDate: modalInitialDate,
|
|
4009
|
+
initialAllDay: modalInitialAllDay,
|
|
3336
4010
|
onSave: handleModalSave,
|
|
3337
4011
|
onDelete: handleModalDelete
|
|
3338
|
-
}) : /* @__PURE__ */
|
|
4012
|
+
}) : /* @__PURE__ */ React20.createElement(
|
|
3339
4013
|
EventModal,
|
|
3340
4014
|
{
|
|
3341
4015
|
isOpen: isModalOpen,
|
|
@@ -3346,10 +4020,12 @@ var Scheduler = ({
|
|
|
3346
4020
|
onDelete: handleModalDelete,
|
|
3347
4021
|
calendars,
|
|
3348
4022
|
eventTypes,
|
|
3349
|
-
translations: t
|
|
4023
|
+
translations: t,
|
|
4024
|
+
locale,
|
|
4025
|
+
initialAllDay: modalInitialAllDay
|
|
3350
4026
|
}
|
|
3351
4027
|
),
|
|
3352
|
-
/* @__PURE__ */
|
|
4028
|
+
/* @__PURE__ */ React20.createElement(
|
|
3353
4029
|
EventContextMenu,
|
|
3354
4030
|
{
|
|
3355
4031
|
event: contextMenuEvent,
|
|
@@ -3374,7 +4050,7 @@ var Scheduler = ({
|
|
|
3374
4050
|
}
|
|
3375
4051
|
}
|
|
3376
4052
|
),
|
|
3377
|
-
/* @__PURE__ */
|
|
4053
|
+
/* @__PURE__ */ React20.createElement(DragOverlay, { dropAnimation: null }, activeDragEvent ? /* @__PURE__ */ React20.createElement(
|
|
3378
4054
|
"div",
|
|
3379
4055
|
{
|
|
3380
4056
|
className: cn(
|
|
@@ -3386,19 +4062,19 @@ var Scheduler = ({
|
|
|
3386
4062
|
backgroundColor: activeDragEvent.color ? `${activeDragEvent.color}e0` : void 0,
|
|
3387
4063
|
borderColor: activeDragEvent.color ? `${activeDragEvent.color}80` : void 0,
|
|
3388
4064
|
color: activeDragEvent.color ? "#fff" : void 0,
|
|
3389
|
-
width:
|
|
3390
|
-
height:
|
|
4065
|
+
width: dragSize.width,
|
|
4066
|
+
height: dragSize.height ? `${dragSize.height}px` : void 0,
|
|
3391
4067
|
boxShadow: `0 20px 40px -15px ${activeDragEvent.color || "var(--primary)"}40, 0 10px 20px -10px rgba(0,0,0,0.2)`,
|
|
3392
4068
|
transform: "rotate(-2deg) scale(1.02)"
|
|
3393
4069
|
}
|
|
3394
4070
|
},
|
|
3395
|
-
/* @__PURE__ */
|
|
4071
|
+
/* @__PURE__ */ React20.createElement("div", { className: "p-2.5 h-full flex flex-col" }, /* @__PURE__ */ React20.createElement(
|
|
3396
4072
|
"div",
|
|
3397
4073
|
{
|
|
3398
4074
|
className: "absolute left-0 top-0 bottom-0 w-1 rounded-l-lg",
|
|
3399
4075
|
style: { backgroundColor: activeDragEvent.color || "var(--primary)" }
|
|
3400
4076
|
}
|
|
3401
|
-
), /* @__PURE__ */
|
|
4077
|
+
), /* @__PURE__ */ React20.createElement("div", { className: "pl-2" }, /* @__PURE__ */ React20.createElement("div", { className: "font-semibold truncate text-sm" }, activeDragEvent.title), (view === "week" || view === "day") && dragSize.height !== void 0 && dragSize.height > 40 && /* @__PURE__ */ React20.createElement("div", { className: "text-xs opacity-80 mt-0.5 flex items-center gap-1" }, /* @__PURE__ */ React20.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ React20.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React20.createElement("path", { d: "M12 6v6l4 2" })), format16(toDisplay(activeDragEvent.start, timezone), overlayTimeFormat, { locale }), " - ", format16(toDisplay(activeDragEvent.end, timezone), overlayTimeFormat, { locale }))), /* @__PURE__ */ React20.createElement("div", { className: "absolute bottom-1.5 right-1.5 opacity-60" }, /* @__PURE__ */ React20.createElement("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React20.createElement("circle", { cx: "9", cy: "5", r: "1.5" }), /* @__PURE__ */ React20.createElement("circle", { cx: "15", cy: "5", r: "1.5" }), /* @__PURE__ */ React20.createElement("circle", { cx: "9", cy: "12", r: "1.5" }), /* @__PURE__ */ React20.createElement("circle", { cx: "15", cy: "12", r: "1.5" }), /* @__PURE__ */ React20.createElement("circle", { cx: "9", cy: "19", r: "1.5" }), /* @__PURE__ */ React20.createElement("circle", { cx: "15", cy: "19", r: "1.5" }))))
|
|
3402
4078
|
) : null)
|
|
3403
4079
|
)
|
|
3404
4080
|
);
|