calendarkit-pro 1.3.0 → 1.3.1
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 +4 -0
- package/dist/index.d.mts +38 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +382 -210
- package/dist/index.mjs +391 -219
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -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,45 @@ 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"
|
|
344
390
|
};
|
|
345
391
|
var fr = {
|
|
346
392
|
today: "Aujourd'hui",
|
|
@@ -409,7 +455,45 @@ var fr = {
|
|
|
409
455
|
allCaughtUp: "Tout est \xE0 jour !",
|
|
410
456
|
noEventsScheduled: "Aucun \xE9v\xE9nement pr\xE9vu",
|
|
411
457
|
noUpcoming: "Votre planning est libre",
|
|
412
|
-
noUpcomingHint: "Aucun \xE9v\xE9nement \xE0 venir. Cr\xE9ez un nouvel \xE9v\xE9nement pour commencer \xE0 planifier."
|
|
458
|
+
noUpcomingHint: "Aucun \xE9v\xE9nement \xE0 venir. Cr\xE9ez un nouvel \xE9v\xE9nement pour commencer \xE0 planifier.",
|
|
459
|
+
newEvent: "Nouvel \xE9v\xE9nement",
|
|
460
|
+
saveChanges: "Enregistrer",
|
|
461
|
+
close: "Fermer",
|
|
462
|
+
noTitle: "(Sans titre)",
|
|
463
|
+
openInMaps: "Ouvrir dans Maps",
|
|
464
|
+
notesLabel: "Notes",
|
|
465
|
+
addNotes: "Ajouter une description ou des notes\u2026",
|
|
466
|
+
attachments: "Pi\xE8ces jointes",
|
|
467
|
+
reminders: "Rappels",
|
|
468
|
+
add: "Ajouter",
|
|
469
|
+
calendar: "Calendrier",
|
|
470
|
+
select: "Choisir",
|
|
471
|
+
addLocation: "Ajouter un lieu",
|
|
472
|
+
guestSingular: "Invit\xE9",
|
|
473
|
+
addGuestPlaceholder: "Ajoutez l'e-mail d'un invit\xE9 puis Entr\xE9e",
|
|
474
|
+
invalidEmail: "Saisissez une adresse e-mail valide",
|
|
475
|
+
removeGuest: "Retirer {email}",
|
|
476
|
+
reminderAtTime: "Au moment de l'\xE9v\xE9nement",
|
|
477
|
+
reminderMinutes: "{n} minutes avant",
|
|
478
|
+
reminderHour: "1 heure avant",
|
|
479
|
+
reminderHours: "{n} heures avant",
|
|
480
|
+
reminderDay: "1 jour avant",
|
|
481
|
+
reminderDays: "{n} jours avant",
|
|
482
|
+
reminderWeek: "1 semaine avant",
|
|
483
|
+
removeReminder: "Supprimer le rappel",
|
|
484
|
+
durationMinutes: "{n} min",
|
|
485
|
+
durationHours: "{n} h",
|
|
486
|
+
durationHoursMinutes: "{h} h {m} min",
|
|
487
|
+
moreEvents: "+{n} de plus",
|
|
488
|
+
idLabel: "ID : {id}",
|
|
489
|
+
previous: "Pr\xE9c\xE9dent",
|
|
490
|
+
next: "Suivant",
|
|
491
|
+
previousMonth: "Mois pr\xE9c\xE9dent",
|
|
492
|
+
nextMonth: "Mois suivant",
|
|
493
|
+
toggleSidebar: "Afficher ou masquer la barre lat\xE9rale",
|
|
494
|
+
toggleTheme: "Basculer le th\xE8me sombre",
|
|
495
|
+
switchLanguage: "Changer de langue",
|
|
496
|
+
eventColor: "Couleur de l'\xE9v\xE9nement"
|
|
413
497
|
};
|
|
414
498
|
|
|
415
499
|
// src/core/format.ts
|
|
@@ -452,7 +536,18 @@ function timeZoneAbbreviation(date, timeZone) {
|
|
|
452
536
|
}
|
|
453
537
|
}
|
|
454
538
|
function resolveTranslations(language, overrides) {
|
|
455
|
-
|
|
539
|
+
const defined = Object.fromEntries(Object.entries(overrides ?? {}).filter(([, value]) => value !== void 0));
|
|
540
|
+
return { ...language === "fr" ? fr : en, ...defined };
|
|
541
|
+
}
|
|
542
|
+
function interpolate(template, values) {
|
|
543
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => key in values ? String(values[key]) : match);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// src/core/color.ts
|
|
547
|
+
var SAFE_COLOR = /^[#\w\s%.,/()+-]+$/;
|
|
548
|
+
var FORBIDDEN = /url\(|expression\(/i;
|
|
549
|
+
function safeColor(value, fallback) {
|
|
550
|
+
return value && SAFE_COLOR.test(value.trim()) && !FORBIDDEN.test(value) ? value.trim() : fallback;
|
|
456
551
|
}
|
|
457
552
|
|
|
458
553
|
// src/components/Sidebar.tsx
|
|
@@ -480,12 +575,6 @@ var Sidebar = ({
|
|
|
480
575
|
const timer = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
481
576
|
return () => clearInterval(timer);
|
|
482
577
|
}, []);
|
|
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
578
|
const getAcronym = (tz) => !tz || !now ? "LOC" : timeZoneAbbreviation(now, tz);
|
|
490
579
|
const timezones = [
|
|
491
580
|
{ value: "", label: translations?.localTime || "Local Time", acronym: "LOC" },
|
|
@@ -535,7 +624,16 @@ var Sidebar = ({
|
|
|
535
624
|
},
|
|
536
625
|
/* @__PURE__ */ React4.createElement(Plus, { className: "w-5 h-5" }),
|
|
537
626
|
/* @__PURE__ */ React4.createElement("span", { className: "text-sm" }, translations?.create || "Create")
|
|
538
|
-
)), /* @__PURE__ */ React4.createElement(
|
|
627
|
+
)), /* @__PURE__ */ React4.createElement(
|
|
628
|
+
MiniCalendar,
|
|
629
|
+
{
|
|
630
|
+
currentDate,
|
|
631
|
+
onDateChange,
|
|
632
|
+
onViewChange,
|
|
633
|
+
locale,
|
|
634
|
+
labels: { previousMonth: translations?.previousMonth, nextMonth: translations?.nextMonth }
|
|
635
|
+
}
|
|
636
|
+
), /* @__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
637
|
"div",
|
|
540
638
|
{
|
|
541
639
|
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 +641,40 @@ var Sidebar = ({
|
|
|
543
641
|
},
|
|
544
642
|
/* @__PURE__ */ React4.createElement("span", { className: "text-sm font-semibold text-foreground" }, translations?.calendars || "Calendars"),
|
|
545
643
|
/* @__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" },
|
|
644
|
+
), calendarsOpen && /* @__PURE__ */ React4.createElement("div", { className: "space-y-1" }, calendars.map((cal) => /* @__PURE__ */ React4.createElement(
|
|
547
645
|
"div",
|
|
548
646
|
{
|
|
549
647
|
key: cal.id,
|
|
550
648
|
className: "flex items-center gap-3 py-2 px-2 hover:bg-accent/60 rounded-xl cursor-pointer group transition-all duration-200",
|
|
551
649
|
onClick: () => onCalendarToggle?.(cal.id, !(cal.active ?? true))
|
|
552
650
|
},
|
|
553
|
-
/* @__PURE__ */ React4.createElement(
|
|
554
|
-
"
|
|
651
|
+
/* @__PURE__ */ React4.createElement(
|
|
652
|
+
"div",
|
|
555
653
|
{
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
`)),
|
|
654
|
+
className: "relative flex items-center justify-center",
|
|
655
|
+
style: { "--cal-color": safeColor(cal.color, "hsl(var(--primary))") }
|
|
656
|
+
},
|
|
657
|
+
/* @__PURE__ */ React4.createElement(
|
|
658
|
+
"input",
|
|
659
|
+
{
|
|
660
|
+
type: "checkbox",
|
|
661
|
+
checked: cal.active ?? true,
|
|
662
|
+
onChange: (e) => {
|
|
663
|
+
e.stopPropagation();
|
|
664
|
+
onCalendarToggle?.(cal.id, e.target.checked);
|
|
665
|
+
},
|
|
666
|
+
"aria-label": cal.label,
|
|
667
|
+
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"
|
|
668
|
+
}
|
|
669
|
+
),
|
|
670
|
+
/* @__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" })))
|
|
671
|
+
),
|
|
575
672
|
/* @__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
673
|
/* @__PURE__ */ React4.createElement(
|
|
577
674
|
"div",
|
|
578
675
|
{
|
|
579
676
|
className: "w-2 h-2 rounded-full opacity-60 group-hover:opacity-100 transition-opacity",
|
|
580
|
-
style: { backgroundColor: cal.color }
|
|
677
|
+
style: { backgroundColor: safeColor(cal.color, "hsl(var(--primary))") }
|
|
581
678
|
}
|
|
582
679
|
)
|
|
583
680
|
))))), /* @__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(
|
|
@@ -864,7 +961,7 @@ var DroppableCell = React6.memo(
|
|
|
864
961
|
);
|
|
865
962
|
|
|
866
963
|
// src/views/MonthView.tsx
|
|
867
|
-
var EventItem = React7.memo(({ event, onEventClick }) => /* @__PURE__ */ React7.createElement(DraggableEvent, { event }, /* @__PURE__ */ React7.createElement(
|
|
964
|
+
var EventItem = React7.memo(({ event, onEventClick, onEventContextMenu }) => /* @__PURE__ */ React7.createElement(DraggableEvent, { event }, /* @__PURE__ */ React7.createElement(
|
|
868
965
|
"div",
|
|
869
966
|
{
|
|
870
967
|
className: cn(
|
|
@@ -880,7 +977,8 @@ var EventItem = React7.memo(({ event, onEventClick }) => /* @__PURE__ */ React7.
|
|
|
880
977
|
onClick: (e) => {
|
|
881
978
|
e.stopPropagation();
|
|
882
979
|
onEventClick?.(event);
|
|
883
|
-
}
|
|
980
|
+
},
|
|
981
|
+
onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0
|
|
884
982
|
},
|
|
885
983
|
/* @__PURE__ */ React7.createElement("span", { className: "font-medium" }, event.title)
|
|
886
984
|
)));
|
|
@@ -891,7 +989,9 @@ var MonthView = ({
|
|
|
891
989
|
onEventClick,
|
|
892
990
|
onDateClick,
|
|
893
991
|
timezone,
|
|
894
|
-
locale
|
|
992
|
+
locale,
|
|
993
|
+
translations,
|
|
994
|
+
onEventContextMenu
|
|
895
995
|
}) => {
|
|
896
996
|
const weekStartsOn = resolveWeekStartsOn(locale, 1);
|
|
897
997
|
const days = useMemo(() => getMonthGrid(currentDate, weekStartsOn), [currentDate, weekStartsOn]);
|
|
@@ -927,7 +1027,19 @@ var MonthView = ({
|
|
|
927
1027
|
"text-sm font-semibold w-7 h-7 flex items-center justify-center rounded-full transition-all duration-200",
|
|
928
1028
|
isSameDay3(day, today) ? "bg-primary text-primary-foreground shadow-md shadow-primary/30" : "group-hover:bg-accent"
|
|
929
1029
|
) }, 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 &&
|
|
1030
|
+
/* @__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, onEventContextMenu })), dayEvents.length > 4 && // U7: "+N more" opens the day instead of doing nothing.
|
|
1031
|
+
/* @__PURE__ */ React7.createElement(
|
|
1032
|
+
"button",
|
|
1033
|
+
{
|
|
1034
|
+
type: "button",
|
|
1035
|
+
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",
|
|
1036
|
+
onClick: (e) => {
|
|
1037
|
+
e.stopPropagation();
|
|
1038
|
+
onDateClick?.(day);
|
|
1039
|
+
}
|
|
1040
|
+
},
|
|
1041
|
+
interpolate(translations?.moreEvents || "+{n} more", { n: dayEvents.length - 4 })
|
|
1042
|
+
))
|
|
931
1043
|
);
|
|
932
1044
|
}))));
|
|
933
1045
|
};
|
|
@@ -1110,7 +1222,8 @@ var WeekViewImpl = ({
|
|
|
1110
1222
|
onEventResize,
|
|
1111
1223
|
timezone,
|
|
1112
1224
|
locale,
|
|
1113
|
-
readonly
|
|
1225
|
+
readonly,
|
|
1226
|
+
onEventContextMenu
|
|
1114
1227
|
}) => {
|
|
1115
1228
|
const weekDays = React9.useMemo(
|
|
1116
1229
|
() => getWeekDays(currentDate, resolveWeekStartsOn(locale, 1)),
|
|
@@ -1260,6 +1373,7 @@ var WeekViewImpl = ({
|
|
|
1260
1373
|
e.stopPropagation();
|
|
1261
1374
|
onEventClick?.(event);
|
|
1262
1375
|
},
|
|
1376
|
+
onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
|
|
1263
1377
|
title: columns > 1 ? `${event.title} (${column + 1}/${columns})` : void 0
|
|
1264
1378
|
},
|
|
1265
1379
|
/* @__PURE__ */ React9.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ React9.createElement("div", { className: cn(
|
|
@@ -1304,7 +1418,9 @@ var DayViewImpl = ({
|
|
|
1304
1418
|
onEventResize,
|
|
1305
1419
|
timezone,
|
|
1306
1420
|
locale,
|
|
1307
|
-
readonly
|
|
1421
|
+
readonly,
|
|
1422
|
+
onEventContextMenu,
|
|
1423
|
+
translations
|
|
1308
1424
|
}) => {
|
|
1309
1425
|
const visibleRange = React10.useMemo(() => {
|
|
1310
1426
|
const start = startOfDay3(currentDate);
|
|
@@ -1328,7 +1444,7 @@ var DayViewImpl = ({
|
|
|
1328
1444
|
const zonedNow = toDisplay(now, timezone);
|
|
1329
1445
|
const nowTop = minutesSinceDisplayMidnight(now, timezone) / 60 * HOUR_HEIGHT2;
|
|
1330
1446
|
const formats = timeFormats(locale);
|
|
1331
|
-
return /* @__PURE__ */ React10.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden shadow-sm" }, /* @__PURE__ */ React10.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__ */ React10.createElement("div", { className: "flex items-center justify-center gap-3" }, /* @__PURE__ */ React10.createElement("h2", { className: "text-xl font-semibold capitalize text-foreground" }, format9(currentDate, "EEEE, MMMM d, yyyy", { locale })), isToday2 && /* @__PURE__ */ React10.createElement("span", { className: "text-xs font-semibold bg-primary text-primary-foreground px-3 py-1 rounded-full shadow-md shadow-primary/20" }, "Today"))), /* @__PURE__ */ React10.createElement("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto relative" }, /* @__PURE__ */ React10.createElement("div", { className: "flex relative", style: { height: HOURS2.length * HOUR_HEIGHT2 } }, /* @__PURE__ */ React10.createElement("div", { className: "w-20 bg-muted/5 border-r-[0.5px] border-border/30 relative" }, HOURS2.map((hour) => /* @__PURE__ */ React10.createElement(
|
|
1447
|
+
return /* @__PURE__ */ React10.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden shadow-sm" }, /* @__PURE__ */ React10.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__ */ React10.createElement("div", { className: "flex items-center justify-center gap-3" }, /* @__PURE__ */ React10.createElement("h2", { className: "text-xl font-semibold capitalize text-foreground" }, format9(currentDate, "EEEE, MMMM d, yyyy", { locale })), isToday2 && /* @__PURE__ */ React10.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__ */ React10.createElement("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto relative" }, /* @__PURE__ */ React10.createElement("div", { className: "flex relative", style: { height: HOURS2.length * HOUR_HEIGHT2 } }, /* @__PURE__ */ React10.createElement("div", { className: "w-20 bg-muted/5 border-r-[0.5px] border-border/30 relative" }, HOURS2.map((hour) => /* @__PURE__ */ React10.createElement(
|
|
1332
1448
|
"div",
|
|
1333
1449
|
{
|
|
1334
1450
|
key: hour,
|
|
@@ -1425,6 +1541,7 @@ var DayViewImpl = ({
|
|
|
1425
1541
|
e.stopPropagation();
|
|
1426
1542
|
onEventClick?.(event);
|
|
1427
1543
|
},
|
|
1544
|
+
onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
|
|
1428
1545
|
title: columns > 1 ? `${event.title} (${column + 1}/${columns})` : void 0
|
|
1429
1546
|
},
|
|
1430
1547
|
/* @__PURE__ */ React10.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ React10.createElement("div", { className: cn(
|
|
@@ -1487,7 +1604,8 @@ var AgendaView = ({
|
|
|
1487
1604
|
onCreateEvent,
|
|
1488
1605
|
locale,
|
|
1489
1606
|
translations,
|
|
1490
|
-
timezone
|
|
1607
|
+
timezone,
|
|
1608
|
+
onEventContextMenu
|
|
1491
1609
|
}) => {
|
|
1492
1610
|
const is24h = uses24HourClock(locale);
|
|
1493
1611
|
const { time: timePattern, compact: compactTimePattern } = timeFormats(locale);
|
|
@@ -1544,6 +1662,7 @@ var AgendaView = ({
|
|
|
1544
1662
|
{
|
|
1545
1663
|
key: event.id,
|
|
1546
1664
|
onClick: () => onEventClick?.(event),
|
|
1665
|
+
onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
|
|
1547
1666
|
className: cn(
|
|
1548
1667
|
"group relative flex gap-4 p-4 rounded-2xl border border-border/40",
|
|
1549
1668
|
"hover:border-primary/40 hover:shadow-lg hover:shadow-primary/5",
|
|
@@ -1584,7 +1703,9 @@ var ResourceView = ({
|
|
|
1584
1703
|
onEventClick,
|
|
1585
1704
|
onTimeSlotClick,
|
|
1586
1705
|
locale,
|
|
1587
|
-
timezone
|
|
1706
|
+
timezone,
|
|
1707
|
+
translations,
|
|
1708
|
+
onEventContextMenu
|
|
1588
1709
|
}) => {
|
|
1589
1710
|
const containerRef = useRef2(null);
|
|
1590
1711
|
const hours = Array.from({ length: 24 }, (_, i) => i);
|
|
@@ -1604,7 +1725,7 @@ var ResourceView = ({
|
|
|
1604
1725
|
// Min width for visibility
|
|
1605
1726
|
};
|
|
1606
1727
|
};
|
|
1607
|
-
return /* @__PURE__ */ React13.createElement("div", { className: "flex flex-col h-full bg-background overflow-hidden" }, /* @__PURE__ */ React13.createElement("div", { className: "flex border-b border-border bg-muted/20" }, /* @__PURE__ */ React13.createElement("div", { className: "w-48 shrink-0 border-r border-border p-4 font-semibold text-sm bg-background sticky left-0 z-20" }, "Resources"), /* @__PURE__ */ React13.createElement("div", { className: "flex overflow-hidden" }, /* @__PURE__ */ React13.createElement("div", { className: "flex relative", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ React13.createElement(
|
|
1728
|
+
return /* @__PURE__ */ React13.createElement("div", { className: "flex flex-col h-full bg-background overflow-hidden" }, /* @__PURE__ */ React13.createElement("div", { className: "flex border-b border-border bg-muted/20" }, /* @__PURE__ */ React13.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__ */ React13.createElement("div", { className: "flex overflow-hidden" }, /* @__PURE__ */ React13.createElement("div", { className: "flex relative", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ React13.createElement(
|
|
1608
1729
|
"div",
|
|
1609
1730
|
{
|
|
1610
1731
|
key: hour,
|
|
@@ -1616,7 +1737,7 @@ var ResourceView = ({
|
|
|
1616
1737
|
const resourceEvents = events.filter(
|
|
1617
1738
|
(e) => e.resourceId === resource.id && isSameDisplayDay(e.start, currentDate, timezone)
|
|
1618
1739
|
);
|
|
1619
|
-
return /* @__PURE__ */ React13.createElement("div", { key: resource.id, className: "flex border-b border-border min-h-[100px]" }, /* @__PURE__ */ React13.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__ */ React13.createElement("img", { src: resource.avatar, alt: resource.label, className: "w-8 h-8 rounded-full object-cover" }) : /* @__PURE__ */ React13.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__ */ React13.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React13.createElement("span", { className: "text-sm font-medium" }, resource.label), /* @__PURE__ */ React13.createElement("span", { className: "text-xs text-muted-foreground" }, "ID: ", resource.id))), /* @__PURE__ */ React13.createElement("div", { className: "relative flex", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ React13.createElement(
|
|
1740
|
+
return /* @__PURE__ */ React13.createElement("div", { key: resource.id, className: "flex border-b border-border min-h-[100px]" }, /* @__PURE__ */ React13.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__ */ React13.createElement("img", { src: resource.avatar, alt: resource.label, className: "w-8 h-8 rounded-full object-cover" }) : /* @__PURE__ */ React13.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__ */ React13.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React13.createElement("span", { className: "text-sm font-medium" }, resource.label), /* @__PURE__ */ React13.createElement("span", { className: "text-xs text-muted-foreground" }, interpolate(translations?.idLabel || "ID: {id}", { id: resource.id })))), /* @__PURE__ */ React13.createElement("div", { className: "relative flex", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ React13.createElement(
|
|
1620
1741
|
"div",
|
|
1621
1742
|
{
|
|
1622
1743
|
key: hour,
|
|
@@ -1648,6 +1769,7 @@ var ResourceView = ({
|
|
|
1648
1769
|
e.stopPropagation();
|
|
1649
1770
|
onEventClick?.(event);
|
|
1650
1771
|
},
|
|
1772
|
+
onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
|
|
1651
1773
|
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
1774
|
style: {
|
|
1653
1775
|
...getEventStyle(event),
|
|
@@ -1662,7 +1784,7 @@ var ResourceView = ({
|
|
|
1662
1784
|
};
|
|
1663
1785
|
|
|
1664
1786
|
// src/components/EventModal.tsx
|
|
1665
|
-
import React15, { useState as useState3, useEffect as useEffect3 } from "react";
|
|
1787
|
+
import React15, { useState as useState3, useEffect as useEffect3, useInsertionEffect, useRef as useRef4 } from "react";
|
|
1666
1788
|
|
|
1667
1789
|
// src/components/ui/Modal.tsx
|
|
1668
1790
|
import React14, { useEffect as useEffect2, useRef as useRef3 } from "react";
|
|
@@ -1673,7 +1795,8 @@ var Modal = ({
|
|
|
1673
1795
|
title,
|
|
1674
1796
|
children,
|
|
1675
1797
|
className,
|
|
1676
|
-
hideHeader = false
|
|
1798
|
+
hideHeader = false,
|
|
1799
|
+
closeLabel = "Close"
|
|
1677
1800
|
}) => {
|
|
1678
1801
|
const overlayRef = useRef3(null);
|
|
1679
1802
|
useEffect2(() => {
|
|
@@ -1714,7 +1837,7 @@ var Modal = ({
|
|
|
1714
1837
|
className: "h-9 w-9 p-0 rounded-xl hover:bg-accent/80 transition-all duration-200"
|
|
1715
1838
|
},
|
|
1716
1839
|
/* @__PURE__ */ React14.createElement(X, { className: "h-4 w-4" }),
|
|
1717
|
-
/* @__PURE__ */ React14.createElement("span", { className: "sr-only" },
|
|
1840
|
+
/* @__PURE__ */ React14.createElement("span", { className: "sr-only" }, closeLabel)
|
|
1718
1841
|
)),
|
|
1719
1842
|
/* @__PURE__ */ React14.createElement("div", { className: cn("overflow-y-auto flex-1", !hideHeader && "p-6") }, children)
|
|
1720
1843
|
));
|
|
@@ -1744,18 +1867,7 @@ import {
|
|
|
1744
1867
|
Tag,
|
|
1745
1868
|
ExternalLink
|
|
1746
1869
|
} 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
|
-
];
|
|
1870
|
+
var REMINDER_OPTIONS = [0, 5, 10, 15, 30, 60, 120, 1440, 2880, 10080];
|
|
1759
1871
|
var COLOR_PALETTE = [
|
|
1760
1872
|
"#3b82f6",
|
|
1761
1873
|
// Blue
|
|
@@ -1778,6 +1890,30 @@ var COLOR_PALETTE = [
|
|
|
1778
1890
|
"#6366f1"
|
|
1779
1891
|
// Indigo
|
|
1780
1892
|
];
|
|
1893
|
+
var EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1894
|
+
var mergeGuests = (current, added) => {
|
|
1895
|
+
const seen = new Set(current.map((email) => email.toLowerCase()));
|
|
1896
|
+
const merged = [...current];
|
|
1897
|
+
for (const email of added) {
|
|
1898
|
+
if (!seen.has(email.toLowerCase())) {
|
|
1899
|
+
seen.add(email.toLowerCase());
|
|
1900
|
+
merged.push(email);
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
return merged;
|
|
1904
|
+
};
|
|
1905
|
+
var reminderLabel = (minutes, t) => {
|
|
1906
|
+
if (minutes === 0) return t.reminderAtTime;
|
|
1907
|
+
if (minutes === 10080) return t.reminderWeek;
|
|
1908
|
+
if (minutes === 1440) return t.reminderDay;
|
|
1909
|
+
if (minutes % 1440 === 0) return interpolate(t.reminderDays, { n: minutes / 1440 });
|
|
1910
|
+
if (minutes === 60) return t.reminderHour;
|
|
1911
|
+
if (minutes % 60 === 0) return interpolate(t.reminderHours, { n: minutes / 60 });
|
|
1912
|
+
return interpolate(t.reminderMinutes, { n: minutes });
|
|
1913
|
+
};
|
|
1914
|
+
var avatarHue = (email) => [...email].reduce((hash, char) => (hash * 31 + char.charCodeAt(0)) % 360, 7);
|
|
1915
|
+
var mapsUrl = (location) => `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(location)}`;
|
|
1916
|
+
var isSafeUrl = (url) => /^(https?:|mailto:|blob:|\/|\.\/|\.\.\/|[^:]*$)/i.test(url.trim());
|
|
1781
1917
|
var EventModal = ({
|
|
1782
1918
|
isOpen,
|
|
1783
1919
|
onClose,
|
|
@@ -1785,9 +1921,15 @@ var EventModal = ({
|
|
|
1785
1921
|
initialDate,
|
|
1786
1922
|
onSave,
|
|
1787
1923
|
onDelete,
|
|
1788
|
-
calendars
|
|
1924
|
+
calendars,
|
|
1925
|
+
translations: t,
|
|
1926
|
+
locale
|
|
1789
1927
|
}) => {
|
|
1790
1928
|
const [mode, setMode] = useState3("create");
|
|
1929
|
+
const translationsRef = useRef4(t);
|
|
1930
|
+
useInsertionEffect(() => {
|
|
1931
|
+
translationsRef.current = t;
|
|
1932
|
+
});
|
|
1791
1933
|
const [formData, setFormData] = useState3({
|
|
1792
1934
|
title: "",
|
|
1793
1935
|
description: "",
|
|
@@ -1800,22 +1942,18 @@ var EventModal = ({
|
|
|
1800
1942
|
type: void 0,
|
|
1801
1943
|
recurrence: void 0,
|
|
1802
1944
|
attachments: [],
|
|
1803
|
-
reminders: [
|
|
1945
|
+
reminders: []
|
|
1804
1946
|
});
|
|
1805
1947
|
const [isCalendarDropdownOpen, setIsCalendarDropdownOpen] = useState3(false);
|
|
1806
1948
|
const [isColorPickerOpen, setIsColorPickerOpen] = useState3(false);
|
|
1807
1949
|
const [isReminderDropdownOpen, setIsReminderDropdownOpen] = useState3(false);
|
|
1808
|
-
const [
|
|
1809
|
-
const
|
|
1810
|
-
"alice@example.com",
|
|
1811
|
-
"bob@example.com",
|
|
1812
|
-
"charlie@example.com",
|
|
1813
|
-
"diana@example.com",
|
|
1814
|
-
"evan@example.com"
|
|
1815
|
-
];
|
|
1816
|
-
const [selectedGuests, setSelectedGuests] = useState3([]);
|
|
1950
|
+
const [guestInput, setGuestInput] = useState3("");
|
|
1951
|
+
const [guestError, setGuestError] = useState3(false);
|
|
1817
1952
|
useEffect3(() => {
|
|
1953
|
+
const defaultReminders = () => [{ id: "1", type: "notification", time: 30, label: reminderLabel(30, translationsRef.current) }];
|
|
1818
1954
|
if (isOpen) {
|
|
1955
|
+
setGuestInput("");
|
|
1956
|
+
setGuestError(false);
|
|
1819
1957
|
if (event) {
|
|
1820
1958
|
setMode("view");
|
|
1821
1959
|
setFormData({
|
|
@@ -1823,9 +1961,9 @@ var EventModal = ({
|
|
|
1823
1961
|
start: new Date(event.start),
|
|
1824
1962
|
end: new Date(event.end),
|
|
1825
1963
|
attachments: event.attachments || [],
|
|
1826
|
-
reminders: event.reminders ||
|
|
1964
|
+
reminders: event.reminders || defaultReminders(),
|
|
1965
|
+
guests: event.guests || []
|
|
1827
1966
|
});
|
|
1828
|
-
setSelectedGuests(event.guests || []);
|
|
1829
1967
|
} else {
|
|
1830
1968
|
setMode("create");
|
|
1831
1969
|
const start = initialDate || /* @__PURE__ */ new Date();
|
|
@@ -1841,21 +1979,34 @@ var EventModal = ({
|
|
|
1841
1979
|
color: "#3b82f6",
|
|
1842
1980
|
calendarId: calendars?.[0]?.id,
|
|
1843
1981
|
attachments: [],
|
|
1844
|
-
reminders:
|
|
1982
|
+
reminders: defaultReminders(),
|
|
1983
|
+
guests: []
|
|
1845
1984
|
});
|
|
1846
|
-
setSelectedGuests([]);
|
|
1847
1985
|
}
|
|
1848
1986
|
}
|
|
1849
1987
|
}, [isOpen, event, initialDate, calendars]);
|
|
1850
|
-
const
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1988
|
+
const guests = formData.guests || [];
|
|
1989
|
+
const addGuests = (raw) => {
|
|
1990
|
+
const entries = raw.split(/[\s,;]+/).filter(Boolean);
|
|
1991
|
+
const valid = entries.filter((entry) => EMAIL.test(entry));
|
|
1992
|
+
const invalid = entries.filter((entry) => !EMAIL.test(entry));
|
|
1993
|
+
if (valid.length > 0) {
|
|
1994
|
+
setFormData((prev) => ({ ...prev, guests: mergeGuests(prev.guests || [], valid) }));
|
|
1995
|
+
}
|
|
1996
|
+
setGuestInput(invalid.join(", "));
|
|
1997
|
+
setGuestError(invalid.length > 0);
|
|
1998
|
+
return invalid.length === 0;
|
|
1999
|
+
};
|
|
2000
|
+
const removeGuest = (email) => {
|
|
2001
|
+
setFormData((prev) => ({ ...prev, guests: (prev.guests || []).filter((g) => g !== email) }));
|
|
1856
2002
|
};
|
|
1857
2003
|
const handleSubmit = (e) => {
|
|
1858
2004
|
e.preventDefault();
|
|
2005
|
+
const pending = guestInput.split(/[\s,;]+/).filter(Boolean);
|
|
2006
|
+
if (pending.some((entry) => !EMAIL.test(entry))) {
|
|
2007
|
+
addGuests(guestInput);
|
|
2008
|
+
return;
|
|
2009
|
+
}
|
|
1859
2010
|
let eventColor = formData.color;
|
|
1860
2011
|
if (formData.calendarId && calendars) {
|
|
1861
2012
|
const selectedCal = calendars.find((c) => c.id === formData.calendarId);
|
|
@@ -1863,8 +2014,10 @@ var EventModal = ({
|
|
|
1863
2014
|
eventColor = selectedCal.color;
|
|
1864
2015
|
}
|
|
1865
2016
|
}
|
|
2017
|
+
const finalGuests = mergeGuests(guests, pending);
|
|
1866
2018
|
onSave({
|
|
1867
2019
|
...formData,
|
|
2020
|
+
guests: finalGuests,
|
|
1868
2021
|
color: eventColor,
|
|
1869
2022
|
id: event?.id
|
|
1870
2023
|
});
|
|
@@ -1898,12 +2051,12 @@ var EventModal = ({
|
|
|
1898
2051
|
}
|
|
1899
2052
|
}
|
|
1900
2053
|
};
|
|
1901
|
-
const addReminder = (minutes
|
|
2054
|
+
const addReminder = (minutes) => {
|
|
1902
2055
|
const newReminder = {
|
|
1903
|
-
id: Math.random().toString(36).
|
|
2056
|
+
id: Math.random().toString(36).slice(2, 11),
|
|
1904
2057
|
type: "notification",
|
|
1905
2058
|
time: minutes,
|
|
1906
|
-
label
|
|
2059
|
+
label: reminderLabel(minutes, t)
|
|
1907
2060
|
};
|
|
1908
2061
|
setFormData((prev) => ({
|
|
1909
2062
|
...prev,
|
|
@@ -1917,23 +2070,20 @@ var EventModal = ({
|
|
|
1917
2070
|
reminders: prev.reminders?.filter((r) => r.id !== id)
|
|
1918
2071
|
}));
|
|
1919
2072
|
};
|
|
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
2073
|
const getDurationText = () => {
|
|
1930
2074
|
if (!formData.start || !formData.end) return "";
|
|
1931
2075
|
const mins = differenceInMinutes5(formData.end, formData.start);
|
|
1932
|
-
if (mins < 60) return
|
|
2076
|
+
if (mins < 60) return interpolate(t.durationMinutes, { n: mins });
|
|
1933
2077
|
const hours = Math.floor(mins / 60);
|
|
1934
2078
|
const remainingMins = mins % 60;
|
|
1935
|
-
if (remainingMins === 0) return
|
|
1936
|
-
return
|
|
2079
|
+
if (remainingMins === 0) return interpolate(t.durationHours, { n: hours });
|
|
2080
|
+
return interpolate(t.durationHoursMinutes, { h: hours, m: remainingMins });
|
|
2081
|
+
};
|
|
2082
|
+
const { time: timeFormat } = timeFormats(locale);
|
|
2083
|
+
const renderAttachment = (att) => {
|
|
2084
|
+
const content = /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "p-2 bg-primary/10 rounded-lg" }, /* @__PURE__ */ React15.createElement(File, { className: "w-4 h-4 text-primary" })), /* @__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)), att.url && /* @__PURE__ */ React15.createElement(Download, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" }));
|
|
2085
|
+
const className = "flex items-center gap-3 p-3 rounded-xl border border-border/30 bg-muted/20 transition-all group";
|
|
2086
|
+
return att.url && isSafeUrl(att.url) ? /* @__PURE__ */ React15.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__ */ React15.createElement("div", { key: att.id, className }, content);
|
|
1937
2087
|
};
|
|
1938
2088
|
const renderViewMode = () => /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col bg-background overflow-hidden w-full max-h-[90vh]" }, /* @__PURE__ */ React15.createElement(
|
|
1939
2089
|
"div",
|
|
@@ -1949,12 +2099,13 @@ var EventModal = ({
|
|
|
1949
2099
|
className: "w-3 h-3 rounded-full",
|
|
1950
2100
|
style: { backgroundColor: event?.color || "#3b82f6" }
|
|
1951
2101
|
}
|
|
1952
|
-
), /* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider" }, calendars?.find((c) => c.id === event?.calendarId)?.label ||
|
|
2102
|
+
), /* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider" }, calendars?.find((c) => c.id === event?.calendarId)?.label || t.event)), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React15.createElement(
|
|
1953
2103
|
"button",
|
|
1954
2104
|
{
|
|
1955
2105
|
onClick: () => setMode("edit"),
|
|
1956
2106
|
className: "p-2 hover:bg-background/80 rounded-lg transition-all text-muted-foreground hover:text-foreground",
|
|
1957
|
-
title:
|
|
2107
|
+
title: t.edit,
|
|
2108
|
+
"aria-label": t.edit
|
|
1958
2109
|
},
|
|
1959
2110
|
/* @__PURE__ */ React15.createElement(Edit2, { className: "w-4 h-4" })
|
|
1960
2111
|
), /* @__PURE__ */ React15.createElement(
|
|
@@ -1962,7 +2113,8 @@ var EventModal = ({
|
|
|
1962
2113
|
{
|
|
1963
2114
|
onClick: handleDelete,
|
|
1964
2115
|
className: "p-2 hover:bg-destructive/10 rounded-lg transition-all text-muted-foreground hover:text-destructive",
|
|
1965
|
-
title:
|
|
2116
|
+
title: t.delete,
|
|
2117
|
+
"aria-label": t.delete
|
|
1966
2118
|
},
|
|
1967
2119
|
/* @__PURE__ */ React15.createElement(Trash2, { className: "w-4 h-4" })
|
|
1968
2120
|
), /* @__PURE__ */ React15.createElement(
|
|
@@ -1970,21 +2122,25 @@ var EventModal = ({
|
|
|
1970
2122
|
{
|
|
1971
2123
|
onClick: onClose,
|
|
1972
2124
|
className: "p-2 hover:bg-background/80 rounded-lg transition-all text-muted-foreground hover:text-foreground",
|
|
1973
|
-
title:
|
|
2125
|
+
title: t.close,
|
|
2126
|
+
"aria-label": t.close
|
|
1974
2127
|
},
|
|
1975
2128
|
/* @__PURE__ */ React15.createElement(X2, { className: "w-4 h-4" })
|
|
1976
2129
|
))),
|
|
1977
|
-
/* @__PURE__ */ React15.createElement("h1", { className: "text-2xl font-bold text-foreground mb-3 leading-tight" }, event?.title ||
|
|
1978
|
-
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-3 text-sm" }, /* @__PURE__ */ React15.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__ */ React15.createElement(Calendar2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "font-medium" }, event?.start && format12(new Date(event.start), "EEE, MMM d"))), /* @__PURE__ */ React15.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__ */ React15.createElement(Clock2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "font-medium" }, event?.start && format12(new Date(event.start),
|
|
2130
|
+
/* @__PURE__ */ React15.createElement("h1", { className: "text-2xl font-bold text-foreground mb-3 leading-tight" }, event?.title || t.noTitle),
|
|
2131
|
+
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-3 text-sm" }, /* @__PURE__ */ React15.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__ */ React15.createElement(Calendar2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "font-medium" }, event?.start && format12(new Date(event.start), "EEE, MMM d", { locale }))), /* @__PURE__ */ React15.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__ */ React15.createElement(Clock2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "font-medium" }, event?.start && format12(new Date(event.start), timeFormat, { locale }), " \u2013 ", event?.end && format12(new Date(event.end), timeFormat, { locale }))))
|
|
1979
2132
|
), /* @__PURE__ */ React15.createElement("div", { className: "px-6 pb-6 space-y-4 overflow-y-auto flex-1" }, event?.location && /* @__PURE__ */ React15.createElement(
|
|
1980
|
-
motion2.
|
|
2133
|
+
motion2.a,
|
|
1981
2134
|
{
|
|
2135
|
+
href: mapsUrl(event.location),
|
|
2136
|
+
target: "_blank",
|
|
2137
|
+
rel: "noopener noreferrer",
|
|
1982
2138
|
initial: { opacity: 0, y: 10 },
|
|
1983
2139
|
animate: { opacity: 1, y: 0 },
|
|
1984
2140
|
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
2141
|
},
|
|
1986
2142
|
/* @__PURE__ */ React15.createElement("div", { className: "p-2 bg-primary/10 rounded-xl" }, /* @__PURE__ */ React15.createElement(MapPin, { className: "w-5 h-5 text-primary" })),
|
|
1987
|
-
/* @__PURE__ */ React15.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React15.createElement("p", { className: "text-sm font-medium text-foreground" }, event.location), /* @__PURE__ */ React15.createElement("p", { className: "text-xs text-muted-foreground mt-0.5" },
|
|
2143
|
+
/* @__PURE__ */ React15.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React15.createElement("p", { className: "text-sm font-medium text-foreground" }, event.location), /* @__PURE__ */ React15.createElement("p", { className: "text-xs text-muted-foreground mt-0.5" }, t.openInMaps)),
|
|
1988
2144
|
/* @__PURE__ */ React15.createElement(ExternalLink, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
|
|
1989
2145
|
), event?.guests && event.guests.length > 0 && /* @__PURE__ */ React15.createElement(
|
|
1990
2146
|
motion2.div,
|
|
@@ -1994,18 +2150,18 @@ var EventModal = ({
|
|
|
1994
2150
|
transition: { delay: 0.05 },
|
|
1995
2151
|
className: "space-y-3"
|
|
1996
2152
|
},
|
|
1997
|
-
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Users2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, event.guests.length, " ", event.guests.length > 1 ?
|
|
1998
|
-
/* @__PURE__ */ React15.createElement("div", { className: "flex flex-wrap gap-2" }, event.guests.map((email
|
|
2153
|
+
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Users2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, event.guests.length, " ", event.guests.length > 1 ? t.guests : t.guestSingular))),
|
|
2154
|
+
/* @__PURE__ */ React15.createElement("div", { className: "flex flex-wrap gap-2" }, event.guests.map((email) => /* @__PURE__ */ React15.createElement(
|
|
1999
2155
|
"div",
|
|
2000
2156
|
{
|
|
2001
|
-
key:
|
|
2002
|
-
className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-muted/30 border border-border/30
|
|
2157
|
+
key: email,
|
|
2158
|
+
className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-muted/30 border border-border/30"
|
|
2003
2159
|
},
|
|
2004
2160
|
/* @__PURE__ */ React15.createElement(
|
|
2005
2161
|
"div",
|
|
2006
2162
|
{
|
|
2007
2163
|
className: "w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold text-white",
|
|
2008
|
-
style: { backgroundColor: `hsl(${
|
|
2164
|
+
style: { backgroundColor: `hsl(${avatarHue(email)}, 70%, 50%)` }
|
|
2009
2165
|
},
|
|
2010
2166
|
email[0].toUpperCase()
|
|
2011
2167
|
),
|
|
@@ -2026,7 +2182,7 @@ var EventModal = ({
|
|
|
2026
2182
|
key: reminder.id,
|
|
2027
2183
|
className: "text-xs font-medium px-2.5 py-1 rounded-full bg-amber-500/10 text-amber-600 dark:text-amber-400"
|
|
2028
2184
|
},
|
|
2029
|
-
reminder.label ||
|
|
2185
|
+
reminder.label || reminderLabel(reminder.time, t)
|
|
2030
2186
|
)))
|
|
2031
2187
|
), event?.description && /* @__PURE__ */ React15.createElement(
|
|
2032
2188
|
motion2.div,
|
|
@@ -2036,7 +2192,7 @@ var EventModal = ({
|
|
|
2036
2192
|
transition: { delay: 0.15 },
|
|
2037
2193
|
className: "space-y-2"
|
|
2038
2194
|
},
|
|
2039
|
-
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" },
|
|
2195
|
+
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, t.notesLabel)),
|
|
2040
2196
|
/* @__PURE__ */ React15.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)
|
|
2041
2197
|
), event?.attachments && event.attachments.length > 0 && /* @__PURE__ */ React15.createElement(
|
|
2042
2198
|
motion2.div,
|
|
@@ -2046,25 +2202,16 @@ var EventModal = ({
|
|
|
2046
2202
|
transition: { delay: 0.2 },
|
|
2047
2203
|
className: "space-y-2"
|
|
2048
2204
|
},
|
|
2049
|
-
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Paperclip2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" },
|
|
2050
|
-
/* @__PURE__ */ React15.createElement("div", { className: "grid gap-2" }, event.attachments.map(
|
|
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
|
-
)))
|
|
2205
|
+
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Paperclip2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, t.attachments)),
|
|
2206
|
+
/* @__PURE__ */ React15.createElement("div", { className: "grid gap-2" }, event.attachments.map(renderAttachment))
|
|
2061
2207
|
)));
|
|
2062
2208
|
const renderEditMode = () => /* @__PURE__ */ React15.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col bg-background overflow-hidden w-full max-h-[85vh]" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between px-5 py-4 border-b border-border/50 shrink-0" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React15.createElement(
|
|
2063
2209
|
"button",
|
|
2064
2210
|
{
|
|
2065
2211
|
type: "button",
|
|
2066
2212
|
onClick: () => setIsColorPickerOpen(!isColorPickerOpen),
|
|
2067
|
-
className: "relative p-1"
|
|
2213
|
+
className: "relative p-1",
|
|
2214
|
+
"aria-label": t.eventColor
|
|
2068
2215
|
},
|
|
2069
2216
|
/* @__PURE__ */ React15.createElement(
|
|
2070
2217
|
"div",
|
|
@@ -2081,6 +2228,7 @@ var EventModal = ({
|
|
|
2081
2228
|
{
|
|
2082
2229
|
key: color,
|
|
2083
2230
|
type: "button",
|
|
2231
|
+
"aria-label": color,
|
|
2084
2232
|
onClick: () => {
|
|
2085
2233
|
setFormData((prev) => ({ ...prev, color }));
|
|
2086
2234
|
setIsColorPickerOpen(false);
|
|
@@ -2092,12 +2240,13 @@ var EventModal = ({
|
|
|
2092
2240
|
style: { backgroundColor: color, color }
|
|
2093
2241
|
}
|
|
2094
2242
|
)))
|
|
2095
|
-
), /* @__PURE__ */ React15.createElement("h2", { className: "text-lg font-semibold text-foreground" }, mode === "edit" ?
|
|
2243
|
+
), /* @__PURE__ */ React15.createElement("h2", { className: "text-lg font-semibold text-foreground" }, mode === "edit" ? t.editEvent : t.newEvent)), /* @__PURE__ */ React15.createElement(
|
|
2096
2244
|
"button",
|
|
2097
2245
|
{
|
|
2098
2246
|
type: "button",
|
|
2099
2247
|
onClick: onClose,
|
|
2100
|
-
className: "p-2 hover:bg-accent rounded-xl transition-all text-muted-foreground hover:text-foreground"
|
|
2248
|
+
className: "p-2 hover:bg-accent rounded-xl transition-all text-muted-foreground hover:text-foreground",
|
|
2249
|
+
"aria-label": t.close
|
|
2101
2250
|
},
|
|
2102
2251
|
/* @__PURE__ */ React15.createElement(X2, { className: "w-4 h-4" })
|
|
2103
2252
|
)), /* @__PURE__ */ React15.createElement("div", { className: "flex-1 overflow-y-auto" }, /* @__PURE__ */ React15.createElement("div", { className: "px-5 py-4 space-y-5" }, /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement(
|
|
@@ -2109,25 +2258,28 @@ var EventModal = ({
|
|
|
2109
2258
|
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
2259
|
value: formData.title,
|
|
2111
2260
|
onChange: (e) => setFormData({ ...formData, title: e.target.value }),
|
|
2112
|
-
placeholder:
|
|
2261
|
+
placeholder: t.title,
|
|
2262
|
+
"aria-label": t.title
|
|
2113
2263
|
}
|
|
2114
|
-
)), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-3 p-4 rounded-2xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15.createElement("div", { className: "p-2 bg-primary/10 rounded-xl shrink-0" }, /* @__PURE__ */ React15.createElement(Clock2, { className: "w-5 h-5 text-primary" })), /* @__PURE__ */ React15.createElement("div", { className: "flex-1 grid grid-cols-2 gap-3" }, /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("label", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" },
|
|
2264
|
+
)), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-3 p-4 rounded-2xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15.createElement("div", { className: "p-2 bg-primary/10 rounded-xl shrink-0" }, /* @__PURE__ */ React15.createElement(Clock2, { className: "w-5 h-5 text-primary" })), /* @__PURE__ */ React15.createElement("div", { className: "flex-1 grid grid-cols-2 gap-3" }, /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("label", { htmlFor: "calendarkit-event-start", className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, t.start), /* @__PURE__ */ React15.createElement(
|
|
2115
2265
|
"input",
|
|
2116
2266
|
{
|
|
2267
|
+
id: "calendarkit-event-start",
|
|
2117
2268
|
type: "datetime-local",
|
|
2118
2269
|
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
2270
|
value: formatDateForInput(formData.start),
|
|
2120
2271
|
onChange: (e) => handleDateChange("start", e.target.value)
|
|
2121
2272
|
}
|
|
2122
|
-
)), /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("label", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" },
|
|
2273
|
+
)), /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("label", { htmlFor: "calendarkit-event-end", className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, t.end), /* @__PURE__ */ React15.createElement(
|
|
2123
2274
|
"input",
|
|
2124
2275
|
{
|
|
2276
|
+
id: "calendarkit-event-end",
|
|
2125
2277
|
type: "datetime-local",
|
|
2126
2278
|
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
2279
|
value: formatDateForInput(formData.end),
|
|
2128
2280
|
onChange: (e) => handleDateChange("end", e.target.value)
|
|
2129
2281
|
}
|
|
2130
|
-
)))), getDurationText() && /* @__PURE__ */ React15.createElement("div", { className: "flex justify-center" }, /* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium px-3 py-1 rounded-full bg-primary/10 text-primary" }, getDurationText())), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Bell2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" },
|
|
2282
|
+
)))), getDurationText() && /* @__PURE__ */ React15.createElement("div", { className: "flex justify-center" }, /* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium px-3 py-1 rounded-full bg-primary/10 text-primary" }, getDurationText())), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Bell2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, t.reminders)), /* @__PURE__ */ React15.createElement("div", { className: "relative" }, /* @__PURE__ */ React15.createElement(
|
|
2131
2283
|
"button",
|
|
2132
2284
|
{
|
|
2133
2285
|
type: "button",
|
|
@@ -2135,16 +2287,16 @@ var EventModal = ({
|
|
|
2135
2287
|
className: "flex items-center gap-1 text-xs font-medium text-primary hover:text-primary/80 transition-colors"
|
|
2136
2288
|
},
|
|
2137
2289
|
/* @__PURE__ */ React15.createElement(Plus3, { className: "w-3.5 h-3.5" }),
|
|
2138
|
-
|
|
2139
|
-
), isReminderDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsReminderDropdownOpen(false) }), /* @__PURE__ */ React15.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((
|
|
2290
|
+
t.add
|
|
2291
|
+
), isReminderDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsReminderDropdownOpen(false) }), /* @__PURE__ */ React15.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__ */ React15.createElement(
|
|
2140
2292
|
"button",
|
|
2141
2293
|
{
|
|
2142
|
-
key:
|
|
2294
|
+
key: minutes,
|
|
2143
2295
|
type: "button",
|
|
2144
|
-
onClick: () => addReminder(
|
|
2296
|
+
onClick: () => addReminder(minutes),
|
|
2145
2297
|
className: "w-full px-3 py-2 text-left text-sm hover:bg-accent transition-colors"
|
|
2146
2298
|
},
|
|
2147
|
-
|
|
2299
|
+
reminderLabel(minutes, t)
|
|
2148
2300
|
)))))), formData.reminders && formData.reminders.length > 0 && /* @__PURE__ */ React15.createElement("div", { className: "flex flex-wrap gap-2" }, formData.reminders.map((reminder) => /* @__PURE__ */ React15.createElement(
|
|
2149
2301
|
"div",
|
|
2150
2302
|
{
|
|
@@ -2152,45 +2304,44 @@ var EventModal = ({
|
|
|
2152
2304
|
className: "flex items-center gap-2 px-3 py-1.5 rounded-full bg-amber-500/10 border border-amber-500/20"
|
|
2153
2305
|
},
|
|
2154
2306
|
/* @__PURE__ */ React15.createElement(BellRing, { className: "w-3.5 h-3.5 text-amber-500" }),
|
|
2155
|
-
/* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400" }, reminder.label),
|
|
2307
|
+
/* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400" }, reminder.label || reminderLabel(reminder.time, t)),
|
|
2156
2308
|
/* @__PURE__ */ React15.createElement(
|
|
2157
2309
|
"button",
|
|
2158
2310
|
{
|
|
2159
2311
|
type: "button",
|
|
2160
2312
|
onClick: () => removeReminder(reminder.id),
|
|
2161
|
-
className: "p-0.5 hover:bg-amber-500/20 rounded-full transition-colors"
|
|
2313
|
+
className: "p-0.5 hover:bg-amber-500/20 rounded-full transition-colors",
|
|
2314
|
+
"aria-label": t.removeReminder
|
|
2162
2315
|
},
|
|
2163
2316
|
/* @__PURE__ */ React15.createElement(X2, { className: "w-3 h-3 text-amber-500" })
|
|
2164
2317
|
)
|
|
2165
|
-
)))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Users2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("
|
|
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",
|
|
2318
|
+
)))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Users2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("label", { htmlFor: "calendarkit-event-guest", className: "text-sm font-medium text-foreground" }, t.guests)), /* @__PURE__ */ React15.createElement(
|
|
2319
|
+
"input",
|
|
2176
2320
|
{
|
|
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%)` }
|
|
2321
|
+
id: "calendarkit-event-guest",
|
|
2322
|
+
type: "text",
|
|
2323
|
+
inputMode: "email",
|
|
2324
|
+
autoComplete: "email",
|
|
2325
|
+
value: guestInput,
|
|
2326
|
+
onChange: (e) => {
|
|
2327
|
+
setGuestInput(e.target.value);
|
|
2328
|
+
setGuestError(false);
|
|
2190
2329
|
},
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2330
|
+
onKeyDown: (e) => {
|
|
2331
|
+
if (e.key === "Enter" || e.key === ",") {
|
|
2332
|
+
e.preventDefault();
|
|
2333
|
+
addGuests(guestInput);
|
|
2334
|
+
}
|
|
2335
|
+
},
|
|
2336
|
+
onBlur: () => guestInput.trim() && addGuests(guestInput),
|
|
2337
|
+
placeholder: t.addGuestPlaceholder,
|
|
2338
|
+
"aria-invalid": guestError,
|
|
2339
|
+
className: cn(
|
|
2340
|
+
"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",
|
|
2341
|
+
guestError ? "border-destructive" : "border-border/30"
|
|
2342
|
+
)
|
|
2343
|
+
}
|
|
2344
|
+
), guestError && /* @__PURE__ */ React15.createElement("p", { role: "alert", className: "text-xs text-destructive" }, t.invalidEmail), guests.length > 0 && /* @__PURE__ */ React15.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, guests.map((email) => /* @__PURE__ */ React15.createElement(
|
|
2194
2345
|
"div",
|
|
2195
2346
|
{
|
|
2196
2347
|
key: email,
|
|
@@ -2200,17 +2351,18 @@ var EventModal = ({
|
|
|
2200
2351
|
"div",
|
|
2201
2352
|
{
|
|
2202
2353
|
className: "w-6 h-6 rounded-full flex items-center justify-center text-xs font-semibold text-white",
|
|
2203
|
-
style: { backgroundColor: `hsl(${
|
|
2354
|
+
style: { backgroundColor: `hsl(${avatarHue(email)}, 70%, 50%)` }
|
|
2204
2355
|
},
|
|
2205
2356
|
email[0].toUpperCase()
|
|
2206
2357
|
),
|
|
2207
|
-
/* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium text-foreground" }, email
|
|
2358
|
+
/* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium text-foreground" }, email),
|
|
2208
2359
|
/* @__PURE__ */ React15.createElement(
|
|
2209
2360
|
"button",
|
|
2210
2361
|
{
|
|
2211
2362
|
type: "button",
|
|
2212
|
-
onClick: () =>
|
|
2213
|
-
className: "p-0.5 hover:bg-destructive/10 rounded-full transition-colors"
|
|
2363
|
+
onClick: () => removeGuest(email),
|
|
2364
|
+
className: "p-0.5 hover:bg-destructive/10 rounded-full transition-colors",
|
|
2365
|
+
"aria-label": interpolate(t.removeGuest, { email })
|
|
2214
2366
|
},
|
|
2215
2367
|
/* @__PURE__ */ React15.createElement(X2, { className: "w-3 h-3 text-muted-foreground" })
|
|
2216
2368
|
)
|
|
@@ -2219,15 +2371,17 @@ var EventModal = ({
|
|
|
2219
2371
|
{
|
|
2220
2372
|
type: "text",
|
|
2221
2373
|
className: "flex-1 bg-transparent text-sm text-foreground placeholder-muted-foreground focus:outline-none",
|
|
2222
|
-
placeholder:
|
|
2374
|
+
placeholder: t.addLocation,
|
|
2375
|
+
"aria-label": t.addLocation,
|
|
2223
2376
|
value: formData.location || "",
|
|
2224
2377
|
onChange: (e) => setFormData({ ...formData, location: e.target.value })
|
|
2225
2378
|
}
|
|
2226
|
-
)), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" },
|
|
2379
|
+
)), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, t.notesLabel)), /* @__PURE__ */ React15.createElement(
|
|
2227
2380
|
"textarea",
|
|
2228
2381
|
{
|
|
2229
2382
|
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:
|
|
2383
|
+
placeholder: t.addNotes,
|
|
2384
|
+
"aria-label": t.notesLabel,
|
|
2231
2385
|
value: formData.description || "",
|
|
2232
2386
|
onChange: (e) => setFormData({ ...formData, description: e.target.value })
|
|
2233
2387
|
}
|
|
@@ -2235,6 +2389,7 @@ var EventModal = ({
|
|
|
2235
2389
|
"select",
|
|
2236
2390
|
{
|
|
2237
2391
|
className: "flex-1 bg-transparent text-sm text-foreground focus:outline-none cursor-pointer",
|
|
2392
|
+
"aria-label": t.repeat,
|
|
2238
2393
|
value: formData.recurrence?.freq || "",
|
|
2239
2394
|
onChange: (e) => {
|
|
2240
2395
|
if (e.target.value === "") {
|
|
@@ -2250,12 +2405,12 @@ var EventModal = ({
|
|
|
2250
2405
|
}
|
|
2251
2406
|
}
|
|
2252
2407
|
},
|
|
2253
|
-
/* @__PURE__ */ React15.createElement("option", { value: "" },
|
|
2254
|
-
/* @__PURE__ */ React15.createElement("option", { value: "DAILY" },
|
|
2255
|
-
/* @__PURE__ */ React15.createElement("option", { value: "WEEKLY" },
|
|
2256
|
-
/* @__PURE__ */ React15.createElement("option", { value: "MONTHLY" },
|
|
2257
|
-
/* @__PURE__ */ React15.createElement("option", { value: "YEARLY" },
|
|
2258
|
-
)), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Tag, { className: "w-5 h-5 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm text-foreground" },
|
|
2408
|
+
/* @__PURE__ */ React15.createElement("option", { value: "" }, t.doesNotRepeat),
|
|
2409
|
+
/* @__PURE__ */ React15.createElement("option", { value: "DAILY" }, t.daily),
|
|
2410
|
+
/* @__PURE__ */ React15.createElement("option", { value: "WEEKLY" }, t.weekly),
|
|
2411
|
+
/* @__PURE__ */ React15.createElement("option", { value: "MONTHLY" }, t.monthly),
|
|
2412
|
+
/* @__PURE__ */ React15.createElement("option", { value: "YEARLY" }, t.yearly)
|
|
2413
|
+
)), calendars && calendars.length > 0 && /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Tag, { className: "w-5 h-5 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm text-foreground" }, t.calendar)), /* @__PURE__ */ React15.createElement("div", { className: "relative" }, /* @__PURE__ */ React15.createElement(
|
|
2259
2414
|
"button",
|
|
2260
2415
|
{
|
|
2261
2416
|
type: "button",
|
|
@@ -2266,12 +2421,12 @@ var EventModal = ({
|
|
|
2266
2421
|
"div",
|
|
2267
2422
|
{
|
|
2268
2423
|
className: "w-3 h-3 rounded-full",
|
|
2269
|
-
style: { backgroundColor: calendars
|
|
2424
|
+
style: { backgroundColor: calendars.find((c) => c.id === formData.calendarId)?.color || "#3b82f6" }
|
|
2270
2425
|
}
|
|
2271
2426
|
),
|
|
2272
|
-
/* @__PURE__ */ React15.createElement("span", { className: "font-medium" }, calendars
|
|
2427
|
+
/* @__PURE__ */ React15.createElement("span", { className: "font-medium" }, calendars.find((c) => c.id === formData.calendarId)?.label || t.select),
|
|
2273
2428
|
/* @__PURE__ */ React15.createElement(ChevronDown2, { className: "w-3.5 h-3.5 text-muted-foreground" })
|
|
2274
|
-
), isCalendarDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsCalendarDropdownOpen(false) }), /* @__PURE__ */ React15.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
|
|
2429
|
+
), isCalendarDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsCalendarDropdownOpen(false) }), /* @__PURE__ */ React15.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__ */ React15.createElement(
|
|
2275
2430
|
"button",
|
|
2276
2431
|
{
|
|
2277
2432
|
key: cal.id,
|
|
@@ -2297,7 +2452,7 @@ var EventModal = ({
|
|
|
2297
2452
|
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
2453
|
},
|
|
2299
2454
|
/* @__PURE__ */ React15.createElement(Trash2, { className: "w-4 h-4" }),
|
|
2300
|
-
|
|
2455
|
+
t.delete
|
|
2301
2456
|
), mode === "create" && /* @__PURE__ */ React15.createElement("div", null), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(
|
|
2302
2457
|
"button",
|
|
2303
2458
|
{
|
|
@@ -2305,14 +2460,14 @@ var EventModal = ({
|
|
|
2305
2460
|
onClick: onClose,
|
|
2306
2461
|
className: "px-4 py-2.5 text-muted-foreground hover:text-foreground font-medium text-sm rounded-xl transition-all hover:bg-accent"
|
|
2307
2462
|
},
|
|
2308
|
-
|
|
2463
|
+
t.cancel
|
|
2309
2464
|
), /* @__PURE__ */ React15.createElement(
|
|
2310
2465
|
"button",
|
|
2311
2466
|
{
|
|
2312
2467
|
type: "submit",
|
|
2313
2468
|
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
2469
|
},
|
|
2315
|
-
mode === "edit" ?
|
|
2470
|
+
mode === "edit" ? t.saveChanges : t.createEvent
|
|
2316
2471
|
))));
|
|
2317
2472
|
return /* @__PURE__ */ React15.createElement(Modal, { isOpen, onClose, hideHeader: true, className: "p-0 overflow-hidden max-w-lg rounded-2xl shadow-2xl" }, /* @__PURE__ */ React15.createElement(AnimatePresence, { mode: "wait" }, mode === "view" && event ? /* @__PURE__ */ React15.createElement(
|
|
2318
2473
|
motion2.div,
|
|
@@ -2340,7 +2495,7 @@ var EventModal = ({
|
|
|
2340
2495
|
// src/components/Skeleton.tsx
|
|
2341
2496
|
import React16 from "react";
|
|
2342
2497
|
var Skeleton = ({ className, style }) => /* @__PURE__ */ React16.createElement("div", { className: cn("animate-pulse bg-muted/40 rounded", className), style });
|
|
2343
|
-
var MonthViewSkeleton = () => /* @__PURE__ */ React16.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React16.createElement("div", { className: "grid grid-cols-7 border-b border-border/50 bg-muted/10" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-4 w-8 mx-auto" })))), /* @__PURE__ */ React16.createElement("div", { className: "grid grid-cols-7 flex-1" }, Array.from({ length: 35 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "min-h-[120px] border-r border-b border-border/30 p-2" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-4 w-6 mb-2" }), /* @__PURE__ */ React16.createElement("div", { className: "space-y-1" },
|
|
2498
|
+
var MonthViewSkeleton = () => /* @__PURE__ */ React16.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React16.createElement("div", { className: "grid grid-cols-7 border-b border-border/50 bg-muted/10" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-4 w-8 mx-auto" })))), /* @__PURE__ */ React16.createElement("div", { className: "grid grid-cols-7 flex-1" }, Array.from({ length: 35 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "min-h-[120px] border-r border-b border-border/30 p-2" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-4 w-6 mb-2" }), /* @__PURE__ */ React16.createElement("div", { className: "space-y-1" }, i * 7 % 10 > 4 && /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-5 w-full rounded-md" }), i * 3 % 10 > 6 && /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-5 w-3/4 rounded-md" }))))));
|
|
2344
2499
|
var WeekViewSkeleton = () => /* @__PURE__ */ React16.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React16.createElement("div", { className: "flex border-b border-border/50 bg-muted/10" }, /* @__PURE__ */ React16.createElement("div", { className: "w-16 p-3 border-r border-border/30" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-8 w-10 mx-auto" })), /* @__PURE__ */ React16.createElement("div", { className: "flex-1 grid grid-cols-7" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-3 w-8 mx-auto mb-1" }), /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-8 w-8 mx-auto rounded-xl" }))))), /* @__PURE__ */ React16.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ React16.createElement("div", { className: "w-16 border-r border-border/30" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "h-[60px] relative" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-4 w-10 absolute right-2 -translate-y-1/2" })))), /* @__PURE__ */ React16.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, Array.from({ length: 7 }).map((_, colIdx) => /* @__PURE__ */ React16.createElement("div", { key: colIdx, className: "relative border-r border-border/30 last:border-r-0" }, Array.from({ length: 10 }).map((_2, rowIdx) => /* @__PURE__ */ React16.createElement("div", { key: rowIdx, className: "h-[60px] border-b border-dashed border-border/20" })), Math.random() > 0.3 && /* @__PURE__ */ React16.createElement(
|
|
2345
2500
|
Skeleton,
|
|
2346
2501
|
{
|
|
@@ -2369,7 +2524,7 @@ var DayViewSkeleton = () => /* @__PURE__ */ React16.createElement("div", { class
|
|
|
2369
2524
|
var AgendaViewSkeleton = () => /* @__PURE__ */ React16.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden p-6" }, /* @__PURE__ */ React16.createElement("div", { className: "space-y-6" }, Array.from({ length: 4 }).map((_, dayIdx) => /* @__PURE__ */ React16.createElement("div", { key: dayIdx }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-5 w-40 mb-4" }), /* @__PURE__ */ React16.createElement("div", { className: "space-y-3" }, Array.from({ length: 2 + Math.floor(Math.random() * 3) }).map((_2, eventIdx) => /* @__PURE__ */ React16.createElement("div", { key: eventIdx, className: "flex items-center gap-4 p-3 rounded-xl bg-muted/10" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-10 w-10 rounded-lg" }), /* @__PURE__ */ React16.createElement("div", { className: "flex-1 space-y-2" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-4 w-3/4" }), /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-3 w-1/2" })))))))));
|
|
2370
2525
|
|
|
2371
2526
|
// src/components/ContextMenu.tsx
|
|
2372
|
-
import React17, { useState as useState4, useCallback as useCallback2, useEffect as useEffect4, useRef as
|
|
2527
|
+
import React17, { useState as useState4, useCallback as useCallback2, useEffect as useEffect4, useRef as useRef5 } from "react";
|
|
2373
2528
|
import { Edit3, Trash2 as Trash22, Copy } from "lucide-react";
|
|
2374
2529
|
import { AnimatePresence as AnimatePresence2, motion as motion3 } from "framer-motion";
|
|
2375
2530
|
var EventContextMenu = ({
|
|
@@ -2382,7 +2537,7 @@ var EventContextMenu = ({
|
|
|
2382
2537
|
customActions = [],
|
|
2383
2538
|
translations
|
|
2384
2539
|
}) => {
|
|
2385
|
-
const menuRef =
|
|
2540
|
+
const menuRef = useRef5(null);
|
|
2386
2541
|
useEffect4(() => {
|
|
2387
2542
|
const handleKeyDown = (e) => {
|
|
2388
2543
|
if (e.key === "Escape") {
|
|
@@ -2673,13 +2828,14 @@ function cachedMonth(event, monthStart, tz) {
|
|
|
2673
2828
|
}
|
|
2674
2829
|
function expandRecurrences(events, range, anchorTz) {
|
|
2675
2830
|
const result = [];
|
|
2676
|
-
const firstMonth = startOfMonth2(toDisplay(range.start, anchorTz));
|
|
2677
2831
|
const lastMonth = startOfMonth2(toDisplay(range.end, anchorTz));
|
|
2678
2832
|
for (const event of events) {
|
|
2679
2833
|
if (!event.recurrence) {
|
|
2680
2834
|
result.push(event);
|
|
2681
2835
|
continue;
|
|
2682
2836
|
}
|
|
2837
|
+
const duration = event.end.getTime() - event.start.getTime();
|
|
2838
|
+
const firstMonth = startOfMonth2(toDisplay(new Date(range.start.getTime() - duration), anchorTz));
|
|
2683
2839
|
try {
|
|
2684
2840
|
for (let month = firstMonth; month <= lastMonth; month = addMonths2(month, 1)) {
|
|
2685
2841
|
for (const occurrence of cachedMonth(event, fromDisplay(month, anchorTz), anchorTz)) {
|
|
@@ -2710,6 +2866,7 @@ function shiftSeries(master, occurrence, newStart, newEnd, anchorTz) {
|
|
|
2710
2866
|
const recurrence = master.recurrence && {
|
|
2711
2867
|
...master.recurrence,
|
|
2712
2868
|
byweekday: master.recurrence.byweekday && dayDelta % 7 !== 0 ? master.recurrence.byweekday.map((d) => ((d + dayDelta) % 7 + 7) % 7) : master.recurrence.byweekday,
|
|
2869
|
+
until: master.recurrence.until && shiftFloating(master.recurrence.until, deltaMs, anchorTz),
|
|
2713
2870
|
exdates: master.recurrence.exdates?.map((d) => shiftFloating(d, deltaMs, anchorTz))
|
|
2714
2871
|
};
|
|
2715
2872
|
return stripOccurrenceFields({ ...master, start, end, recurrence });
|
|
@@ -2720,10 +2877,12 @@ function excludeOccurrence(master, occurrenceStart) {
|
|
|
2720
2877
|
}
|
|
2721
2878
|
|
|
2722
2879
|
// src/hooks/useStableCallback.ts
|
|
2723
|
-
import { useCallback as useCallback3, useRef as
|
|
2880
|
+
import { useCallback as useCallback3, useInsertionEffect as useInsertionEffect2, useRef as useRef6 } from "react";
|
|
2724
2881
|
function useStableCallback(fn) {
|
|
2725
|
-
const ref =
|
|
2726
|
-
|
|
2882
|
+
const ref = useRef6(fn);
|
|
2883
|
+
useInsertionEffect2(() => {
|
|
2884
|
+
ref.current = fn;
|
|
2885
|
+
});
|
|
2727
2886
|
return useCallback3((...args) => ref.current(...args), []);
|
|
2728
2887
|
}
|
|
2729
2888
|
|
|
@@ -2904,6 +3063,7 @@ var useCalendarLogic = ({
|
|
|
2904
3063
|
return { original: master, updated: shiftSeries(master, event, start, end, timezone) };
|
|
2905
3064
|
};
|
|
2906
3065
|
const handleDragEnd = useStableCallback((dragEvent) => {
|
|
3066
|
+
if (readOnly) return;
|
|
2907
3067
|
const { active, over } = dragEvent;
|
|
2908
3068
|
if (!over) return;
|
|
2909
3069
|
const dragged = active.data.current?.event;
|
|
@@ -2960,10 +3120,10 @@ var useCalendarLogic = ({
|
|
|
2960
3120
|
};
|
|
2961
3121
|
|
|
2962
3122
|
// src/index.tsx
|
|
2963
|
-
import { differenceInMinutes as differenceInMinutes6, format as format14 } from "date-fns";
|
|
3123
|
+
import { differenceInMinutes as differenceInMinutes6, format as format14, startOfWeek as startOfWeek3 } from "date-fns";
|
|
2964
3124
|
|
|
2965
3125
|
// src/hooks/useSwipeGesture.ts
|
|
2966
|
-
import { useRef as
|
|
3126
|
+
import { useRef as useRef7, useCallback as useCallback4, useEffect as useEffect5 } from "react";
|
|
2967
3127
|
var useSwipeGesture = (options) => {
|
|
2968
3128
|
const {
|
|
2969
3129
|
onSwipeLeft,
|
|
@@ -2975,8 +3135,8 @@ var useSwipeGesture = (options) => {
|
|
|
2975
3135
|
allowedTime = 500,
|
|
2976
3136
|
enabled = true
|
|
2977
3137
|
} = options;
|
|
2978
|
-
const touchInfoRef =
|
|
2979
|
-
const elementRef =
|
|
3138
|
+
const touchInfoRef = useRef7(null);
|
|
3139
|
+
const elementRef = useRef7(null);
|
|
2980
3140
|
const handleTouchStart = useCallback4((e) => {
|
|
2981
3141
|
if (!enabled) return;
|
|
2982
3142
|
const touch = e.touches[0];
|
|
@@ -3072,6 +3232,7 @@ var Scheduler = ({
|
|
|
3072
3232
|
const {
|
|
3073
3233
|
contextMenuEvent,
|
|
3074
3234
|
contextMenuPosition,
|
|
3235
|
+
openContextMenu,
|
|
3075
3236
|
closeContextMenu
|
|
3076
3237
|
} = useEventContextMenu();
|
|
3077
3238
|
const {
|
|
@@ -3159,14 +3320,15 @@ var Scheduler = ({
|
|
|
3159
3320
|
}
|
|
3160
3321
|
return "150px";
|
|
3161
3322
|
};
|
|
3323
|
+
const activeCalendarKey = calendars ? calendars.filter((c) => c.active !== false).map((c) => c.id).join("\0") : null;
|
|
3162
3324
|
const filteredEvents = useMemo4(() => {
|
|
3163
|
-
if (
|
|
3164
|
-
const activeCalendarIds =
|
|
3165
|
-
return expandedEvents.filter((e) =>
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3325
|
+
if (activeCalendarKey === null) return expandedEvents;
|
|
3326
|
+
const activeCalendarIds = new Set(activeCalendarKey.split("\0"));
|
|
3327
|
+
return expandedEvents.filter((e) => !e.calendarId || activeCalendarIds.has(String(e.calendarId)));
|
|
3328
|
+
}, [expandedEvents, activeCalendarKey]);
|
|
3329
|
+
const periodKey = view === "month" ? format14(currentDate, "yyyy-MM") : view === "week" ? format14(startOfWeek3(currentDate, { weekStartsOn: resolveWeekStartsOn(locale, 1) }), "yyyy-MM-dd") : format14(currentDate, "yyyy-MM-dd");
|
|
3330
|
+
const slotClickHandler = readOnly ? void 0 : handleTimeSlotClick;
|
|
3331
|
+
const contextMenuHandler = readOnly ? void 0 : openContextMenu;
|
|
3170
3332
|
return /* @__PURE__ */ React18.createElement(
|
|
3171
3333
|
DndContext,
|
|
3172
3334
|
{
|
|
@@ -3237,7 +3399,7 @@ var Scheduler = ({
|
|
|
3237
3399
|
), /* @__PURE__ */ React18.createElement("div", { className: "flex-1 flex flex-col overflow-hidden relative" }, isLoading ? /* @__PURE__ */ React18.createElement("div", { className: "flex-1 overflow-auto p-0 md:p-4" }, /* @__PURE__ */ React18.createElement("div", { className: "h-full min-w-full" }, view === "month" && /* @__PURE__ */ React18.createElement(MonthViewSkeleton, null), view === "week" && /* @__PURE__ */ React18.createElement(WeekViewSkeleton, null), view === "day" && /* @__PURE__ */ React18.createElement(DayViewSkeleton, null), view === "agenda" && /* @__PURE__ */ React18.createElement(AgendaViewSkeleton, null), view === "resource" && /* @__PURE__ */ React18.createElement(WeekViewSkeleton, null))) : /* @__PURE__ */ React18.createElement("div", { ref: swipeRef, className: "flex-1 overflow-auto p-0 md:p-4 touch-pan-y" }, /* @__PURE__ */ React18.createElement("div", { className: "h-full min-w-full" }, /* @__PURE__ */ React18.createElement(AnimatePresence3, { mode: "wait", initial: false }, /* @__PURE__ */ React18.createElement(
|
|
3238
3400
|
motion4.div,
|
|
3239
3401
|
{
|
|
3240
|
-
key: `${view}-${
|
|
3402
|
+
key: `${view}-${periodKey}-${timezone || "local"}`,
|
|
3241
3403
|
initial: { opacity: 0, scale: 0.98, y: 15 },
|
|
3242
3404
|
animate: {
|
|
3243
3405
|
opacity: 1,
|
|
@@ -3267,7 +3429,9 @@ var Scheduler = ({
|
|
|
3267
3429
|
onEventClick: handleEventClickInternal,
|
|
3268
3430
|
onDateClick: handleDateClick,
|
|
3269
3431
|
timezone,
|
|
3270
|
-
locale
|
|
3432
|
+
locale,
|
|
3433
|
+
translations: t,
|
|
3434
|
+
onEventContextMenu: contextMenuHandler
|
|
3271
3435
|
}
|
|
3272
3436
|
),
|
|
3273
3437
|
view === "week" && /* @__PURE__ */ React18.createElement(
|
|
@@ -3276,11 +3440,12 @@ var Scheduler = ({
|
|
|
3276
3440
|
currentDate,
|
|
3277
3441
|
events: filteredEvents,
|
|
3278
3442
|
onEventClick: handleEventClickInternal,
|
|
3279
|
-
onTimeSlotClick:
|
|
3443
|
+
onTimeSlotClick: slotClickHandler,
|
|
3280
3444
|
onEventResize: handleEventResize,
|
|
3281
3445
|
timezone,
|
|
3282
3446
|
locale,
|
|
3283
|
-
readonly: readOnly
|
|
3447
|
+
readonly: readOnly,
|
|
3448
|
+
onEventContextMenu: contextMenuHandler
|
|
3284
3449
|
}
|
|
3285
3450
|
),
|
|
3286
3451
|
view === "day" && /* @__PURE__ */ React18.createElement(
|
|
@@ -3289,11 +3454,13 @@ var Scheduler = ({
|
|
|
3289
3454
|
currentDate,
|
|
3290
3455
|
events: filteredEvents,
|
|
3291
3456
|
onEventClick: handleEventClickInternal,
|
|
3292
|
-
onTimeSlotClick:
|
|
3457
|
+
onTimeSlotClick: slotClickHandler,
|
|
3293
3458
|
onEventResize: handleEventResize,
|
|
3294
3459
|
timezone,
|
|
3295
3460
|
locale,
|
|
3296
|
-
readonly: readOnly
|
|
3461
|
+
readonly: readOnly,
|
|
3462
|
+
translations: t,
|
|
3463
|
+
onEventContextMenu: contextMenuHandler
|
|
3297
3464
|
}
|
|
3298
3465
|
),
|
|
3299
3466
|
view === "agenda" && /* @__PURE__ */ React18.createElement(
|
|
@@ -3305,7 +3472,8 @@ var Scheduler = ({
|
|
|
3305
3472
|
onCreateEvent: handleCreateEvent,
|
|
3306
3473
|
locale,
|
|
3307
3474
|
translations: t,
|
|
3308
|
-
timezone
|
|
3475
|
+
timezone,
|
|
3476
|
+
onEventContextMenu: contextMenuHandler
|
|
3309
3477
|
}
|
|
3310
3478
|
),
|
|
3311
3479
|
view === "resource" && resources && /* @__PURE__ */ React18.createElement(
|
|
@@ -3315,15 +3483,18 @@ var Scheduler = ({
|
|
|
3315
3483
|
events: filteredEvents,
|
|
3316
3484
|
resources,
|
|
3317
3485
|
onEventClick: handleEventClickInternal,
|
|
3318
|
-
onTimeSlotClick:
|
|
3486
|
+
onTimeSlotClick: slotClickHandler,
|
|
3319
3487
|
locale,
|
|
3320
|
-
timezone
|
|
3488
|
+
timezone,
|
|
3489
|
+
translations: t,
|
|
3490
|
+
onEventContextMenu: contextMenuHandler
|
|
3321
3491
|
}
|
|
3322
3492
|
)
|
|
3323
|
-
)))), /* @__PURE__ */ React18.createElement("div", { className: "md:hidden absolute bottom-6 right-6 z-50" }, /* @__PURE__ */ React18.createElement(
|
|
3493
|
+
)))), !readOnly && /* @__PURE__ */ React18.createElement("div", { className: "md:hidden absolute bottom-6 right-6 z-50" }, /* @__PURE__ */ React18.createElement(
|
|
3324
3494
|
"button",
|
|
3325
3495
|
{
|
|
3326
3496
|
onClick: handleCreateEvent,
|
|
3497
|
+
"aria-label": t.createEvent,
|
|
3327
3498
|
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
3499
|
},
|
|
3329
3500
|
/* @__PURE__ */ React18.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__ */ React18.createElement("path", { d: "M5 12h14" }), /* @__PURE__ */ React18.createElement("path", { d: "M12 5v14" }))
|
|
@@ -3346,7 +3517,8 @@ var Scheduler = ({
|
|
|
3346
3517
|
onDelete: handleModalDelete,
|
|
3347
3518
|
calendars,
|
|
3348
3519
|
eventTypes,
|
|
3349
|
-
translations: t
|
|
3520
|
+
translations: t,
|
|
3521
|
+
locale
|
|
3350
3522
|
}
|
|
3351
3523
|
),
|
|
3352
3524
|
/* @__PURE__ */ React18.createElement(
|
|
@@ -3398,7 +3570,7 @@ var Scheduler = ({
|
|
|
3398
3570
|
className: "absolute left-0 top-0 bottom-0 w-1 rounded-l-lg",
|
|
3399
3571
|
style: { backgroundColor: activeDragEvent.color || "var(--primary)" }
|
|
3400
3572
|
}
|
|
3401
|
-
), /* @__PURE__ */ React18.createElement("div", { className: "pl-2" }, /* @__PURE__ */ React18.createElement("div", { className: "font-semibold truncate text-sm" }, activeDragEvent.title), (view === "week" || view === "day") && getDragHeight() && getDragHeight() > 40 && /* @__PURE__ */ React18.createElement("div", { className: "text-xs opacity-80 mt-0.5 flex items-center gap-1" }, /* @__PURE__ */ React18.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ React18.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React18.createElement("path", { d: "M12 6v6l4 2" })), format14(activeDragEvent.start, overlayTimeFormat, { locale }), " - ", format14(activeDragEvent.end, overlayTimeFormat, { locale }))), /* @__PURE__ */ React18.createElement("div", { className: "absolute bottom-1.5 right-1.5 opacity-60" }, /* @__PURE__ */ React18.createElement("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React18.createElement("circle", { cx: "9", cy: "5", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "15", cy: "5", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "9", cy: "12", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "15", cy: "12", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "9", cy: "19", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "15", cy: "19", r: "1.5" }))))
|
|
3573
|
+
), /* @__PURE__ */ React18.createElement("div", { className: "pl-2" }, /* @__PURE__ */ React18.createElement("div", { className: "font-semibold truncate text-sm" }, activeDragEvent.title), (view === "week" || view === "day") && getDragHeight() && getDragHeight() > 40 && /* @__PURE__ */ React18.createElement("div", { className: "text-xs opacity-80 mt-0.5 flex items-center gap-1" }, /* @__PURE__ */ React18.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ React18.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React18.createElement("path", { d: "M12 6v6l4 2" })), format14(toDisplay(activeDragEvent.start, timezone), overlayTimeFormat, { locale }), " - ", format14(toDisplay(activeDragEvent.end, timezone), overlayTimeFormat, { locale }))), /* @__PURE__ */ React18.createElement("div", { className: "absolute bottom-1.5 right-1.5 opacity-60" }, /* @__PURE__ */ React18.createElement("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React18.createElement("circle", { cx: "9", cy: "5", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "15", cy: "5", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "9", cy: "12", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "15", cy: "12", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "9", cy: "19", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "15", cy: "19", r: "1.5" }))))
|
|
3402
3574
|
) : null)
|
|
3403
3575
|
)
|
|
3404
3576
|
);
|