calendarkit-pro 1.3.0 → 1.4.0

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