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.js CHANGED
@@ -35,8 +35,8 @@ __export(index_exports, {
35
35
  cn: () => cn
36
36
  });
37
37
  module.exports = __toCommonJS(index_exports);
38
- var import_react20 = __toESM(require("react"));
39
- var import_core3 = require("@dnd-kit/core");
38
+ var import_react22 = __toESM(require("react"));
39
+ var import_core5 = require("@dnd-kit/core");
40
40
  var import_modifiers = require("@dnd-kit/modifiers");
41
41
  var import_framer_motion4 = require("framer-motion");
42
42
 
@@ -128,7 +128,8 @@ var CalendarHeader = ({
128
128
  variant: "ghost",
129
129
  size: "icon",
130
130
  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",
131
- onClick: onMenuClick
131
+ onClick: onMenuClick,
132
+ "aria-label": translations.toggleSidebar
132
133
  },
133
134
  /* @__PURE__ */ import_react.default.createElement(import_lucide_react.Menu, { className: "h-5 w-5" })
134
135
  ), /* @__PURE__ */ import_react.default.createElement(
@@ -145,7 +146,8 @@ var CalendarHeader = ({
145
146
  variant: "ghost",
146
147
  size: "icon",
147
148
  onClick: onPrev,
148
- className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200"
149
+ className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200",
150
+ "aria-label": translations.previous
149
151
  },
150
152
  /* @__PURE__ */ import_react.default.createElement(import_lucide_react.ChevronLeft, { className: "h-4 w-4 text-muted-foreground" })
151
153
  ), /* @__PURE__ */ import_react.default.createElement(
@@ -154,7 +156,8 @@ var CalendarHeader = ({
154
156
  variant: "ghost",
155
157
  size: "icon",
156
158
  onClick: onNext,
157
- className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200"
159
+ className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200",
160
+ "aria-label": translations.next
158
161
  },
159
162
  /* @__PURE__ */ import_react.default.createElement(import_lucide_react.ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
160
163
  )), /* @__PURE__ */ import_react.default.createElement("div", { className: "ml-2 md:ml-4" }, /* @__PURE__ */ import_react.default.createElement("h2", { className: "text-lg md:text-xl font-semibold text-foreground whitespace-nowrap capitalize tracking-tight" }, (0, import_date_fns.format)(currentDate, "MMMM yyyy", { locale }))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 md:gap-3 w-full md:w-auto justify-end" }, onLanguageChange && language && /* @__PURE__ */ import_react.default.createElement(
@@ -163,6 +166,7 @@ var CalendarHeader = ({
163
166
  variant: "ghost",
164
167
  size: "sm",
165
168
  onClick: () => onLanguageChange(language === "en" ? "fr" : "en"),
169
+ "aria-label": translations.switchLanguage,
166
170
  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"
167
171
  },
168
172
  language
@@ -172,7 +176,8 @@ var CalendarHeader = ({
172
176
  variant: "ghost",
173
177
  size: "icon",
174
178
  className: "rounded-xl h-9 w-9 hover:bg-accent/80 transition-all duration-200",
175
- onClick: onThemeToggle
179
+ onClick: onThemeToggle,
180
+ "aria-label": translations.toggleTheme
176
181
  },
177
182
  isDarkMode ? /* @__PURE__ */ import_react.default.createElement(import_lucide_react.Sun, { className: "h-4 w-4 text-amber-500" }) : /* @__PURE__ */ import_react.default.createElement(import_lucide_react.Moon, { className: "h-4 w-4 text-muted-foreground" })
178
183
  ), !hideViewSwitcher && /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center bg-muted/50 backdrop-blur-sm rounded-xl p-1" }, viewConfig.map(({ key, icon: Icon }) => /* @__PURE__ */ import_react.default.createElement(
@@ -182,6 +187,8 @@ var CalendarHeader = ({
182
187
  variant: "ghost",
183
188
  size: "sm",
184
189
  onClick: () => onViewChange(key),
190
+ "aria-pressed": view === key,
191
+ "aria-label": translations[key],
185
192
  className: cn(
186
193
  "h-8 px-3 text-xs rounded-lg transition-all duration-200 gap-1.5",
187
194
  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"
@@ -226,7 +233,8 @@ var MiniCalendar = ({
226
233
  onDateChange,
227
234
  onViewChange,
228
235
  className,
229
- locale
236
+ locale,
237
+ labels
230
238
  }) => {
231
239
  const [viewDate, setViewDate] = import_react2.default.useState(currentDate);
232
240
  import_react2.default.useEffect(() => {
@@ -264,7 +272,7 @@ var MiniCalendar = ({
264
272
  size: "icon",
265
273
  className: "h-7 w-7 rounded-md hover:bg-background/80 transition-all",
266
274
  onClick: handlePrev,
267
- "aria-label": "Previous month"
275
+ "aria-label": labels?.previousMonth || "Previous month"
268
276
  },
269
277
  /* @__PURE__ */ import_react2.default.createElement(import_lucide_react2.ChevronLeft, { className: "h-4 w-4" })
270
278
  ), /* @__PURE__ */ import_react2.default.createElement(
@@ -274,7 +282,7 @@ var MiniCalendar = ({
274
282
  size: "icon",
275
283
  className: "h-7 w-7 rounded-md hover:bg-background/80 transition-all",
276
284
  onClick: handleNext,
277
- "aria-label": "Next month"
285
+ "aria-label": labels?.nextMonth || "Next month"
278
286
  },
279
287
  /* @__PURE__ */ import_react2.default.createElement(import_lucide_react2.ChevronRight, { className: "h-4 w-4" })
280
288
  ))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "grid grid-cols-7 gap-y-2 text-center mb-2" }, weekDays.map((day, i) => /* @__PURE__ */ import_react2.default.createElement("div", { key: `${day}-${i}`, className: "text-[10px] text-muted-foreground/70 font-semibold uppercase" }, day))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "grid grid-cols-7 gap-y-1 text-center" }, days.map((day) => {
@@ -374,7 +382,50 @@ var en = {
374
382
  allCaughtUp: "All caught up!",
375
383
  noEventsScheduled: "No events scheduled",
376
384
  noUpcoming: "Your schedule is clear",
377
- noUpcomingHint: "No upcoming events to show. Create a new event to start planning."
385
+ noUpcomingHint: "No upcoming events to show. Create a new event to start planning.",
386
+ newEvent: "New Event",
387
+ saveChanges: "Save Changes",
388
+ close: "Close",
389
+ noTitle: "(No title)",
390
+ openInMaps: "Open in maps",
391
+ notesLabel: "Notes",
392
+ addNotes: "Add description or notes...",
393
+ attachments: "Attachments",
394
+ reminders: "Reminders",
395
+ add: "Add",
396
+ calendar: "Calendar",
397
+ select: "Select",
398
+ addLocation: "Add location",
399
+ guestSingular: "Guest",
400
+ addGuestPlaceholder: "Add a guest email and press Enter",
401
+ invalidEmail: "Enter a valid email address",
402
+ removeGuest: "Remove {email}",
403
+ reminderAtTime: "At time of event",
404
+ reminderMinutes: "{n} minutes before",
405
+ reminderHour: "1 hour before",
406
+ reminderHours: "{n} hours before",
407
+ reminderDay: "1 day before",
408
+ reminderDays: "{n} days before",
409
+ reminderWeek: "1 week before",
410
+ removeReminder: "Remove reminder",
411
+ durationMinutes: "{n} min",
412
+ durationHours: "{n} hr",
413
+ durationHoursMinutes: "{h} hr {m} min",
414
+ moreEvents: "+{n} more",
415
+ idLabel: "ID: {id}",
416
+ previous: "Previous",
417
+ next: "Next",
418
+ previousMonth: "Previous month",
419
+ nextMonth: "Next month",
420
+ toggleSidebar: "Toggle sidebar",
421
+ toggleTheme: "Toggle dark mode",
422
+ switchLanguage: "Switch language",
423
+ eventColor: "Event color",
424
+ showLess: "Show less",
425
+ continuesBefore: "Started earlier",
426
+ continuesAfter: "Continues later",
427
+ durationDay: "1 day",
428
+ durationDays: "{n} days"
378
429
  };
379
430
  var fr = {
380
431
  today: "Aujourd'hui",
@@ -443,7 +494,50 @@ var fr = {
443
494
  allCaughtUp: "Tout est \xE0 jour !",
444
495
  noEventsScheduled: "Aucun \xE9v\xE9nement pr\xE9vu",
445
496
  noUpcoming: "Votre planning est libre",
446
- noUpcomingHint: "Aucun \xE9v\xE9nement \xE0 venir. Cr\xE9ez un nouvel \xE9v\xE9nement pour commencer \xE0 planifier."
497
+ noUpcomingHint: "Aucun \xE9v\xE9nement \xE0 venir. Cr\xE9ez un nouvel \xE9v\xE9nement pour commencer \xE0 planifier.",
498
+ newEvent: "Nouvel \xE9v\xE9nement",
499
+ saveChanges: "Enregistrer",
500
+ close: "Fermer",
501
+ noTitle: "(Sans titre)",
502
+ openInMaps: "Ouvrir dans Maps",
503
+ notesLabel: "Notes",
504
+ addNotes: "Ajouter une description ou des notes\u2026",
505
+ attachments: "Pi\xE8ces jointes",
506
+ reminders: "Rappels",
507
+ add: "Ajouter",
508
+ calendar: "Calendrier",
509
+ select: "Choisir",
510
+ addLocation: "Ajouter un lieu",
511
+ guestSingular: "Invit\xE9",
512
+ addGuestPlaceholder: "Ajoutez l'e-mail d'un invit\xE9 puis Entr\xE9e",
513
+ invalidEmail: "Saisissez une adresse e-mail valide",
514
+ removeGuest: "Retirer {email}",
515
+ reminderAtTime: "Au moment de l'\xE9v\xE9nement",
516
+ reminderMinutes: "{n} minutes avant",
517
+ reminderHour: "1 heure avant",
518
+ reminderHours: "{n} heures avant",
519
+ reminderDay: "1 jour avant",
520
+ reminderDays: "{n} jours avant",
521
+ reminderWeek: "1 semaine avant",
522
+ removeReminder: "Supprimer le rappel",
523
+ durationMinutes: "{n} min",
524
+ durationHours: "{n} h",
525
+ durationHoursMinutes: "{h} h {m} min",
526
+ moreEvents: "+{n} de plus",
527
+ idLabel: "ID : {id}",
528
+ previous: "Pr\xE9c\xE9dent",
529
+ next: "Suivant",
530
+ previousMonth: "Mois pr\xE9c\xE9dent",
531
+ nextMonth: "Mois suivant",
532
+ toggleSidebar: "Afficher ou masquer la barre lat\xE9rale",
533
+ toggleTheme: "Basculer le th\xE8me sombre",
534
+ switchLanguage: "Changer de langue",
535
+ eventColor: "Couleur de l'\xE9v\xE9nement",
536
+ showLess: "R\xE9duire",
537
+ continuesBefore: "A commenc\xE9 avant",
538
+ continuesAfter: "Continue apr\xE8s",
539
+ durationDay: "1 jour",
540
+ durationDays: "{n} jours"
447
541
  };
448
542
 
449
543
  // src/core/format.ts
@@ -486,7 +580,18 @@ function timeZoneAbbreviation(date, timeZone) {
486
580
  }
487
581
  }
488
582
  function resolveTranslations(language, overrides) {
489
- return { ...language === "fr" ? fr : en, ...overrides };
583
+ const defined = Object.fromEntries(Object.entries(overrides ?? {}).filter(([, value]) => value !== void 0));
584
+ return { ...language === "fr" ? fr : en, ...defined };
585
+ }
586
+ function interpolate(template, values) {
587
+ return template.replace(/\{(\w+)\}/g, (match, key) => key in values ? String(values[key]) : match);
588
+ }
589
+
590
+ // src/core/color.ts
591
+ var SAFE_COLOR = /^[#\w\s%.,/()+-]+$/;
592
+ var FORBIDDEN = /url\(|expression\(/i;
593
+ function safeColor(value, fallback) {
594
+ return value && SAFE_COLOR.test(value.trim()) && !FORBIDDEN.test(value) ? value.trim() : fallback;
490
595
  }
491
596
 
492
597
  // src/components/Sidebar.tsx
@@ -514,12 +619,6 @@ var Sidebar = ({
514
619
  const timer = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
515
620
  return () => clearInterval(timer);
516
621
  }, []);
517
- const defaultCalendars = [
518
- { id: "1", label: "My Calendar", color: "#3b82f6", active: true },
519
- { id: "2", label: "Birthdays", color: "#10b981", active: true },
520
- { id: "3", label: "Tasks", color: "#6366f1", active: true }
521
- ];
522
- const displayCalendars = calendars || defaultCalendars;
523
622
  const getAcronym = (tz) => !tz || !now ? "LOC" : timeZoneAbbreviation(now, tz);
524
623
  const timezones = [
525
624
  { value: "", label: translations?.localTime || "Local Time", acronym: "LOC" },
@@ -569,7 +668,16 @@ var Sidebar = ({
569
668
  },
570
669
  /* @__PURE__ */ import_react3.default.createElement(import_lucide_react3.Plus, { className: "w-5 h-5" }),
571
670
  /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-sm" }, translations?.create || "Create")
572
- )), /* @__PURE__ */ import_react3.default.createElement(MiniCalendar, { currentDate, onDateChange, onViewChange, locale }), /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex-1 px-4 space-y-5 mt-5" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "bg-muted/20 rounded-2xl p-3 border-[0px] border-border/30" }, /* @__PURE__ */ import_react3.default.createElement(
671
+ )), /* @__PURE__ */ import_react3.default.createElement(
672
+ MiniCalendar,
673
+ {
674
+ currentDate,
675
+ onDateChange,
676
+ onViewChange,
677
+ locale,
678
+ labels: { previousMonth: translations?.previousMonth, nextMonth: translations?.nextMonth }
679
+ }
680
+ ), /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex-1 px-4 space-y-5 mt-5" }, calendars && calendars.length > 0 && /* @__PURE__ */ import_react3.default.createElement("div", { className: "bg-muted/20 rounded-2xl p-3 border-[0px] border-border/30" }, /* @__PURE__ */ import_react3.default.createElement(
573
681
  "div",
574
682
  {
575
683
  className: "flex items-center justify-between cursor-pointer hover:bg-accent/50 p-2 -m-1 rounded-xl mb-2 transition-all duration-200",
@@ -577,41 +685,40 @@ var Sidebar = ({
577
685
  },
578
686
  /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-sm font-semibold text-foreground" }, translations?.calendars || "Calendars"),
579
687
  /* @__PURE__ */ import_react3.default.createElement(import_lucide_react3.ChevronDown, { className: cn("w-4 h-4 text-muted-foreground transition-transform duration-200", calendarsOpen && "rotate-180") })
580
- ), calendarsOpen && /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-1" }, displayCalendars.map((cal) => /* @__PURE__ */ import_react3.default.createElement(
688
+ ), calendarsOpen && /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-1" }, calendars.map((cal) => /* @__PURE__ */ import_react3.default.createElement(
581
689
  "div",
582
690
  {
583
691
  key: cal.id,
584
692
  className: "flex items-center gap-3 py-2 px-2 hover:bg-accent/60 rounded-xl cursor-pointer group transition-all duration-200",
585
693
  onClick: () => onCalendarToggle?.(cal.id, !(cal.active ?? true))
586
694
  },
587
- /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative flex items-center justify-center" }, /* @__PURE__ */ import_react3.default.createElement(
588
- "input",
695
+ /* @__PURE__ */ import_react3.default.createElement(
696
+ "div",
589
697
  {
590
- type: "checkbox",
591
- checked: cal.active ?? true,
592
- onChange: (e) => {
593
- e.stopPropagation();
594
- onCalendarToggle?.(cal.id, e.target.checked);
595
- },
596
- className: "peer h-5 w-5 rounded-md border-2 border-border/60 cursor-pointer appearance-none checked:border-transparent transition-all duration-200",
597
- style: { "--primary-color": cal.color },
598
- "data-cal-id": cal.id
599
- }
600
- ), /* @__PURE__ */ import_react3.default.createElement("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none opacity-0 peer-checked:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "w-3.5 h-3.5 text-white", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3 }, /* @__PURE__ */ import_react3.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }))), /* @__PURE__ */ import_react3.default.createElement("style", null, `
601
- input[type="checkbox"][data-cal-id="${cal.id}"]:checked {
602
- background-color: ${cal.color} !important;
603
- border-color: ${cal.color} !important;
604
- }
605
- input[type="checkbox"][data-cal-id="${cal.id}"]:focus {
606
- --tw-ring-color: ${cal.color}40 !important;
607
- }
608
- `)),
698
+ className: "relative flex items-center justify-center",
699
+ style: { "--cal-color": safeColor(cal.color, "hsl(var(--primary))") }
700
+ },
701
+ /* @__PURE__ */ import_react3.default.createElement(
702
+ "input",
703
+ {
704
+ type: "checkbox",
705
+ checked: cal.active ?? true,
706
+ onChange: (e) => {
707
+ e.stopPropagation();
708
+ onCalendarToggle?.(cal.id, e.target.checked);
709
+ },
710
+ "aria-label": cal.label,
711
+ 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"
712
+ }
713
+ ),
714
+ /* @__PURE__ */ import_react3.default.createElement("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none opacity-0 peer-checked:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "w-3.5 h-3.5 text-white", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3 }, /* @__PURE__ */ import_react3.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" })))
715
+ ),
609
716
  /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex items-center gap-2 flex-1 min-w-0" }, /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-sm text-foreground/90 truncate font-medium" }, cal.label)),
610
717
  /* @__PURE__ */ import_react3.default.createElement(
611
718
  "div",
612
719
  {
613
720
  className: "w-2 h-2 rounded-full opacity-60 group-hover:opacity-100 transition-opacity",
614
- style: { backgroundColor: cal.color }
721
+ style: { backgroundColor: safeColor(cal.color, "hsl(var(--primary))") }
615
722
  }
616
723
  )
617
724
  ))))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "mt-auto px-4 pt-5" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "bg-muted/20 rounded-2xl p-3" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex items-center gap-2 mb-3" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "p-1.5 bg-primary/10 rounded-lg" }, /* @__PURE__ */ import_react3.default.createElement(import_lucide_react3.Globe, { className: "w-4 h-4 text-primary" })), /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-sm font-semibold text-foreground" }, translations?.timezone || "Timezone")), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react3.default.createElement(
@@ -640,10 +747,13 @@ var Sidebar = ({
640
747
  };
641
748
 
642
749
  // src/views/MonthView.tsx
643
- var import_react6 = __toESM(require("react"));
644
- var import_date_fns8 = require("date-fns");
750
+ var import_react7 = __toESM(require("react"));
751
+ var import_date_fns10 = require("date-fns");
645
752
 
646
753
  // src/core/events.ts
754
+ var import_date_fns8 = require("date-fns");
755
+
756
+ // src/core/allDay.ts
647
757
  var import_date_fns7 = require("date-fns");
648
758
 
649
759
  // src/core/timezone.ts
@@ -704,6 +814,91 @@ function displayToday(tz, now = /* @__PURE__ */ new Date()) {
704
814
  return (0, import_date_fns6.startOfDay)(toDisplay(now, tz));
705
815
  }
706
816
 
817
+ // src/core/allDay.ts
818
+ var DAY_EVENT_MIN_MS = 24 * 60 * 60 * 1e3;
819
+ function isDayEvent(event) {
820
+ return event.allDay === true || event.end.getTime() - event.start.getTime() >= DAY_EVENT_MIN_MS;
821
+ }
822
+ var isMidnight = (date) => date.getHours() === 0 && date.getMinutes() === 0 && date.getSeconds() === 0 && date.getMilliseconds() === 0;
823
+ var isUtcMidnight = (date) => date.getUTCHours() === 0 && date.getUTCMinutes() === 0 && date.getUTCSeconds() === 0 && date.getUTCMilliseconds() === 0;
824
+ function toCalendarMidnight(date) {
825
+ return !isMidnight(date) && isUtcMidnight(date) ? new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) : date;
826
+ }
827
+ function calendarDay(date) {
828
+ if (isMidnight(date)) return { day: (0, import_date_fns7.startOfDay)(date), midnight: true };
829
+ if (isUtcMidnight(date)) return { day: new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()), midnight: true };
830
+ return { day: (0, import_date_fns7.startOfDay)(date), midnight: false };
831
+ }
832
+ function dayEventSpan(event, tz) {
833
+ if (event.allDay) {
834
+ const firstDay2 = calendarDay(event.start).day;
835
+ if (event.end.getTime() <= event.start.getTime()) return { firstDay: firstDay2, lastDay: firstDay2 };
836
+ const end = calendarDay(event.end);
837
+ const lastDay2 = end.midnight ? (0, import_date_fns7.addDays)(end.day, -1) : end.day;
838
+ return { firstDay: firstDay2, lastDay: lastDay2 < firstDay2 ? firstDay2 : lastDay2 };
839
+ }
840
+ const firstDay = (0, import_date_fns7.startOfDay)(toDisplay(event.start, tz));
841
+ const lastDay = (0, import_date_fns7.startOfDay)(toDisplay(new Date(event.end.getTime() - 1), tz));
842
+ return { firstDay, lastDay: lastDay < firstDay ? firstDay : lastDay };
843
+ }
844
+ var partitionCache = /* @__PURE__ */ new WeakMap();
845
+ function partitionDayEvents(events, tz) {
846
+ let byZone = partitionCache.get(events);
847
+ if (!byZone) {
848
+ byZone = /* @__PURE__ */ new Map();
849
+ partitionCache.set(events, byZone);
850
+ }
851
+ const key = tz ?? "";
852
+ let result = byZone.get(key);
853
+ if (!result) {
854
+ const dayEvents = [];
855
+ const timedEvents = [];
856
+ for (const event of events) (isDayEvent(event) ? dayEvents : timedEvents).push(event);
857
+ result = { dayEvents, timedEvents };
858
+ byZone.set(key, result);
859
+ }
860
+ return result;
861
+ }
862
+ var rowCache = /* @__PURE__ */ new WeakMap();
863
+ function layoutDayRow(days, dayEvents, tz) {
864
+ if (days.length === 0) return { segments: [], laneCount: 0 };
865
+ const rowStart = (0, import_date_fns7.startOfDay)(days[0]);
866
+ const columns = days.length;
867
+ const key = `${tz ?? ""}|${rowStart.getTime()}|${columns}`;
868
+ let cache = rowCache.get(dayEvents);
869
+ if (!cache) {
870
+ cache = /* @__PURE__ */ new Map();
871
+ rowCache.set(dayEvents, cache);
872
+ }
873
+ const cached = cache.get(key);
874
+ if (cached) return cached;
875
+ const unplaced = [];
876
+ for (const event of dayEvents) {
877
+ const { firstDay, lastDay } = dayEventSpan(event, tz);
878
+ const first = (0, import_date_fns7.differenceInCalendarDays)(firstDay, rowStart);
879
+ const last = (0, import_date_fns7.differenceInCalendarDays)(lastDay, rowStart);
880
+ if (last < 0 || first >= columns) continue;
881
+ const startCol = Math.max(first, 0);
882
+ const endCol = Math.min(last, columns - 1);
883
+ unplaced.push({ event, startCol, span: endCol - startCol + 1, continuesBefore: first < 0, continuesAfter: last >= columns });
884
+ }
885
+ 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));
886
+ const occupied = [];
887
+ const segments = [];
888
+ for (const segment of unplaced) {
889
+ let lane = occupied.findIndex((row) => row.slice(segment.startCol, segment.startCol + segment.span).every((taken) => !taken));
890
+ if (lane === -1) {
891
+ lane = occupied.length;
892
+ occupied.push(new Array(columns).fill(false));
893
+ }
894
+ for (let c = segment.startCol; c < segment.startCol + segment.span; c++) occupied[lane][c] = true;
895
+ segments.push({ ...segment, lane });
896
+ }
897
+ const layout = { segments, laneCount: occupied.length };
898
+ cache.set(key, layout);
899
+ return layout;
900
+ }
901
+
707
902
  // src/core/events.ts
708
903
  var toDate = (value) => value === void 0 || value === null ? void 0 : value instanceof Date ? value : new Date(value);
709
904
  var isValidDate = (date) => !!date && !Number.isNaN(date.getTime());
@@ -712,29 +907,35 @@ var normalizedList = /* @__PURE__ */ new WeakMap();
712
907
  function normalizeEvent(event) {
713
908
  const cached = normalizedEvent.get(event);
714
909
  if (cached !== void 0) return cached;
715
- const start = toDate(event.start);
716
- const end = toDate(event.end);
910
+ const day = (value) => event.allDay && value ? toCalendarMidnight(value) : value;
911
+ const start = day(toDate(event.start));
912
+ const end = day(toDate(event.end));
717
913
  let result = null;
718
914
  if (!isValidDate(start) || !isValidDate(end)) {
719
915
  warnOnce(`invalid-date:${event.id}`, `Event "${event.id}" has an invalid start or end date and was skipped.`);
720
916
  } else if (end.getTime() < start.getTime()) {
721
917
  warnOnce(`end-before-start:${event.id}`, `Event "${event.id}" ends before it starts and was skipped.`);
722
918
  } else {
723
- const needsCopy = start !== event.start || end !== event.end || needsRecurrenceCopy(event);
919
+ const needsCopy = start !== event.start || end !== event.end || needsRecurrenceCopy(event) || !!event.allDay && dateOnlyRecurrence(event);
724
920
  result = needsCopy ? {
725
921
  ...event,
726
922
  start,
727
923
  end,
728
924
  recurrence: event.recurrence && {
729
925
  ...event.recurrence,
730
- until: toDate(event.recurrence.until),
731
- exdates: event.recurrence.exdates?.map((d) => toDate(d))
926
+ until: day(toDate(event.recurrence.until)),
927
+ exdates: event.recurrence.exdates?.map((d) => day(toDate(d)))
732
928
  }
733
929
  } : event;
734
930
  }
735
931
  normalizedEvent.set(event, result);
736
932
  return result;
737
933
  }
934
+ function dateOnlyRecurrence(event) {
935
+ const r = event.recurrence;
936
+ const changes = (d) => d instanceof Date && toCalendarMidnight(d) !== d;
937
+ return !!r && (changes(r.until) || !!r.exdates?.some(changes));
938
+ }
738
939
  function needsRecurrenceCopy(event) {
739
940
  const r = event.recurrence;
740
941
  if (!r) return false;
@@ -757,7 +958,7 @@ function normalizeEvents(events) {
757
958
  normalizedList.set(events, result);
758
959
  return result;
759
960
  }
760
- var dayKey = (wall) => (0, import_date_fns7.format)(wall, "yyyy-MM-dd");
961
+ var dayKey = (wall) => (0, import_date_fns8.format)(wall, "yyyy-MM-dd");
761
962
  function memoByZone(cache, events, tz, compute) {
762
963
  let byZone = cache.get(events);
763
964
  if (!byZone) {
@@ -795,10 +996,10 @@ function segmentsByDisplayDay(events, tz, range) {
795
996
  const rawEnd = toDisplay(event.end, tz);
796
997
  const wallEnd = rawEnd < wallStart ? wallStart : rawEnd;
797
998
  if (range && (wallEnd < range.start || wallStart >= range.end)) continue;
798
- let day = (0, import_date_fns7.startOfDay)(range && wallStart < range.start ? range.start : wallStart);
999
+ let day = (0, import_date_fns8.startOfDay)(range && wallStart < range.start ? range.start : wallStart);
799
1000
  const stop = range && wallEnd > range.end ? range.end : wallEnd;
800
1001
  do {
801
- const next = (0, import_date_fns7.addDays)(day, 1);
1002
+ const next = (0, import_date_fns8.addDays)(day, 1);
802
1003
  const start = wallStart > day ? wallStart : day;
803
1004
  const end = wallEnd < next ? wallEnd : next;
804
1005
  if (end > start || wallStart.getTime() === wallEnd.getTime()) {
@@ -815,25 +1016,153 @@ function segmentsByDisplayDay(events, tz, range) {
815
1016
  });
816
1017
  }
817
1018
 
818
- // src/components/dnd/DraggableEvent.tsx
1019
+ // src/components/AllDayBar.tsx
819
1020
  var import_react4 = __toESM(require("react"));
820
1021
  var import_core = require("@dnd-kit/core");
821
1022
  var import_utilities = require("@dnd-kit/utilities");
1023
+ var import_date_fns9 = require("date-fns");
1024
+ var AllDayBarImpl = ({
1025
+ segment,
1026
+ rowDays,
1027
+ laneHeight,
1028
+ timezone,
1029
+ locale,
1030
+ translations,
1031
+ readonly,
1032
+ onEventClick,
1033
+ onEventContextMenu,
1034
+ onDayEventResize
1035
+ }) => {
1036
+ const { event, startCol, span, lane, continuesBefore, continuesAfter } = segment;
1037
+ const columns = rowDays.length;
1038
+ const { firstDay, lastDay } = dayEventSpan(event, timezone);
1039
+ const segmentOffset = (0, import_date_fns9.differenceInCalendarDays)(rowDays[startCol], firstDay);
1040
+ const dragData = (0, import_react4.useRef)({ event, grabDayOffset: segmentOffset });
1041
+ dragData.current.event = event;
1042
+ const dragDisabled = readonly || isEventDragDisabled(event);
1043
+ const { attributes, listeners, setNodeRef, transform, isDragging } = (0, import_core.useDraggable)({
1044
+ id: `${event.id}@day@${(0, import_date_fns9.format)(rowDays[0], "yyyy-MM-dd")}`,
1045
+ data: dragData.current,
1046
+ disabled: dragDisabled
1047
+ });
1048
+ const [resizeCols, setResizeCols] = (0, import_react4.useState)(0);
1049
+ const ignoreClick = (0, import_react4.useRef)(false);
1050
+ const canResize = !readonly && !continuesAfter && !isEventResizeDisabled(event) && !!onDayEventResize;
1051
+ const shownSpan = Math.max(1, Math.min(span + resizeCols, columns - startCol));
1052
+ const handlePointerDownCapture = (e) => {
1053
+ const rect = e.currentTarget.getBoundingClientRect();
1054
+ const dayWithin = rect.width > 0 ? Math.floor((e.clientX - rect.left) / rect.width * span) : 0;
1055
+ dragData.current.grabDayOffset = segmentOffset + Math.min(Math.max(dayWithin, 0), span - 1);
1056
+ };
1057
+ const handleResizeStart = (e) => {
1058
+ e.stopPropagation();
1059
+ e.preventDefault();
1060
+ const bar = e.currentTarget.parentElement;
1061
+ const columnWidth = bar.getBoundingClientRect().width / span || 1;
1062
+ const startX = e.clientX;
1063
+ let delta = 0;
1064
+ const onMove = (moveEvent) => {
1065
+ delta = Math.round((moveEvent.clientX - startX) / columnWidth);
1066
+ setResizeCols(delta);
1067
+ };
1068
+ const stop = () => {
1069
+ document.removeEventListener("pointermove", onMove);
1070
+ document.removeEventListener("pointerup", onUp);
1071
+ document.removeEventListener("pointercancel", stop);
1072
+ setResizeCols(0);
1073
+ };
1074
+ const onUp = () => {
1075
+ stop();
1076
+ ignoreClick.current = true;
1077
+ setTimeout(() => {
1078
+ ignoreClick.current = false;
1079
+ }, 0);
1080
+ if (delta !== 0) onDayEventResize?.(event, (0, import_date_fns9.addDays)(rowDays[startCol + span - 1], delta));
1081
+ };
1082
+ document.addEventListener("pointermove", onMove);
1083
+ document.addEventListener("pointerup", onUp);
1084
+ document.addEventListener("pointercancel", stop);
1085
+ };
1086
+ const color = event.color || "hsl(var(--primary))";
1087
+ const dateFormat = "d MMM";
1088
+ const label = `${event.title}, ${(0, import_date_fns9.format)(firstDay, dateFormat, { locale })}${lastDay > firstDay ? ` \u2013 ${(0, import_date_fns9.format)(lastDay, dateFormat, { locale })}` : ""}`;
1089
+ return /* @__PURE__ */ import_react4.default.createElement(
1090
+ "div",
1091
+ {
1092
+ ref: setNodeRef,
1093
+ ...listeners,
1094
+ ...attributes,
1095
+ onPointerDownCapture: handlePointerDownCapture,
1096
+ role: "button",
1097
+ "aria-label": label,
1098
+ className: cn(
1099
+ "group absolute px-[2px] select-none",
1100
+ dragDisabled ? "cursor-pointer" : "cursor-grab active:cursor-grabbing touch-none"
1101
+ ),
1102
+ style: {
1103
+ left: `${startCol / columns * 100}%`,
1104
+ width: `${shownSpan / columns * 100}%`,
1105
+ top: lane * laneHeight,
1106
+ height: laneHeight,
1107
+ transform: import_utilities.CSS.Translate.toString(transform),
1108
+ opacity: isDragging ? 0 : void 0,
1109
+ zIndex: isDragging ? 100 : 1
1110
+ },
1111
+ onClick: (e) => {
1112
+ e.stopPropagation();
1113
+ if (ignoreClick.current) {
1114
+ ignoreClick.current = false;
1115
+ return;
1116
+ }
1117
+ onEventClick?.(event);
1118
+ },
1119
+ onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0
1120
+ },
1121
+ /* @__PURE__ */ import_react4.default.createElement(
1122
+ "div",
1123
+ {
1124
+ className: cn(
1125
+ "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",
1126
+ continuesBefore ? "rounded-l-none" : "rounded-l-md",
1127
+ continuesAfter ? "rounded-r-none" : "rounded-r-md"
1128
+ ),
1129
+ style: { backgroundColor: color }
1130
+ },
1131
+ continuesBefore && /* @__PURE__ */ import_react4.default.createElement("span", { "aria-label": translations?.continuesBefore }, "\u2039"),
1132
+ /* @__PURE__ */ import_react4.default.createElement("span", { className: "truncate" }, event.title),
1133
+ continuesAfter && /* @__PURE__ */ import_react4.default.createElement("span", { className: "ml-auto", "aria-label": translations?.continuesAfter }, "\u203A"),
1134
+ canResize && /* @__PURE__ */ import_react4.default.createElement(
1135
+ "div",
1136
+ {
1137
+ "data-testid": "all-day-resize",
1138
+ className: "absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize opacity-0 group-hover:opacity-100 bg-black/20",
1139
+ onPointerDown: handleResizeStart
1140
+ }
1141
+ )
1142
+ )
1143
+ );
1144
+ };
1145
+ var AllDayBar = import_react4.default.memo(AllDayBarImpl);
1146
+
1147
+ // src/components/dnd/DraggableEvent.tsx
1148
+ var import_react5 = __toESM(require("react"));
1149
+ var import_core2 = require("@dnd-kit/core");
1150
+ var import_utilities2 = require("@dnd-kit/utilities");
822
1151
  var DraggableEventImpl = ({ event, dragId, grabOffsetMs, children, className, style: propStyle, ...props }) => {
823
1152
  const dragDisabled = isEventDragDisabled(event);
824
- const { attributes, listeners, setNodeRef, transform, isDragging } = (0, import_core.useDraggable)({
1153
+ const { attributes, listeners, setNodeRef, transform, isDragging } = (0, import_core2.useDraggable)({
825
1154
  id: dragId ?? event.id,
826
1155
  data: { event, grabOffsetMs },
827
1156
  disabled: dragDisabled
828
1157
  });
829
1158
  const style = {
830
1159
  ...propStyle,
831
- transform: import_utilities.CSS.Translate.toString(transform),
1160
+ transform: import_utilities2.CSS.Translate.toString(transform),
832
1161
  zIndex: isDragging ? 100 : propStyle?.zIndex,
833
1162
  // Hide the original while dragging: the DragOverlay ghost is what the user follows.
834
1163
  opacity: isDragging ? 0 : propStyle?.opacity
835
1164
  };
836
- return /* @__PURE__ */ import_react4.default.createElement(
1165
+ return /* @__PURE__ */ import_react5.default.createElement(
837
1166
  "div",
838
1167
  {
839
1168
  ref: setNodeRef,
@@ -846,11 +1175,11 @@ var DraggableEventImpl = ({ event, dragId, grabOffsetMs, children, className, st
846
1175
  children
847
1176
  );
848
1177
  };
849
- var DraggableEvent = import_react4.default.memo(DraggableEventImpl);
1178
+ var DraggableEvent = import_react5.default.memo(DraggableEventImpl);
850
1179
 
851
1180
  // src/components/dnd/DroppableCell.tsx
852
- var import_react5 = __toESM(require("react"));
853
- var import_core2 = require("@dnd-kit/core");
1181
+ var import_react6 = __toESM(require("react"));
1182
+ var import_core3 = require("@dnd-kit/core");
854
1183
  var QUARTER_HOVER = [
855
1184
  "hover:bg-blue-50/50 dark:hover:bg-blue-900/10",
856
1185
  "hover:bg-blue-50/80 dark:hover:bg-blue-900/20",
@@ -864,13 +1193,13 @@ var QUARTER_ACTIVE = [
864
1193
  "bg-blue-100/80 dark:bg-blue-900/40 ring-2 ring-primary ring-inset"
865
1194
  ];
866
1195
  var quarterOf = (date) => Math.min(3, Math.floor(date.getMinutes() / 15));
867
- var DroppableCellImpl = ({ id, date, resourceId, children, className, style, onClick, onSlotClick }) => {
868
- const { isOver, setNodeRef } = (0, import_core2.useDroppable)({
1196
+ var DroppableCellImpl = ({ id, date, resourceId, allDayRow, children, className, style, onClick, onSlotClick }) => {
1197
+ const { isOver, setNodeRef } = (0, import_core3.useDroppable)({
869
1198
  id,
870
- data: { date, resourceId }
1199
+ data: { date, resourceId, allDayRow }
871
1200
  });
872
1201
  const quarter = quarterOf(date);
873
- return /* @__PURE__ */ import_react5.default.createElement(
1202
+ return /* @__PURE__ */ import_react6.default.createElement(
874
1203
  "div",
875
1204
  {
876
1205
  ref: setNodeRef,
@@ -892,13 +1221,13 @@ var shallowEqualStyle = (a, b) => {
892
1221
  const keys = Object.keys(a);
893
1222
  return keys.length === Object.keys(b).length && keys.every((key) => a[key] === b[key]);
894
1223
  };
895
- var DroppableCell = import_react5.default.memo(
1224
+ var DroppableCell = import_react6.default.memo(
896
1225
  DroppableCellImpl,
897
- (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)
1226
+ (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)
898
1227
  );
899
1228
 
900
1229
  // src/views/MonthView.tsx
901
- var EventItem = import_react6.default.memo(({ event, onEventClick }) => /* @__PURE__ */ import_react6.default.createElement(DraggableEvent, { event }, /* @__PURE__ */ import_react6.default.createElement(
1230
+ var EventItem = import_react7.default.memo(({ event, onEventClick, onEventContextMenu }) => /* @__PURE__ */ import_react7.default.createElement(DraggableEvent, { event }, /* @__PURE__ */ import_react7.default.createElement(
902
1231
  "div",
903
1232
  {
904
1233
  className: cn(
@@ -914,61 +1243,183 @@ var EventItem = import_react6.default.memo(({ event, onEventClick }) => /* @__PU
914
1243
  onClick: (e) => {
915
1244
  e.stopPropagation();
916
1245
  onEventClick?.(event);
917
- }
1246
+ },
1247
+ onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0
918
1248
  },
919
- /* @__PURE__ */ import_react6.default.createElement("span", { className: "font-medium" }, event.title)
1249
+ /* @__PURE__ */ import_react7.default.createElement("span", { className: "font-medium" }, event.title)
920
1250
  )));
921
1251
  EventItem.displayName = "EventItem";
1252
+ var ROW_HEIGHT = 130;
1253
+ var LANE_HEIGHT = 20;
1254
+ var MAX_LANES = 3;
1255
+ var MAX_ITEMS = 4;
1256
+ var BARS_TOP = 38;
1257
+ var CELL_CHROME = 16 + 28 + 6;
1258
+ var ITEM_STEP = 29 + 4;
1259
+ var MORE_HEIGHT = 20;
1260
+ function timedSlots(visibleLanes, timedCount, hiddenBars) {
1261
+ if (visibleLanes === 0) return Math.min(timedCount, MAX_ITEMS);
1262
+ const room = ROW_HEIGHT - CELL_CHROME - visibleLanes * LANE_HEIGHT;
1263
+ if (hiddenBars === 0 && timedCount * ITEM_STEP - 4 <= room) return timedCount;
1264
+ return Math.max(0, Math.floor((room - MORE_HEIGHT) / ITEM_STEP));
1265
+ }
922
1266
  var MonthView = ({
923
1267
  currentDate,
924
1268
  events,
925
1269
  onEventClick,
926
1270
  onDateClick,
927
1271
  timezone,
928
- locale
1272
+ locale,
1273
+ translations,
1274
+ onEventContextMenu,
1275
+ onDayEventResize,
1276
+ readonly
929
1277
  }) => {
930
1278
  const weekStartsOn = resolveWeekStartsOn(locale, 1);
931
- const days = (0, import_react6.useMemo)(() => getMonthGrid(currentDate, weekStartsOn), [currentDate, weekStartsOn]);
932
- const weekDays = (0, import_react6.useMemo)(() => getWeekDays(currentDate, weekStartsOn), [currentDate, weekStartsOn]);
933
- const eventsByDay = eventsByStartDay(events, timezone);
1279
+ const days = (0, import_react7.useMemo)(() => getMonthGrid(currentDate, weekStartsOn), [currentDate, weekStartsOn]);
1280
+ const weekDays = (0, import_react7.useMemo)(() => getWeekDays(currentDate, weekStartsOn), [currentDate, weekStartsOn]);
1281
+ const weeks = (0, import_react7.useMemo)(
1282
+ () => Array.from({ length: Math.ceil(days.length / 7) }, (_, i) => days.slice(i * 7, i * 7 + 7)),
1283
+ [days]
1284
+ );
1285
+ const { dayEvents, timedEvents } = partitionDayEvents(events, timezone);
1286
+ const eventsByDay = eventsByStartDay(timedEvents, timezone);
934
1287
  const today = displayToday(timezone);
935
- return /* @__PURE__ */ import_react6.default.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__ */ import_react6.default.createElement("div", { className: "overflow-y-auto flex-1 relative" }, /* @__PURE__ */ import_react6.default.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__ */ import_react6.default.createElement(
1288
+ return /* @__PURE__ */ import_react7.default.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__ */ import_react7.default.createElement("div", { className: "overflow-y-auto flex-1 relative" }, /* @__PURE__ */ import_react7.default.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__ */ import_react7.default.createElement(
936
1289
  "div",
937
1290
  {
938
1291
  key: day.toISOString(),
939
1292
  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"
940
1293
  },
941
- (0, import_date_fns8.format)(day, "EEE", { locale })
942
- ))), /* @__PURE__ */ import_react6.default.createElement("div", { className: "grid grid-cols-7", style: { gridAutoRows: "130px" } }, days.map((day) => {
943
- const dayKey2 = (0, import_date_fns8.format)(day, "yyyy-MM-dd");
944
- const dayEvents = eventsByDay.get(dayKey2) || [];
945
- const isCurrentMonth = (0, import_date_fns8.isSameMonth)(day, currentDate);
946
- const cellId = day.toISOString();
947
- return /* @__PURE__ */ import_react6.default.createElement(
948
- DroppableCell,
1294
+ (0, import_date_fns10.format)(day, "EEE", { locale })
1295
+ ))), weeks.map((week) => {
1296
+ const { segments, laneCount } = layoutDayRow(week, dayEvents, timezone);
1297
+ const visibleLanes = Math.min(laneCount, MAX_LANES);
1298
+ return /* @__PURE__ */ import_react7.default.createElement("div", { key: week[0].toISOString(), className: "relative grid grid-cols-7", style: { height: ROW_HEIGHT } }, week.map((day, column) => {
1299
+ const dayKey2 = (0, import_date_fns10.format)(day, "yyyy-MM-dd");
1300
+ const dayTimed = eventsByDay.get(dayKey2) || [];
1301
+ const barsOnDay = segments.filter((s) => column >= s.startCol && column < s.startCol + s.span);
1302
+ const hiddenBars = barsOnDay.filter((s) => s.lane >= MAX_LANES).length;
1303
+ const shown = timedSlots(visibleLanes, dayTimed.length, hiddenBars);
1304
+ const hidden = hiddenBars + dayTimed.length - shown;
1305
+ const total = barsOnDay.length + dayTimed.length;
1306
+ const isCurrentMonth = (0, import_date_fns10.isSameMonth)(day, currentDate);
1307
+ const cellId = day.toISOString();
1308
+ return /* @__PURE__ */ import_react7.default.createElement(
1309
+ DroppableCell,
1310
+ {
1311
+ key: cellId,
1312
+ id: cellId,
1313
+ date: day,
1314
+ className: cn(
1315
+ "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",
1316
+ !isCurrentMonth && "bg-muted/5 text-muted-foreground/60",
1317
+ (0, import_date_fns10.isSameDay)(day, today) && "bg-primary/5 ring-1 ring-inset ring-primary/20"
1318
+ ),
1319
+ onClick: () => onDateClick?.(day)
1320
+ },
1321
+ /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: cn(
1322
+ "text-sm font-semibold w-7 h-7 flex items-center justify-center rounded-full transition-all duration-200",
1323
+ (0, import_date_fns10.isSameDay)(day, today) ? "bg-primary text-primary-foreground shadow-md shadow-primary/30" : "group-hover:bg-accent"
1324
+ ) }, (0, import_date_fns10.format)(day, "d", { locale })), total > 0 && /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-[10px] font-medium text-muted-foreground/60 bg-muted/50 px-1.5 py-0.5 rounded-full" }, total)),
1325
+ visibleLanes > 0 && /* @__PURE__ */ import_react7.default.createElement("div", { className: "shrink-0", style: { height: visibleLanes * LANE_HEIGHT - 6 } }),
1326
+ /* @__PURE__ */ import_react7.default.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__ */ import_react7.default.createElement(EventItem, { key: `${event.id}-${dayKey2}`, event, onEventClick, onEventContextMenu })), hidden > 0 && // "+N more" counts hidden bars and hidden timed events, and opens the day.
1327
+ /* @__PURE__ */ import_react7.default.createElement(
1328
+ "button",
1329
+ {
1330
+ type: "button",
1331
+ 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",
1332
+ onClick: (e) => {
1333
+ e.stopPropagation();
1334
+ onDateClick?.(day);
1335
+ }
1336
+ },
1337
+ interpolate(translations?.moreEvents || "+{n} more", { n: hidden })
1338
+ ))
1339
+ );
1340
+ }), /* @__PURE__ */ import_react7.default.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__ */ import_react7.default.createElement("div", { key: `${segment.event.id}-${week[0].toISOString()}`, className: "pointer-events-auto" }, /* @__PURE__ */ import_react7.default.createElement(
1341
+ AllDayBar,
949
1342
  {
950
- key: cellId,
951
- id: cellId,
952
- date: day,
953
- className: cn(
954
- "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",
955
- !isCurrentMonth && "bg-muted/5 text-muted-foreground/60",
956
- (0, import_date_fns8.isSameDay)(day, today) && "bg-primary/5 ring-1 ring-inset ring-primary/20"
957
- ),
958
- onClick: () => onDateClick?.(day)
959
- },
960
- /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: cn(
961
- "text-sm font-semibold w-7 h-7 flex items-center justify-center rounded-full transition-all duration-200",
962
- (0, import_date_fns8.isSameDay)(day, today) ? "bg-primary text-primary-foreground shadow-md shadow-primary/30" : "group-hover:bg-accent"
963
- ) }, (0, import_date_fns8.format)(day, "d", { locale })), dayEvents.length > 0 && /* @__PURE__ */ import_react6.default.createElement("div", { className: "text-[10px] font-medium text-muted-foreground/60 bg-muted/50 px-1.5 py-0.5 rounded-full" }, dayEvents.length)),
964
- /* @__PURE__ */ import_react6.default.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__ */ import_react6.default.createElement(EventItem, { key: `${event.id}-${dayKey2}`, event, onEventClick })), dayEvents.length > 4 && /* @__PURE__ */ import_react6.default.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"))
965
- );
966
- }))));
1343
+ segment,
1344
+ rowDays: week,
1345
+ laneHeight: LANE_HEIGHT,
1346
+ timezone,
1347
+ locale,
1348
+ translations,
1349
+ readonly,
1350
+ onEventClick,
1351
+ onEventContextMenu,
1352
+ onDayEventResize
1353
+ }
1354
+ )))));
1355
+ })));
967
1356
  };
968
1357
 
969
1358
  // src/views/WeekView.tsx
1359
+ var import_react10 = __toESM(require("react"));
1360
+ var import_date_fns13 = require("date-fns");
1361
+
1362
+ // src/components/AllDayRow.tsx
970
1363
  var import_react8 = __toESM(require("react"));
971
- var import_date_fns9 = require("date-fns");
1364
+ var import_date_fns11 = require("date-fns");
1365
+ var LANE_HEIGHT2 = 22;
1366
+ var AllDayRowImpl = ({
1367
+ days,
1368
+ dayEvents,
1369
+ timezone,
1370
+ locale,
1371
+ translations,
1372
+ readonly,
1373
+ gutterClassName,
1374
+ maxLanes = 2,
1375
+ onEventClick,
1376
+ onEventContextMenu,
1377
+ onDayEventResize,
1378
+ onSlotClick
1379
+ }) => {
1380
+ const [expanded, setExpanded] = (0, import_react8.useState)(false);
1381
+ const rowKey = days.length ? (0, import_date_fns11.format)(days[0], "yyyy-MM-dd") : "";
1382
+ (0, import_react8.useEffect)(() => setExpanded(false), [rowKey]);
1383
+ const handleSlotClick = (0, import_react8.useCallback)((day) => onSlotClick?.(day), [onSlotClick]);
1384
+ const { segments, laneCount } = layoutDayRow(days, dayEvents, timezone);
1385
+ const visibleLanes = expanded ? laneCount : Math.min(laneCount, maxLanes);
1386
+ const hidden = segments.filter((segment) => segment.lane >= visibleLanes).length;
1387
+ const height = Math.max(visibleLanes, 1) * LANE_HEIGHT2 + 4;
1388
+ return /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex border-b-[0.5px] border-border/50 bg-background", "data-all-day-row": true }, /* @__PURE__ */ import_react8.default.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__ */ import_react8.default.createElement("span", null, translations?.allDay || "All Day"), laneCount > maxLanes && /* @__PURE__ */ import_react8.default.createElement(
1389
+ "button",
1390
+ {
1391
+ type: "button",
1392
+ className: "text-primary font-semibold hover:underline",
1393
+ onClick: () => setExpanded(!expanded)
1394
+ },
1395
+ expanded ? translations?.showLess || "Show less" : interpolate(translations?.moreEvents || "+{n} more", { n: hidden })
1396
+ )), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-1 relative", style: { height } }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "absolute inset-0 grid", style: { gridTemplateColumns: `repeat(${days.length}, minmax(0, 1fr))` } }, days.map((day, index) => /* @__PURE__ */ import_react8.default.createElement(
1397
+ DroppableCell,
1398
+ {
1399
+ key: day.toISOString(),
1400
+ id: `all-day-${day.toISOString()}`,
1401
+ date: day,
1402
+ allDayRow: true,
1403
+ className: cn("h-full", index > 0 && "border-l-[0.5px] border-border/30"),
1404
+ onSlotClick: readonly || !onSlotClick ? void 0 : handleSlotClick
1405
+ }
1406
+ ))), /* @__PURE__ */ import_react8.default.createElement("div", { className: "absolute inset-x-0 top-0 pointer-events-none", style: { height } }, segments.filter((segment) => segment.lane < visibleLanes).map((segment) => /* @__PURE__ */ import_react8.default.createElement("div", { key: `${segment.event.id}-${rowKey}`, className: "pointer-events-auto" }, /* @__PURE__ */ import_react8.default.createElement(
1407
+ AllDayBar,
1408
+ {
1409
+ segment,
1410
+ rowDays: days,
1411
+ laneHeight: LANE_HEIGHT2,
1412
+ timezone,
1413
+ locale,
1414
+ translations,
1415
+ readonly,
1416
+ onEventClick,
1417
+ onEventContextMenu,
1418
+ onDayEventResize
1419
+ }
1420
+ ))))));
1421
+ };
1422
+ var AllDayRow = import_react8.default.memo(AllDayRowImpl);
972
1423
 
973
1424
  // src/core/layout.ts
974
1425
  var layoutCache = /* @__PURE__ */ new WeakMap();
@@ -1009,9 +1460,10 @@ function layoutDayEvents(segments) {
1009
1460
  }
1010
1461
 
1011
1462
  // src/components/dnd/ResizableEvent.tsx
1012
- var import_react7 = __toESM(require("react"));
1463
+ var import_react9 = __toESM(require("react"));
1013
1464
 
1014
1465
  // src/core/dnd.ts
1466
+ var import_date_fns12 = require("date-fns");
1015
1467
  function computeDrop({ event, overDate, overResourceId, grabOffsetMs = 0, view, tz }) {
1016
1468
  let wallStart;
1017
1469
  if (view === "month") {
@@ -1032,6 +1484,23 @@ function computeResizeEnd(event, deltaMinutes, minDuration = 15) {
1032
1484
  const minEnd = event.start.getTime() + minDuration * 6e4;
1033
1485
  return new Date(Math.max(event.end.getTime() + deltaMinutes * 6e4, minEnd));
1034
1486
  }
1487
+ var DAY_MS = 24 * 60 * 60 * 1e3;
1488
+ var shiftDays = (date, days, event, tz) => event.allDay ? (0, import_date_fns12.addDays)(date, days) : fromDisplay((0, import_date_fns12.addDays)(toDisplay(date, tz), days), tz);
1489
+ function computeDayMove(event, overDay, grabDayOffset, tz) {
1490
+ const { firstDay } = dayEventSpan(event, tz);
1491
+ const days = (0, import_date_fns12.differenceInCalendarDays)((0, import_date_fns12.addDays)((0, import_date_fns12.startOfDay)(overDay), -grabDayOffset), firstDay);
1492
+ if (days === 0) return null;
1493
+ return { start: shiftDays(event.start, days, event, tz), end: shiftDays(event.end, days, event, tz) };
1494
+ }
1495
+ function computeDayResize(event, newLastDay, tz) {
1496
+ const { firstDay, lastDay } = dayEventSpan(event, tz);
1497
+ const target = (0, import_date_fns12.startOfDay)(newLastDay) < firstDay ? firstDay : (0, import_date_fns12.startOfDay)(newLastDay);
1498
+ const days = (0, import_date_fns12.differenceInCalendarDays)(target, lastDay);
1499
+ if (days === 0) return null;
1500
+ if (event.allDay) return (0, import_date_fns12.addDays)(target, 1);
1501
+ const end = new Date(Math.max(shiftDays(event.end, days, event, tz).getTime(), event.start.getTime() + DAY_MS));
1502
+ return end.getTime() === event.end.getTime() ? null : end;
1503
+ }
1035
1504
 
1036
1505
  // src/components/dnd/ResizableEvent.tsx
1037
1506
  var ResizableEvent = ({
@@ -1045,13 +1514,13 @@ var ResizableEvent = ({
1045
1514
  readonly
1046
1515
  }) => {
1047
1516
  const resizeLocked = readonly || isEventResizeDisabled(event);
1048
- const [isResizing, setIsResizing] = (0, import_react7.useState)(false);
1049
- const [resizeHeight, setResizeHeight] = (0, import_react7.useState)(null);
1050
- const containerRef = (0, import_react7.useRef)(null);
1051
- const startYRef = (0, import_react7.useRef)(0);
1052
- const startHeightRef = (0, import_react7.useRef)(0);
1053
- const resizeHeightRef = (0, import_react7.useRef)(null);
1054
- const handleResizeStart = (0, import_react7.useCallback)((e) => {
1517
+ const [isResizing, setIsResizing] = (0, import_react9.useState)(false);
1518
+ const [resizeHeight, setResizeHeight] = (0, import_react9.useState)(null);
1519
+ const containerRef = (0, import_react9.useRef)(null);
1520
+ const startYRef = (0, import_react9.useRef)(0);
1521
+ const startHeightRef = (0, import_react9.useRef)(0);
1522
+ const resizeHeightRef = (0, import_react9.useRef)(null);
1523
+ const handleResizeStart = (0, import_react9.useCallback)((e) => {
1055
1524
  e.preventDefault();
1056
1525
  e.stopPropagation();
1057
1526
  const clientY = "touches" in e ? e.touches[0].clientY : e.clientY;
@@ -1090,10 +1559,10 @@ var ResizableEvent = ({
1090
1559
  document.addEventListener("touchmove", handleMove, { passive: false });
1091
1560
  document.addEventListener("touchend", handleEnd);
1092
1561
  }, [event, hourHeight, minDuration, onResize]);
1093
- const handlePointerDown = (0, import_react7.useCallback)((e) => {
1562
+ const handlePointerDown = (0, import_react9.useCallback)((e) => {
1094
1563
  e.stopPropagation();
1095
1564
  }, []);
1096
- return /* @__PURE__ */ import_react7.default.createElement(
1565
+ return /* @__PURE__ */ import_react9.default.createElement(
1097
1566
  "div",
1098
1567
  {
1099
1568
  ref: containerRef,
@@ -1104,7 +1573,7 @@ var ResizableEvent = ({
1104
1573
  }
1105
1574
  },
1106
1575
  children,
1107
- /* @__PURE__ */ import_react7.default.createElement(
1576
+ /* @__PURE__ */ import_react9.default.createElement(
1108
1577
  "div",
1109
1578
  {
1110
1579
  className: cn(
@@ -1117,12 +1586,12 @@ var ResizableEvent = ({
1117
1586
  onMouseDown: resizeLocked ? void 0 : handleResizeStart,
1118
1587
  onTouchStart: resizeLocked ? void 0 : handleResizeStart
1119
1588
  },
1120
- /* @__PURE__ */ import_react7.default.createElement("div", { className: cn(
1589
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: cn(
1121
1590
  "w-8 h-1 rounded-full transition-all",
1122
1591
  isResizing ? "bg-primary" : "bg-muted-foreground/30 group-hover:bg-primary/50"
1123
1592
  ) })
1124
1593
  ),
1125
- isResizing && /* @__PURE__ */ import_react7.default.createElement("div", { className: "absolute inset-0 border-2 border-primary border-dashed rounded-md pointer-events-none bg-primary/5" })
1594
+ isResizing && /* @__PURE__ */ import_react9.default.createElement("div", { className: "absolute inset-0 border-2 border-primary border-dashed rounded-md pointer-events-none bg-primary/5" })
1126
1595
  );
1127
1596
  };
1128
1597
 
@@ -1144,72 +1613,92 @@ var WeekViewImpl = ({
1144
1613
  onEventResize,
1145
1614
  timezone,
1146
1615
  locale,
1147
- readonly
1616
+ readonly,
1617
+ onEventContextMenu,
1618
+ onDayEventResize,
1619
+ onAllDaySlotClick,
1620
+ translations
1148
1621
  }) => {
1149
- const weekDays = import_react8.default.useMemo(
1622
+ const weekDays = import_react10.default.useMemo(
1150
1623
  () => getWeekDays(currentDate, resolveWeekStartsOn(locale, 1)),
1151
1624
  [currentDate, locale]
1152
1625
  );
1153
- const visibleRange = import_react8.default.useMemo(
1154
- () => ({ start: weekDays[0], end: (0, import_date_fns9.addDays)(weekDays[weekDays.length - 1], 1) }),
1626
+ const visibleRange = import_react10.default.useMemo(
1627
+ () => ({ start: weekDays[0], end: (0, import_date_fns13.addDays)(weekDays[weekDays.length - 1], 1) }),
1155
1628
  [weekDays]
1156
1629
  );
1157
- const scrollContainerRef = import_react8.default.useRef(null);
1158
- const [now, setNow] = import_react8.default.useState(() => /* @__PURE__ */ new Date());
1159
- import_react8.default.useEffect(() => {
1630
+ const scrollContainerRef = import_react10.default.useRef(null);
1631
+ const [now, setNow] = import_react10.default.useState(() => /* @__PURE__ */ new Date());
1632
+ import_react10.default.useEffect(() => {
1160
1633
  const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
1161
1634
  return () => clearInterval(interval);
1162
1635
  }, []);
1163
- import_react8.default.useEffect(() => {
1636
+ import_react10.default.useEffect(() => {
1164
1637
  if (scrollContainerRef.current) {
1165
1638
  const offsetHour = 4;
1166
1639
  scrollContainerRef.current.scrollTop = (toDisplay(/* @__PURE__ */ new Date(), timezone).getHours() - offsetHour) * HOUR_HEIGHT;
1167
1640
  }
1168
1641
  }, [timezone]);
1169
- const segmentsByDay = segmentsByDisplayDay(events, timezone, visibleRange);
1642
+ const { dayEvents, timedEvents } = partitionDayEvents(events, timezone);
1643
+ const segmentsByDay = segmentsByDisplayDay(timedEvents, timezone, visibleRange);
1170
1644
  const today = displayToday(timezone, now);
1171
1645
  const zonedNow = toDisplay(now, timezone);
1172
1646
  const nowTop = minutesSinceDisplayMidnight(now, timezone) / 60 * HOUR_HEIGHT;
1173
- const showsToday = weekDays.some((day) => (0, import_date_fns9.isSameDay)(day, today));
1647
+ const showsToday = weekDays.some((day) => (0, import_date_fns13.isSameDay)(day, today));
1174
1648
  const zone = resolveTimeZone(timezone);
1175
1649
  const zoneLabel = timeZoneAbbreviation(now, zone) || zone || "LOC";
1176
1650
  const formats = timeFormats(locale);
1177
- return /* @__PURE__ */ import_react8.default.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__ */ import_react8.default.createElement(
1651
+ return /* @__PURE__ */ import_react10.default.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__ */ import_react10.default.createElement(
1178
1652
  "div",
1179
1653
  {
1180
1654
  ref: scrollContainerRef,
1181
1655
  className: "flex-1 overflow-y-auto scrollbar-hide relative bg-background scroll-smooth"
1182
1656
  },
1183
- /* @__PURE__ */ import_react8.default.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__ */ import_react8.default.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__ */ import_react8.default.createElement("div", { className: "flex flex-col items-center justify-center leading-tight" }, /* @__PURE__ */ import_react8.default.createElement("span", null, (0, import_date_fns9.format)(zonedNow, "HH:mm")), /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[10px] opacity-75" }, "(", zoneLabel, ")"))), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-1 grid grid-cols-7" }, weekDays.map((day, index) => /* @__PURE__ */ import_react8.default.createElement("div", { key: day.toISOString(), className: cn("py-3 px-2 text-center", index > 0 && "border-l-[0.5px] border-border/30") }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1.5" }, (0, import_date_fns9.format)(day, "EEE", { locale })), /* @__PURE__ */ import_react8.default.createElement("div", { className: cn(
1657
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "sticky top-0 z-20" }, /* @__PURE__ */ import_react10.default.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__ */ import_react10.default.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__ */ import_react10.default.createElement("div", { className: "flex flex-col items-center justify-center leading-tight" }, /* @__PURE__ */ import_react10.default.createElement("span", null, (0, import_date_fns13.format)(zonedNow, "HH:mm")), /* @__PURE__ */ import_react10.default.createElement("span", { className: "text-[10px] opacity-75" }, "(", zoneLabel, ")"))), /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex-1 grid grid-cols-7" }, weekDays.map((day, index) => /* @__PURE__ */ import_react10.default.createElement("div", { key: day.toISOString(), className: cn("py-3 px-2 text-center", index > 0 && "border-l-[0.5px] border-border/30") }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1.5" }, (0, import_date_fns13.format)(day, "EEE", { locale })), /* @__PURE__ */ import_react10.default.createElement("div", { className: cn(
1184
1658
  "w-9 h-9 flex items-center justify-center rounded-xl mx-auto text-sm font-semibold transition-all duration-200",
1185
- (0, import_date_fns9.isSameDay)(day, today) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30 scale-110" : "text-foreground hover:bg-accent/80"
1186
- ) }, (0, import_date_fns9.format)(day, "d", { locale })))))),
1187
- /* @__PURE__ */ import_react8.default.createElement(
1659
+ (0, import_date_fns13.isSameDay)(day, today) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30 scale-110" : "text-foreground hover:bg-accent/80"
1660
+ ) }, (0, import_date_fns13.format)(day, "d", { locale })))))), /* @__PURE__ */ import_react10.default.createElement(
1661
+ AllDayRow,
1662
+ {
1663
+ days: weekDays,
1664
+ dayEvents,
1665
+ timezone,
1666
+ locale,
1667
+ translations,
1668
+ readonly,
1669
+ gutterClassName: "w-16",
1670
+ onEventClick,
1671
+ onEventContextMenu,
1672
+ onDayEventResize,
1673
+ onSlotClick: onAllDaySlotClick
1674
+ }
1675
+ )),
1676
+ /* @__PURE__ */ import_react10.default.createElement(
1188
1677
  "div",
1189
1678
  {
1190
1679
  className: "flex min-w-full relative",
1191
1680
  style: { height: HOURS.length * HOUR_HEIGHT }
1192
1681
  },
1193
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-none w-16 border-r-[0.5px] border-border/30 relative bg-muted/5" }, HOURS.map((hour) => /* @__PURE__ */ import_react8.default.createElement(
1682
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex-none w-16 border-r-[0.5px] border-border/30 relative bg-muted/5" }, HOURS.map((hour) => /* @__PURE__ */ import_react10.default.createElement(
1194
1683
  "div",
1195
1684
  {
1196
1685
  key: hour,
1197
1686
  className: "relative w-full text-[11px] text-muted-foreground/80 text-right pr-3 font-medium tabular-nums box-border",
1198
1687
  style: { height: HOUR_HEIGHT }
1199
1688
  },
1200
- /* @__PURE__ */ import_react8.default.createElement("span", { className: "block -translate-y-1/2" }, hour !== 0 && (0, import_date_fns9.format)(slotDate(currentDate, hour, 0), formats.hour, { locale }))
1201
- )), showsToday && /* @__PURE__ */ import_react8.default.createElement(
1689
+ /* @__PURE__ */ import_react10.default.createElement("span", { className: "block -translate-y-1/2" }, hour !== 0 && (0, import_date_fns13.format)(slotDate(currentDate, hour, 0), formats.hour, { locale }))
1690
+ )), showsToday && /* @__PURE__ */ import_react10.default.createElement(
1202
1691
  "div",
1203
1692
  {
1204
1693
  className: "absolute left-0 w-full pointer-events-none z-30 flex justify-end pr-2",
1205
1694
  style: { top: `${nowTop}px` }
1206
1695
  },
1207
- /* @__PURE__ */ import_react8.default.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" }, (0, import_date_fns9.format)(zonedNow, formats.compact, { locale }))
1696
+ /* @__PURE__ */ import_react10.default.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" }, (0, import_date_fns13.format)(zonedNow, formats.compact, { locale }))
1208
1697
  )),
1209
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, weekDays.map((day, dayIndex) => {
1210
- const dayKey2 = (0, import_date_fns9.format)(day, "yyyy-MM-dd");
1698
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, weekDays.map((day, dayIndex) => {
1699
+ const dayKey2 = (0, import_date_fns13.format)(day, "yyyy-MM-dd");
1211
1700
  const positioned = layoutDayEvents(segmentsByDay.get(dayKey2) ?? NO_SEGMENTS);
1212
- return /* @__PURE__ */ import_react8.default.createElement("div", { key: dayKey2, className: cn("relative h-full", dayIndex > 0 && "border-l-[0.5px] border-border/30") }, HOURS.map((hour) => /* @__PURE__ */ import_react8.default.createElement(
1701
+ return /* @__PURE__ */ import_react10.default.createElement("div", { key: dayKey2, className: cn("relative h-full", dayIndex > 0 && "border-l-[0.5px] border-border/30") }, HOURS.map((hour) => /* @__PURE__ */ import_react10.default.createElement(
1213
1702
  "div",
1214
1703
  {
1215
1704
  key: hour,
@@ -1218,7 +1707,7 @@ var WeekViewImpl = ({
1218
1707
  },
1219
1708
  QUARTERS.map((minute) => {
1220
1709
  const cellDate = slotDate(day, hour, minute);
1221
- return /* @__PURE__ */ import_react8.default.createElement(
1710
+ return /* @__PURE__ */ import_react10.default.createElement(
1222
1711
  DroppableCell,
1223
1712
  {
1224
1713
  key: minute,
@@ -1239,12 +1728,12 @@ var WeekViewImpl = ({
1239
1728
  const zonedEventStart = toDisplay(event.start, timezone);
1240
1729
  const zonedEventEnd = toDisplay(event.end, timezone);
1241
1730
  const startMinutes = start.getHours() * 60 + start.getMinutes();
1242
- const durationMinutes = (0, import_date_fns9.differenceInMinutes)(end, start);
1731
+ const durationMinutes = (0, import_date_fns13.differenceInMinutes)(end, start);
1243
1732
  const top = startMinutes / 60 * HOUR_HEIGHT;
1244
1733
  const height = durationMinutes / 60 * HOUR_HEIGHT;
1245
1734
  const isShortEvent = durationMinutes < 60;
1246
1735
  const isLastSegment = end.getTime() === zonedEventEnd.getTime();
1247
- return /* @__PURE__ */ import_react8.default.createElement(
1736
+ return /* @__PURE__ */ import_react10.default.createElement(
1248
1737
  DraggableEvent,
1249
1738
  {
1250
1739
  key: `${event.id}-${dayKey2}`,
@@ -1261,7 +1750,7 @@ var WeekViewImpl = ({
1261
1750
  paddingRight: columns > 1 ? "2px" : "0"
1262
1751
  }
1263
1752
  },
1264
- /* @__PURE__ */ import_react8.default.createElement(
1753
+ /* @__PURE__ */ import_react10.default.createElement(
1265
1754
  ResizableEvent,
1266
1755
  {
1267
1756
  readonly: readonly || !isLastSegment,
@@ -1271,7 +1760,7 @@ var WeekViewImpl = ({
1271
1760
  className: "h-full",
1272
1761
  style: { height: "100%" }
1273
1762
  },
1274
- /* @__PURE__ */ import_react8.default.createElement(
1763
+ /* @__PURE__ */ import_react10.default.createElement(
1275
1764
  "div",
1276
1765
  {
1277
1766
  className: cn(
@@ -1294,33 +1783,34 @@ var WeekViewImpl = ({
1294
1783
  e.stopPropagation();
1295
1784
  onEventClick?.(event);
1296
1785
  },
1786
+ onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
1297
1787
  title: columns > 1 ? `${event.title} (${column + 1}/${columns})` : void 0
1298
1788
  },
1299
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: cn(
1789
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: cn(
1300
1790
  "font-semibold truncate text-foreground/90 leading-tight",
1301
1791
  isShortEvent ? "text-xs text-center" : "text-xs"
1302
- ) }, event.title), !isShortEvent && /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-[10px] text-muted-foreground truncate mt-0.5 font-medium leading-tight" }, (0, import_date_fns9.format)(zonedEventStart, formats.time, { locale }), " - ", (0, import_date_fns9.format)(zonedEventEnd, formats.time, { locale })), event.description && height > 50 && /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-[10px] text-muted-foreground/80 truncate mt-1 leading-tight opacity-80" }, event.description)), columns > 1 && !isShortEvent && /* @__PURE__ */ import_react8.default.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))
1792
+ ) }, event.title), !isShortEvent && /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-[10px] text-muted-foreground truncate mt-0.5 font-medium leading-tight" }, (0, import_date_fns13.format)(zonedEventStart, formats.time, { locale }), " - ", (0, import_date_fns13.format)(zonedEventEnd, formats.time, { locale })), event.description && height > 50 && /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-[10px] text-muted-foreground/80 truncate mt-1 leading-tight opacity-80" }, event.description)), columns > 1 && !isShortEvent && /* @__PURE__ */ import_react10.default.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))
1303
1793
  )
1304
1794
  )
1305
1795
  );
1306
- }), (0, import_date_fns9.isSameDay)(day, today) && /* @__PURE__ */ import_react8.default.createElement(
1796
+ }), (0, import_date_fns13.isSameDay)(day, today) && /* @__PURE__ */ import_react10.default.createElement(
1307
1797
  "div",
1308
1798
  {
1309
1799
  className: "absolute left-0 right-0 z-20 pointer-events-none flex items-center",
1310
1800
  style: { top: `${nowTop}px` }
1311
1801
  },
1312
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
1313
- /* @__PURE__ */ import_react8.default.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" })
1802
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
1803
+ /* @__PURE__ */ import_react10.default.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" })
1314
1804
  ));
1315
1805
  }))
1316
1806
  )
1317
1807
  ));
1318
1808
  };
1319
- var WeekView = import_react8.default.memo(WeekViewImpl);
1809
+ var WeekView = import_react10.default.memo(WeekViewImpl);
1320
1810
 
1321
1811
  // src/views/DayView.tsx
1322
- var import_react9 = __toESM(require("react"));
1323
- var import_date_fns10 = require("date-fns");
1812
+ var import_react11 = __toESM(require("react"));
1813
+ var import_date_fns14 = require("date-fns");
1324
1814
  var HOUR_HEIGHT2 = 80;
1325
1815
  var HOURS2 = Array.from({ length: 24 }, (_, i) => i);
1326
1816
  var QUARTERS2 = [0, 15, 30, 45];
@@ -1338,46 +1828,67 @@ var DayViewImpl = ({
1338
1828
  onEventResize,
1339
1829
  timezone,
1340
1830
  locale,
1341
- readonly
1831
+ readonly,
1832
+ onEventContextMenu,
1833
+ translations,
1834
+ onDayEventResize,
1835
+ onAllDaySlotClick
1342
1836
  }) => {
1343
- const visibleRange = import_react9.default.useMemo(() => {
1344
- const start = (0, import_date_fns10.startOfDay)(currentDate);
1345
- return { start, end: (0, import_date_fns10.addDays)(start, 1) };
1837
+ const visibleRange = import_react11.default.useMemo(() => {
1838
+ const start = (0, import_date_fns14.startOfDay)(currentDate);
1839
+ return { start, end: (0, import_date_fns14.addDays)(start, 1) };
1346
1840
  }, [currentDate]);
1347
- const scrollContainerRef = import_react9.default.useRef(null);
1348
- const [now, setNow] = import_react9.default.useState(() => /* @__PURE__ */ new Date());
1349
- import_react9.default.useEffect(() => {
1841
+ const scrollContainerRef = import_react11.default.useRef(null);
1842
+ const [now, setNow] = import_react11.default.useState(() => /* @__PURE__ */ new Date());
1843
+ import_react11.default.useEffect(() => {
1350
1844
  const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
1351
1845
  return () => clearInterval(interval);
1352
1846
  }, []);
1353
- import_react9.default.useEffect(() => {
1847
+ import_react11.default.useEffect(() => {
1354
1848
  if (scrollContainerRef.current) {
1355
1849
  const offsetHour = 3;
1356
1850
  scrollContainerRef.current.scrollTop = (toDisplay(/* @__PURE__ */ new Date(), timezone).getHours() - offsetHour) * HOUR_HEIGHT2;
1357
1851
  }
1358
1852
  }, [timezone]);
1359
- const dayKey2 = (0, import_date_fns10.format)(currentDate, "yyyy-MM-dd");
1360
- const positioned = layoutDayEvents(segmentsByDisplayDay(events, timezone, visibleRange).get(dayKey2) ?? NO_SEGMENTS2);
1361
- const isToday2 = (0, import_date_fns10.isSameDay)(currentDate, displayToday(timezone, now));
1853
+ const dayKey2 = (0, import_date_fns14.format)(currentDate, "yyyy-MM-dd");
1854
+ const { dayEvents, timedEvents } = partitionDayEvents(events, timezone);
1855
+ const rowDays = import_react11.default.useMemo(() => [visibleRange.start], [visibleRange]);
1856
+ const positioned = layoutDayEvents(segmentsByDisplayDay(timedEvents, timezone, visibleRange).get(dayKey2) ?? NO_SEGMENTS2);
1857
+ const isToday2 = (0, import_date_fns14.isSameDay)(currentDate, displayToday(timezone, now));
1362
1858
  const zonedNow = toDisplay(now, timezone);
1363
1859
  const nowTop = minutesSinceDisplayMidnight(now, timezone) / 60 * HOUR_HEIGHT2;
1364
1860
  const formats = timeFormats(locale);
1365
- return /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden shadow-sm" }, /* @__PURE__ */ import_react9.default.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__ */ import_react9.default.createElement("div", { className: "flex items-center justify-center gap-3" }, /* @__PURE__ */ import_react9.default.createElement("h2", { className: "text-xl font-semibold capitalize text-foreground" }, (0, import_date_fns10.format)(currentDate, "EEEE, MMMM d, yyyy", { locale })), isToday2 && /* @__PURE__ */ import_react9.default.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__ */ import_react9.default.createElement("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto relative" }, /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex relative", style: { height: HOURS2.length * HOUR_HEIGHT2 } }, /* @__PURE__ */ import_react9.default.createElement("div", { className: "w-20 bg-muted/5 border-r-[0.5px] border-border/30 relative" }, HOURS2.map((hour) => /* @__PURE__ */ import_react9.default.createElement(
1861
+ return /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden shadow-sm" }, /* @__PURE__ */ import_react11.default.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__ */ import_react11.default.createElement("div", { className: "flex items-center justify-center gap-3" }, /* @__PURE__ */ import_react11.default.createElement("h2", { className: "text-xl font-semibold capitalize text-foreground" }, (0, import_date_fns14.format)(currentDate, "EEEE, MMMM d, yyyy", { locale })), isToday2 && /* @__PURE__ */ import_react11.default.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__ */ import_react11.default.createElement(
1862
+ AllDayRow,
1863
+ {
1864
+ days: rowDays,
1865
+ dayEvents,
1866
+ timezone,
1867
+ locale,
1868
+ translations,
1869
+ readonly,
1870
+ gutterClassName: "w-20",
1871
+ onEventClick,
1872
+ onEventContextMenu,
1873
+ onDayEventResize,
1874
+ onSlotClick: onAllDaySlotClick
1875
+ }
1876
+ ), /* @__PURE__ */ import_react11.default.createElement("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto relative" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex relative", style: { height: HOURS2.length * HOUR_HEIGHT2 } }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "w-20 bg-muted/5 border-r-[0.5px] border-border/30 relative" }, HOURS2.map((hour) => /* @__PURE__ */ import_react11.default.createElement(
1366
1877
  "div",
1367
1878
  {
1368
1879
  key: hour,
1369
1880
  className: "relative w-full",
1370
1881
  style: { height: HOUR_HEIGHT2 }
1371
1882
  },
1372
- hour !== 0 && /* @__PURE__ */ import_react9.default.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" }, (0, import_date_fns10.format)(slotDate2(currentDate, hour, 0), formats.hour, { locale }))
1373
- )), isToday2 && /* @__PURE__ */ import_react9.default.createElement(
1883
+ hour !== 0 && /* @__PURE__ */ import_react11.default.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" }, (0, import_date_fns14.format)(slotDate2(currentDate, hour, 0), formats.hour, { locale }))
1884
+ )), isToday2 && /* @__PURE__ */ import_react11.default.createElement(
1374
1885
  "div",
1375
1886
  {
1376
1887
  className: "absolute left-0 w-full pointer-events-none z-30 flex justify-end pr-2",
1377
1888
  style: { top: `${nowTop}px` }
1378
1889
  },
1379
- /* @__PURE__ */ import_react9.default.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" }, (0, import_date_fns10.format)(zonedNow, formats.time, { locale }))
1380
- )), /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex-1 relative" }, HOURS2.map((hour) => /* @__PURE__ */ import_react9.default.createElement(
1890
+ /* @__PURE__ */ import_react11.default.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" }, (0, import_date_fns14.format)(zonedNow, formats.time, { locale }))
1891
+ )), /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex-1 relative" }, HOURS2.map((hour) => /* @__PURE__ */ import_react11.default.createElement(
1381
1892
  "div",
1382
1893
  {
1383
1894
  key: hour,
@@ -1386,7 +1897,7 @@ var DayViewImpl = ({
1386
1897
  },
1387
1898
  QUARTERS2.map((minute) => {
1388
1899
  const cellDate = slotDate2(currentDate, hour, minute);
1389
- return /* @__PURE__ */ import_react9.default.createElement(
1900
+ return /* @__PURE__ */ import_react11.default.createElement(
1390
1901
  DroppableCell,
1391
1902
  {
1392
1903
  key: minute,
@@ -1407,12 +1918,12 @@ var DayViewImpl = ({
1407
1918
  const zonedStart = toDisplay(event.start, timezone);
1408
1919
  const zonedEnd = toDisplay(event.end, timezone);
1409
1920
  const startMinutes = start.getHours() * 60 + start.getMinutes();
1410
- const durationMinutes = (0, import_date_fns10.differenceInMinutes)(end, start);
1921
+ const durationMinutes = (0, import_date_fns14.differenceInMinutes)(end, start);
1411
1922
  const top = startMinutes / 60 * HOUR_HEIGHT2;
1412
1923
  const height = durationMinutes / 60 * HOUR_HEIGHT2;
1413
1924
  const isShortEvent = durationMinutes < 45;
1414
1925
  const isLastSegment = end.getTime() === zonedEnd.getTime();
1415
- return /* @__PURE__ */ import_react9.default.createElement(
1926
+ return /* @__PURE__ */ import_react11.default.createElement(
1416
1927
  DraggableEvent,
1417
1928
  {
1418
1929
  key: `${event.id}-${dayKey2}`,
@@ -1428,7 +1939,7 @@ var DayViewImpl = ({
1428
1939
  paddingRight: columns > 1 ? "2px" : "0"
1429
1940
  }
1430
1941
  },
1431
- /* @__PURE__ */ import_react9.default.createElement(
1942
+ /* @__PURE__ */ import_react11.default.createElement(
1432
1943
  ResizableEvent,
1433
1944
  {
1434
1945
  readonly: readonly || !isLastSegment,
@@ -1438,7 +1949,7 @@ var DayViewImpl = ({
1438
1949
  className: "h-full",
1439
1950
  style: { height: "100%" }
1440
1951
  },
1441
- /* @__PURE__ */ import_react9.default.createElement(
1952
+ /* @__PURE__ */ import_react11.default.createElement(
1442
1953
  "div",
1443
1954
  {
1444
1955
  className: cn(
@@ -1459,42 +1970,43 @@ var DayViewImpl = ({
1459
1970
  e.stopPropagation();
1460
1971
  onEventClick?.(event);
1461
1972
  },
1973
+ onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
1462
1974
  title: columns > 1 ? `${event.title} (${column + 1}/${columns})` : void 0
1463
1975
  },
1464
- /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ import_react9.default.createElement("div", { className: cn(
1976
+ /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: cn(
1465
1977
  "font-semibold truncate leading-tight",
1466
1978
  isShortEvent ? "text-xs" : "text-sm",
1467
1979
  event.color ? "text-foreground" : "text-foreground/90"
1468
- ) }, event.title), !isShortEvent && /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement("div", { className: "text-xs text-muted-foreground mt-0.5 font-medium" }, (0, import_date_fns10.format)(zonedStart, formats.time, { locale }), " - ", (0, import_date_fns10.format)(zonedEnd, formats.time, { locale })), event.description && height > 60 && /* @__PURE__ */ import_react9.default.createElement("div", { className: "text-xs text-muted-foreground/80 mt-1 line-clamp-2" }, event.description)), columns > 1 && !isShortEvent && /* @__PURE__ */ import_react9.default.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))
1980
+ ) }, event.title), !isShortEvent && /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null, /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-xs text-muted-foreground mt-0.5 font-medium" }, (0, import_date_fns14.format)(zonedStart, formats.time, { locale }), " - ", (0, import_date_fns14.format)(zonedEnd, formats.time, { locale })), event.description && height > 60 && /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-xs text-muted-foreground/80 mt-1 line-clamp-2" }, event.description)), columns > 1 && !isShortEvent && /* @__PURE__ */ import_react11.default.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))
1469
1981
  )
1470
1982
  )
1471
1983
  );
1472
- }), isToday2 && /* @__PURE__ */ import_react9.default.createElement(
1984
+ }), isToday2 && /* @__PURE__ */ import_react11.default.createElement(
1473
1985
  "div",
1474
1986
  {
1475
1987
  className: "absolute left-0 right-0 z-20 pointer-events-none flex items-center",
1476
1988
  style: { top: `${nowTop}px` }
1477
1989
  },
1478
- /* @__PURE__ */ import_react9.default.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
1479
- /* @__PURE__ */ import_react9.default.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" })
1990
+ /* @__PURE__ */ import_react11.default.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
1991
+ /* @__PURE__ */ import_react11.default.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" })
1480
1992
  )))));
1481
1993
  };
1482
- var DayView = import_react9.default.memo(DayViewImpl);
1994
+ var DayView = import_react11.default.memo(DayViewImpl);
1483
1995
 
1484
1996
  // src/views/AgendaView.tsx
1485
- var import_react11 = __toESM(require("react"));
1486
- var import_date_fns11 = require("date-fns");
1997
+ var import_react13 = __toESM(require("react"));
1998
+ var import_date_fns15 = require("date-fns");
1487
1999
 
1488
2000
  // src/components/EmptyState.tsx
1489
- var import_react10 = __toESM(require("react"));
2001
+ var import_react12 = __toESM(require("react"));
1490
2002
  var import_lucide_react4 = require("lucide-react");
1491
- var AgendaEmptyState = ({ onCreateEvent, translations }) => /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex flex-col items-center justify-center h-full min-h-[400px] py-12" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "relative mb-8" }, /* @__PURE__ */ import_react10.default.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__ */ import_react10.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "w-12 h-12 rounded-2xl bg-green-100 dark:bg-green-900/30 flex items-center justify-center" }, /* @__PURE__ */ import_react10.default.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__ */ import_react10.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }))), /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-left" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "font-medium text-foreground" }, translations?.allCaughtUp || "All caught up!"), /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-sm text-muted-foreground" }, translations?.noEventsScheduled || "No events scheduled"))))), /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center max-w-sm" }, /* @__PURE__ */ import_react10.default.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, translations?.noUpcoming || "Your schedule is clear"), /* @__PURE__ */ import_react10.default.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__ */ import_react10.default.createElement(
2003
+ var AgendaEmptyState = ({ onCreateEvent, translations }) => /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex flex-col items-center justify-center h-full min-h-[400px] py-12" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "relative mb-8" }, /* @__PURE__ */ import_react12.default.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__ */ import_react12.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "w-12 h-12 rounded-2xl bg-green-100 dark:bg-green-900/30 flex items-center justify-center" }, /* @__PURE__ */ import_react12.default.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__ */ import_react12.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }))), /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-left" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "font-medium text-foreground" }, translations?.allCaughtUp || "All caught up!"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-sm text-muted-foreground" }, translations?.noEventsScheduled || "No events scheduled"))))), /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-center max-w-sm" }, /* @__PURE__ */ import_react12.default.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, translations?.noUpcoming || "Your schedule is clear"), /* @__PURE__ */ import_react12.default.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__ */ import_react12.default.createElement(
1492
2004
  "button",
1493
2005
  {
1494
2006
  onClick: onCreateEvent,
1495
2007
  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"
1496
2008
  },
1497
- /* @__PURE__ */ import_react10.default.createElement(import_lucide_react4.Plus, { className: "w-4 h-4" }),
2009
+ /* @__PURE__ */ import_react12.default.createElement(import_lucide_react4.Plus, { className: "w-4 h-4" }),
1498
2010
  translations?.createEvent || "Create Event"
1499
2011
  )));
1500
2012
 
@@ -1502,7 +2014,7 @@ var AgendaEmptyState = ({ onCreateEvent, translations }) => /* @__PURE__ */ impo
1502
2014
  var import_framer_motion = require("framer-motion");
1503
2015
  var import_lucide_react5 = require("lucide-react");
1504
2016
  var formatDuration = (start, end) => {
1505
- const minutes = (0, import_date_fns11.differenceInMinutes)(end, start);
2017
+ const minutes = (0, import_date_fns15.differenceInMinutes)(end, start);
1506
2018
  if (minutes < 60) return `${minutes}m`;
1507
2019
  const hours = Math.floor(minutes / 60);
1508
2020
  const remainingMinutes = minutes % 60;
@@ -1510,9 +2022,9 @@ var formatDuration = (start, end) => {
1510
2022
  return `${hours}h ${remainingMinutes}m`;
1511
2023
  };
1512
2024
  var getDateLabel = (date, today, locale, translations) => {
1513
- if ((0, import_date_fns11.isSameDay)(date, today)) return translations?.today || "Today";
1514
- if ((0, import_date_fns11.isSameDay)(date, (0, import_date_fns11.addDays)(today, 1))) return translations?.tomorrow || "Tomorrow";
1515
- return (0, import_date_fns11.format)(date, "EEEE", { locale });
2025
+ if ((0, import_date_fns15.isSameDay)(date, today)) return translations?.today || "Today";
2026
+ if ((0, import_date_fns15.isSameDay)(date, (0, import_date_fns15.addDays)(today, 1))) return translations?.tomorrow || "Tomorrow";
2027
+ return (0, import_date_fns15.format)(date, "EEEE", { locale });
1516
2028
  };
1517
2029
  var AgendaView = ({
1518
2030
  currentDate,
@@ -1521,17 +2033,18 @@ var AgendaView = ({
1521
2033
  onCreateEvent,
1522
2034
  locale,
1523
2035
  translations,
1524
- timezone
2036
+ timezone,
2037
+ onEventContextMenu
1525
2038
  }) => {
1526
2039
  const is24h = uses24HourClock(locale);
1527
2040
  const { time: timePattern, compact: compactTimePattern } = timeFormats(locale);
1528
2041
  const today = displayToday(timezone);
1529
- const groupedEvents = (0, import_react11.useMemo)(() => {
2042
+ const groupedEvents = (0, import_react13.useMemo)(() => {
1530
2043
  const byDay = eventsByStartDay(events, timezone);
1531
2044
  const groups = [];
1532
2045
  for (let i = 0; i < 30; i++) {
1533
- const day = (0, import_date_fns11.addDays)((0, import_date_fns11.startOfDay)(currentDate), i);
1534
- const dayEvents = byDay.get((0, import_date_fns11.format)(day, "yyyy-MM-dd"));
2046
+ const day = (0, import_date_fns15.addDays)((0, import_date_fns15.startOfDay)(currentDate), i);
2047
+ const dayEvents = byDay.get((0, import_date_fns15.format)(day, "yyyy-MM-dd"));
1535
2048
  if (dayEvents?.length) {
1536
2049
  groups.push({ date: day, events: [...dayEvents].sort((a, b) => a.start.getTime() - b.start.getTime()) });
1537
2050
  }
@@ -1551,7 +2064,7 @@ var AgendaView = ({
1551
2064
  hidden: { opacity: 0, x: -20 },
1552
2065
  show: { opacity: 1, x: 0 }
1553
2066
  };
1554
- return /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col h-full bg-background overflow-y-auto" }, groupedEvents.length === 0 ? /* @__PURE__ */ import_react11.default.createElement(AgendaEmptyState, { onCreateEvent, translations }) : /* @__PURE__ */ import_react11.default.createElement(
2067
+ return /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex flex-col h-full bg-background overflow-y-auto" }, groupedEvents.length === 0 ? /* @__PURE__ */ import_react13.default.createElement(AgendaEmptyState, { onCreateEvent, translations }) : /* @__PURE__ */ import_react13.default.createElement(
1555
2068
  import_framer_motion.motion.div,
1556
2069
  {
1557
2070
  className: "max-w-3xl mx-auto w-full pb-10 px-4 md:px-6",
@@ -1559,25 +2072,26 @@ var AgendaView = ({
1559
2072
  initial: "hidden",
1560
2073
  animate: "show"
1561
2074
  },
1562
- groupedEvents.map((group) => /* @__PURE__ */ import_react11.default.createElement(
2075
+ groupedEvents.map((group) => /* @__PURE__ */ import_react13.default.createElement(
1563
2076
  import_framer_motion.motion.div,
1564
2077
  {
1565
2078
  key: group.date.toISOString(),
1566
2079
  className: "relative",
1567
2080
  variants: item
1568
2081
  },
1569
- /* @__PURE__ */ import_react11.default.createElement("div", { className: "sticky top-0 bg-background/95 backdrop-blur-md py-4 z-10 border-b border-border/50" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: cn(
2082
+ /* @__PURE__ */ import_react13.default.createElement("div", { className: "sticky top-0 bg-background/95 backdrop-blur-md py-4 z-10 border-b border-border/50" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: cn(
1570
2083
  "flex flex-col items-center justify-center w-16 h-16 rounded-2xl transition-all",
1571
- (0, import_date_fns11.isSameDay)(group.date, today) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30" : "bg-muted/50 text-foreground"
1572
- ) }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-2xl font-bold leading-none" }, (0, import_date_fns11.format)(group.date, "d")), /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-xs font-medium uppercase tracking-wide opacity-80" }, (0, import_date_fns11.format)(group.date, "MMM", { locale }))), /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: cn(
2084
+ (0, import_date_fns15.isSameDay)(group.date, today) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30" : "bg-muted/50 text-foreground"
2085
+ ) }, /* @__PURE__ */ import_react13.default.createElement("span", { className: "text-2xl font-bold leading-none" }, (0, import_date_fns15.format)(group.date, "d")), /* @__PURE__ */ import_react13.default.createElement("span", { className: "text-xs font-medium uppercase tracking-wide opacity-80" }, (0, import_date_fns15.format)(group.date, "MMM", { locale }))), /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ import_react13.default.createElement("span", { className: cn(
1573
2086
  "text-lg font-semibold",
1574
- (0, import_date_fns11.isSameDay)(group.date, today) && "text-primary"
1575
- ) }, getDateLabel(group.date, today, locale, translations)), /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-sm text-muted-foreground" }, group.events.length, " ", group.events.length !== 1 ? translations?.eventPlural || "events" : translations?.eventSingular || "event")))),
1576
- /* @__PURE__ */ import_react11.default.createElement("div", { className: "py-4 space-y-3" }, group.events.map((event) => /* @__PURE__ */ import_react11.default.createElement(
2087
+ (0, import_date_fns15.isSameDay)(group.date, today) && "text-primary"
2088
+ ) }, getDateLabel(group.date, today, locale, translations)), /* @__PURE__ */ import_react13.default.createElement("span", { className: "text-sm text-muted-foreground" }, group.events.length, " ", group.events.length !== 1 ? translations?.eventPlural || "events" : translations?.eventSingular || "event")))),
2089
+ /* @__PURE__ */ import_react13.default.createElement("div", { className: "py-4 space-y-3" }, group.events.map((event) => /* @__PURE__ */ import_react13.default.createElement(
1577
2090
  import_framer_motion.motion.div,
1578
2091
  {
1579
2092
  key: event.id,
1580
2093
  onClick: () => onEventClick?.(event),
2094
+ onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
1581
2095
  className: cn(
1582
2096
  "group relative flex gap-4 p-4 rounded-2xl border border-border/40",
1583
2097
  "hover:border-primary/40 hover:shadow-lg hover:shadow-primary/5",
@@ -1587,30 +2101,30 @@ var AgendaView = ({
1587
2101
  whileHover: { scale: 1.01, y: -2 },
1588
2102
  transition: { duration: 0.2 }
1589
2103
  },
1590
- /* @__PURE__ */ import_react11.default.createElement(
2104
+ /* @__PURE__ */ import_react13.default.createElement(
1591
2105
  "div",
1592
2106
  {
1593
2107
  className: "absolute left-0 top-3 bottom-3 w-1 rounded-full",
1594
2108
  style: { backgroundColor: event.color || "var(--primary)" }
1595
2109
  }
1596
2110
  ),
1597
- /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col items-center min-w-[70px] pl-2" }, event.allDay ? /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ import_react11.default.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__ */ import_react11.default.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-base font-semibold text-foreground" }, (0, import_date_fns11.format)(toDisplay(event.start, timezone), compactTimePattern, { locale })), !is24h && /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-xs text-muted-foreground uppercase" }, (0, import_date_fns11.format)(toDisplay(event.start, timezone), "a")), /* @__PURE__ */ import_react11.default.createElement("div", { className: "w-px h-3 bg-border my-1" }), /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-xs text-muted-foreground/70 font-medium" }, formatDuration(event.start, event.end)))),
1598
- /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex-1 min-w-0 space-y-2" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-start justify-between gap-2" }, /* @__PURE__ */ import_react11.default.createElement("h4", { className: "text-base font-semibold text-foreground group-hover:text-primary transition-colors line-clamp-1" }, event.title), /* @__PURE__ */ import_react11.default.createElement(
2111
+ /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex flex-col items-center min-w-[70px] pl-2" }, event.allDay ? /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ import_react13.default.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__ */ import_react13.default.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ import_react13.default.createElement("span", { className: "text-base font-semibold text-foreground" }, (0, import_date_fns15.format)(toDisplay(event.start, timezone), compactTimePattern, { locale })), !is24h && /* @__PURE__ */ import_react13.default.createElement("span", { className: "text-xs text-muted-foreground uppercase" }, (0, import_date_fns15.format)(toDisplay(event.start, timezone), "a")), /* @__PURE__ */ import_react13.default.createElement("div", { className: "w-px h-3 bg-border my-1" }), /* @__PURE__ */ import_react13.default.createElement("span", { className: "text-xs text-muted-foreground/70 font-medium" }, formatDuration(event.start, event.end)))),
2112
+ /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex-1 min-w-0 space-y-2" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex items-start justify-between gap-2" }, /* @__PURE__ */ import_react13.default.createElement("h4", { className: "text-base font-semibold text-foreground group-hover:text-primary transition-colors line-clamp-1" }, event.title), /* @__PURE__ */ import_react13.default.createElement(
1599
2113
  "div",
1600
2114
  {
1601
2115
  className: "w-3 h-3 rounded-full shrink-0 mt-1.5",
1602
2116
  style: { backgroundColor: event.color || "var(--primary)" }
1603
2117
  }
1604
- )), event.description && /* @__PURE__ */ import_react11.default.createElement("p", { className: "text-sm text-muted-foreground line-clamp-2 leading-relaxed" }, event.description), /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-wrap items-center gap-3 pt-1" }, !event.allDay && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react5.Clock, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react11.default.createElement("span", null, (0, import_date_fns11.format)(toDisplay(event.start, timezone), timePattern, { locale }), " - ", (0, import_date_fns11.format)(toDisplay(event.end, timezone), timePattern, { locale }))), event.guests && event.guests.length > 0 && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react5.Users, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react11.default.createElement("span", null, event.guests.length, " ", event.guests.length !== 1 ? translations?.guestsCount || "guests" : translations?.guestCount || "guest")), event.attachments && event.attachments.length > 0 && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react5.Paperclip, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react11.default.createElement("span", null, event.attachments.length)), event.reminders && event.reminders.length > 0 && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react5.Bell, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react11.default.createElement("span", null, event.reminders.length)))),
1605
- /* @__PURE__ */ import_react11.default.createElement("div", { className: "absolute right-4 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react11.default.createElement("svg", { className: "w-5 h-5 text-muted-foreground", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ import_react11.default.createElement("path", { d: "M9 18l6-6-6-6" })))
2118
+ )), event.description && /* @__PURE__ */ import_react13.default.createElement("p", { className: "text-sm text-muted-foreground line-clamp-2 leading-relaxed" }, event.description), /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex flex-wrap items-center gap-3 pt-1" }, !event.allDay && /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react13.default.createElement(import_lucide_react5.Clock, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react13.default.createElement("span", null, (0, import_date_fns15.format)(toDisplay(event.start, timezone), timePattern, { locale }), " - ", (0, import_date_fns15.format)(toDisplay(event.end, timezone), timePattern, { locale }))), event.guests && event.guests.length > 0 && /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react13.default.createElement(import_lucide_react5.Users, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react13.default.createElement("span", null, event.guests.length, " ", event.guests.length !== 1 ? translations?.guestsCount || "guests" : translations?.guestCount || "guest")), event.attachments && event.attachments.length > 0 && /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react13.default.createElement(import_lucide_react5.Paperclip, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react13.default.createElement("span", null, event.attachments.length)), event.reminders && event.reminders.length > 0 && /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react13.default.createElement(import_lucide_react5.Bell, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react13.default.createElement("span", null, event.reminders.length)))),
2119
+ /* @__PURE__ */ import_react13.default.createElement("div", { className: "absolute right-4 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react13.default.createElement("svg", { className: "w-5 h-5 text-muted-foreground", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ import_react13.default.createElement("path", { d: "M9 18l6-6-6-6" })))
1606
2120
  )))
1607
2121
  ))
1608
2122
  ));
1609
2123
  };
1610
2124
 
1611
2125
  // src/views/ResourceView.tsx
1612
- var import_react12 = __toESM(require("react"));
1613
- var import_date_fns12 = require("date-fns");
2126
+ var import_react14 = __toESM(require("react"));
2127
+ var import_date_fns16 = require("date-fns");
1614
2128
  var ResourceView = ({
1615
2129
  currentDate,
1616
2130
  events,
@@ -1618,18 +2132,20 @@ var ResourceView = ({
1618
2132
  onEventClick,
1619
2133
  onTimeSlotClick,
1620
2134
  locale,
1621
- timezone
2135
+ timezone,
2136
+ translations,
2137
+ onEventContextMenu
1622
2138
  }) => {
1623
- const containerRef = (0, import_react12.useRef)(null);
2139
+ const containerRef = (0, import_react14.useRef)(null);
1624
2140
  const hours = Array.from({ length: 24 }, (_, i) => i);
1625
2141
  const hourWidth = 100;
1626
2142
  const timeFormat = timeFormats(locale).hour;
1627
2143
  const getEventStyle = (event) => {
1628
2144
  const start = toDisplay(event.start, timezone);
1629
2145
  const end = toDisplay(event.end, timezone);
1630
- const dayStart = (0, import_date_fns12.startOfDay)(currentDate);
1631
- const startMinutes = (0, import_date_fns12.differenceInMinutes)(start, dayStart);
1632
- const durationMinutes = (0, import_date_fns12.differenceInMinutes)(end, start);
2146
+ const dayStart = (0, import_date_fns16.startOfDay)(currentDate);
2147
+ const startMinutes = (0, import_date_fns16.differenceInMinutes)(start, dayStart);
2148
+ const durationMinutes = (0, import_date_fns16.differenceInMinutes)(end, start);
1633
2149
  const left = startMinutes / 60 * hourWidth;
1634
2150
  const width = durationMinutes / 60 * hourWidth;
1635
2151
  return {
@@ -1638,19 +2154,19 @@ var ResourceView = ({
1638
2154
  // Min width for visibility
1639
2155
  };
1640
2156
  };
1641
- return /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex flex-col h-full bg-background overflow-hidden" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex border-b border-border bg-muted/20" }, /* @__PURE__ */ import_react12.default.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__ */ import_react12.default.createElement("div", { className: "flex overflow-hidden" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex relative", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ import_react12.default.createElement(
2157
+ return /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-col h-full bg-background overflow-hidden" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex border-b border-border bg-muted/20" }, /* @__PURE__ */ import_react14.default.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__ */ import_react14.default.createElement("div", { className: "flex overflow-hidden" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex relative", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ import_react14.default.createElement(
1642
2158
  "div",
1643
2159
  {
1644
2160
  key: hour,
1645
2161
  className: "border-r border-border/50 text-xs text-muted-foreground p-2 font-medium shrink-0",
1646
2162
  style: { width: hourWidth }
1647
2163
  },
1648
- (0, import_date_fns12.format)((/* @__PURE__ */ new Date()).setHours(hour, 0, 0, 0), timeFormat, { locale })
1649
- ))))), /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex-1 overflow-auto relative", ref: containerRef }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "min-w-fit" }, resources.map((resource) => {
2164
+ (0, import_date_fns16.format)((/* @__PURE__ */ new Date()).setHours(hour, 0, 0, 0), timeFormat, { locale })
2165
+ ))))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex-1 overflow-auto relative", ref: containerRef }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "min-w-fit" }, resources.map((resource) => {
1650
2166
  const resourceEvents = events.filter(
1651
2167
  (e) => e.resourceId === resource.id && isSameDisplayDay(e.start, currentDate, timezone)
1652
2168
  );
1653
- return /* @__PURE__ */ import_react12.default.createElement("div", { key: resource.id, className: "flex border-b border-border min-h-[100px]" }, /* @__PURE__ */ import_react12.default.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__ */ import_react12.default.createElement("img", { src: resource.avatar, alt: resource.label, className: "w-8 h-8 rounded-full object-cover" }) : /* @__PURE__ */ import_react12.default.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__ */ import_react12.default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ import_react12.default.createElement("span", { className: "text-sm font-medium" }, resource.label), /* @__PURE__ */ import_react12.default.createElement("span", { className: "text-xs text-muted-foreground" }, "ID: ", resource.id))), /* @__PURE__ */ import_react12.default.createElement("div", { className: "relative flex", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ import_react12.default.createElement(
2169
+ return /* @__PURE__ */ import_react14.default.createElement("div", { key: resource.id, className: "flex border-b border-border min-h-[100px]" }, /* @__PURE__ */ import_react14.default.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__ */ import_react14.default.createElement("img", { src: resource.avatar, alt: resource.label, className: "w-8 h-8 rounded-full object-cover" }) : /* @__PURE__ */ import_react14.default.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__ */ import_react14.default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium" }, resource.label), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs text-muted-foreground" }, interpolate(translations?.idLabel || "ID: {id}", { id: resource.id })))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "relative flex", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ import_react14.default.createElement(
1654
2170
  "div",
1655
2171
  {
1656
2172
  key: hour,
@@ -1661,7 +2177,7 @@ var ResourceView = ({
1661
2177
  const slotDate3 = new Date(currentDate);
1662
2178
  slotDate3.setHours(hour, minute, 0, 0);
1663
2179
  const slotId = `${resource.id}-${slotDate3.toISOString()}`;
1664
- return /* @__PURE__ */ import_react12.default.createElement(
2180
+ return /* @__PURE__ */ import_react14.default.createElement(
1665
2181
  DroppableCell,
1666
2182
  {
1667
2183
  key: minute,
@@ -1673,7 +2189,7 @@ var ResourceView = ({
1673
2189
  }
1674
2190
  );
1675
2191
  })
1676
- )), resourceEvents.map((event) => /* @__PURE__ */ import_react12.default.createElement(
2192
+ )), resourceEvents.map((event) => /* @__PURE__ */ import_react14.default.createElement(
1677
2193
  DraggableEvent,
1678
2194
  {
1679
2195
  key: event.id,
@@ -1682,6 +2198,7 @@ var ResourceView = ({
1682
2198
  e.stopPropagation();
1683
2199
  onEventClick?.(event);
1684
2200
  },
2201
+ onContextMenu: onEventContextMenu ? (e) => onEventContextMenu(event, e) : void 0,
1685
2202
  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",
1686
2203
  style: {
1687
2204
  ...getEventStyle(event),
@@ -1690,16 +2207,16 @@ var ResourceView = ({
1690
2207
  color: "#fff"
1691
2208
  }
1692
2209
  },
1693
- /* @__PURE__ */ import_react12.default.createElement("div", { className: "truncate" }, event.title)
2210
+ /* @__PURE__ */ import_react14.default.createElement("div", { className: "truncate" }, event.title)
1694
2211
  ))));
1695
2212
  }))));
1696
2213
  };
1697
2214
 
1698
2215
  // src/components/EventModal.tsx
1699
- var import_react14 = __toESM(require("react"));
2216
+ var import_react16 = __toESM(require("react"));
1700
2217
 
1701
2218
  // src/components/ui/Modal.tsx
1702
- var import_react13 = __toESM(require("react"));
2219
+ var import_react15 = __toESM(require("react"));
1703
2220
  var import_lucide_react6 = require("lucide-react");
1704
2221
  var Modal = ({
1705
2222
  isOpen,
@@ -1707,10 +2224,11 @@ var Modal = ({
1707
2224
  title,
1708
2225
  children,
1709
2226
  className,
1710
- hideHeader = false
2227
+ hideHeader = false,
2228
+ closeLabel = "Close"
1711
2229
  }) => {
1712
- const overlayRef = (0, import_react13.useRef)(null);
1713
- (0, import_react13.useEffect)(() => {
2230
+ const overlayRef = (0, import_react15.useRef)(null);
2231
+ (0, import_react15.useEffect)(() => {
1714
2232
  const handleEscape = (e) => {
1715
2233
  if (e.key === "Escape") {
1716
2234
  onClose();
@@ -1724,14 +2242,14 @@ var Modal = ({
1724
2242
  };
1725
2243
  }, [isOpen, onClose]);
1726
2244
  if (!isOpen) return null;
1727
- return /* @__PURE__ */ import_react13.default.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__ */ import_react13.default.createElement(
2245
+ return /* @__PURE__ */ import_react15.default.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__ */ import_react15.default.createElement(
1728
2246
  "div",
1729
2247
  {
1730
2248
  ref: overlayRef,
1731
2249
  className: "absolute inset-0",
1732
2250
  onClick: onClose
1733
2251
  }
1734
- ), /* @__PURE__ */ import_react13.default.createElement(
2252
+ ), /* @__PURE__ */ import_react15.default.createElement(
1735
2253
  "div",
1736
2254
  {
1737
2255
  className: cn(
@@ -1739,7 +2257,7 @@ var Modal = ({
1739
2257
  className
1740
2258
  )
1741
2259
  },
1742
- !hideHeader && /* @__PURE__ */ import_react13.default.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__ */ import_react13.default.createElement("h3", { className: "text-lg font-semibold text-foreground" }, title), /* @__PURE__ */ import_react13.default.createElement(
2260
+ !hideHeader && /* @__PURE__ */ import_react15.default.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__ */ import_react15.default.createElement("h3", { className: "text-lg font-semibold text-foreground" }, title), /* @__PURE__ */ import_react15.default.createElement(
1743
2261
  Button,
1744
2262
  {
1745
2263
  variant: "ghost",
@@ -1747,29 +2265,18 @@ var Modal = ({
1747
2265
  onClick: onClose,
1748
2266
  className: "h-9 w-9 p-0 rounded-xl hover:bg-accent/80 transition-all duration-200"
1749
2267
  },
1750
- /* @__PURE__ */ import_react13.default.createElement(import_lucide_react6.X, { className: "h-4 w-4" }),
1751
- /* @__PURE__ */ import_react13.default.createElement("span", { className: "sr-only" }, "Close")
2268
+ /* @__PURE__ */ import_react15.default.createElement(import_lucide_react6.X, { className: "h-4 w-4" }),
2269
+ /* @__PURE__ */ import_react15.default.createElement("span", { className: "sr-only" }, closeLabel)
1752
2270
  )),
1753
- /* @__PURE__ */ import_react13.default.createElement("div", { className: cn("overflow-y-auto flex-1", !hideHeader && "p-6") }, children)
2271
+ /* @__PURE__ */ import_react15.default.createElement("div", { className: cn("overflow-y-auto flex-1", !hideHeader && "p-6") }, children)
1754
2272
  ));
1755
2273
  };
1756
2274
 
1757
2275
  // src/components/EventModal.tsx
1758
- var import_date_fns13 = require("date-fns");
2276
+ var import_date_fns17 = require("date-fns");
1759
2277
  var import_framer_motion2 = require("framer-motion");
1760
2278
  var import_lucide_react7 = require("lucide-react");
1761
- var REMINDER_OPTIONS = [
1762
- { value: 0, label: "At time of event" },
1763
- { value: 5, label: "5 minutes before" },
1764
- { value: 10, label: "10 minutes before" },
1765
- { value: 15, label: "15 minutes before" },
1766
- { value: 30, label: "30 minutes before" },
1767
- { value: 60, label: "1 hour before" },
1768
- { value: 120, label: "2 hours before" },
1769
- { value: 1440, label: "1 day before" },
1770
- { value: 2880, label: "2 days before" },
1771
- { value: 10080, label: "1 week before" }
1772
- ];
2279
+ var REMINDER_OPTIONS = [0, 5, 10, 15, 30, 60, 120, 1440, 2880, 10080];
1773
2280
  var COLOR_PALETTE = [
1774
2281
  "#3b82f6",
1775
2282
  // Blue
@@ -1792,6 +2299,30 @@ var COLOR_PALETTE = [
1792
2299
  "#6366f1"
1793
2300
  // Indigo
1794
2301
  ];
2302
+ var EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2303
+ var mergeGuests = (current, added) => {
2304
+ const seen = new Set(current.map((email) => email.toLowerCase()));
2305
+ const merged = [...current];
2306
+ for (const email of added) {
2307
+ if (!seen.has(email.toLowerCase())) {
2308
+ seen.add(email.toLowerCase());
2309
+ merged.push(email);
2310
+ }
2311
+ }
2312
+ return merged;
2313
+ };
2314
+ var reminderLabel = (minutes, t) => {
2315
+ if (minutes === 0) return t.reminderAtTime;
2316
+ if (minutes === 10080) return t.reminderWeek;
2317
+ if (minutes === 1440) return t.reminderDay;
2318
+ if (minutes % 1440 === 0) return interpolate(t.reminderDays, { n: minutes / 1440 });
2319
+ if (minutes === 60) return t.reminderHour;
2320
+ if (minutes % 60 === 0) return interpolate(t.reminderHours, { n: minutes / 60 });
2321
+ return interpolate(t.reminderMinutes, { n: minutes });
2322
+ };
2323
+ var avatarHue = (email) => [...email].reduce((hash, char) => (hash * 31 + char.charCodeAt(0)) % 360, 7);
2324
+ var mapsUrl = (location) => `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(location)}`;
2325
+ var isSafeUrl = (url) => /^(https?:|mailto:|blob:|\/|\.\/|\.\.\/|[^:]*$)/i.test(url.trim());
1795
2326
  var EventModal = ({
1796
2327
  isOpen,
1797
2328
  onClose,
@@ -1799,10 +2330,17 @@ var EventModal = ({
1799
2330
  initialDate,
1800
2331
  onSave,
1801
2332
  onDelete,
1802
- calendars
2333
+ calendars,
2334
+ translations: t,
2335
+ locale,
2336
+ initialAllDay
1803
2337
  }) => {
1804
- const [mode, setMode] = (0, import_react14.useState)("create");
1805
- const [formData, setFormData] = (0, import_react14.useState)({
2338
+ const [mode, setMode] = (0, import_react16.useState)("create");
2339
+ const translationsRef = (0, import_react16.useRef)(t);
2340
+ (0, import_react16.useInsertionEffect)(() => {
2341
+ translationsRef.current = t;
2342
+ });
2343
+ const [formData, setFormData] = (0, import_react16.useState)({
1806
2344
  title: "",
1807
2345
  description: "",
1808
2346
  location: "",
@@ -1814,22 +2352,18 @@ var EventModal = ({
1814
2352
  type: void 0,
1815
2353
  recurrence: void 0,
1816
2354
  attachments: [],
1817
- reminders: [{ id: "1", type: "notification", time: 30, label: "30 minutes before" }]
2355
+ reminders: []
1818
2356
  });
1819
- const [isCalendarDropdownOpen, setIsCalendarDropdownOpen] = (0, import_react14.useState)(false);
1820
- const [isColorPickerOpen, setIsColorPickerOpen] = (0, import_react14.useState)(false);
1821
- const [isReminderDropdownOpen, setIsReminderDropdownOpen] = (0, import_react14.useState)(false);
1822
- const [isGuestsDropdownOpen, setIsGuestsDropdownOpen] = (0, import_react14.useState)(false);
1823
- const fakeGuests = [
1824
- "alice@example.com",
1825
- "bob@example.com",
1826
- "charlie@example.com",
1827
- "diana@example.com",
1828
- "evan@example.com"
1829
- ];
1830
- const [selectedGuests, setSelectedGuests] = (0, import_react14.useState)([]);
1831
- (0, import_react14.useEffect)(() => {
2357
+ const [isCalendarDropdownOpen, setIsCalendarDropdownOpen] = (0, import_react16.useState)(false);
2358
+ const [isColorPickerOpen, setIsColorPickerOpen] = (0, import_react16.useState)(false);
2359
+ const [isReminderDropdownOpen, setIsReminderDropdownOpen] = (0, import_react16.useState)(false);
2360
+ const [guestInput, setGuestInput] = (0, import_react16.useState)("");
2361
+ const [guestError, setGuestError] = (0, import_react16.useState)(false);
2362
+ (0, import_react16.useEffect)(() => {
2363
+ const defaultReminders = () => [{ id: "1", type: "notification", time: 30, label: reminderLabel(30, translationsRef.current) }];
1832
2364
  if (isOpen) {
2365
+ setGuestInput("");
2366
+ setGuestError(false);
1833
2367
  if (event) {
1834
2368
  setMode("view");
1835
2369
  setFormData({
@@ -1837,39 +2371,52 @@ var EventModal = ({
1837
2371
  start: new Date(event.start),
1838
2372
  end: new Date(event.end),
1839
2373
  attachments: event.attachments || [],
1840
- reminders: event.reminders || [{ id: "1", type: "notification", time: 30, label: "30 minutes before" }]
2374
+ reminders: event.reminders || defaultReminders(),
2375
+ guests: event.guests || []
1841
2376
  });
1842
- setSelectedGuests(event.guests || []);
1843
2377
  } else {
1844
2378
  setMode("create");
1845
- const start = initialDate || /* @__PURE__ */ new Date();
1846
- const end = new Date(start);
1847
- end.setHours(start.getHours() + 1);
2379
+ const base = initialDate || /* @__PURE__ */ new Date();
2380
+ const start = initialAllDay ? (0, import_date_fns17.startOfDay)(base) : base;
2381
+ const end = initialAllDay ? (0, import_date_fns17.addDays)(start, 1) : new Date(base.getTime() + 60 * 60 * 1e3);
1848
2382
  setFormData({
1849
2383
  title: "",
1850
2384
  description: "",
1851
2385
  location: "",
1852
2386
  start,
1853
2387
  end,
1854
- allDay: false,
2388
+ allDay: !!initialAllDay,
1855
2389
  color: "#3b82f6",
1856
2390
  calendarId: calendars?.[0]?.id,
1857
2391
  attachments: [],
1858
- reminders: [{ id: "1", type: "notification", time: 30, label: "30 minutes before" }]
2392
+ reminders: defaultReminders(),
2393
+ guests: []
1859
2394
  });
1860
- setSelectedGuests([]);
1861
2395
  }
1862
2396
  }
1863
- }, [isOpen, event, initialDate, calendars]);
1864
- const toggleGuest = (email) => {
1865
- setSelectedGuests((prev) => {
1866
- const newGuests = prev.includes(email) ? prev.filter((e) => e !== email) : [...prev, email];
1867
- setFormData((curr) => ({ ...curr, guests: newGuests }));
1868
- return newGuests;
1869
- });
2397
+ }, [isOpen, event, initialDate, calendars, initialAllDay]);
2398
+ const guests = formData.guests || [];
2399
+ const addGuests = (raw) => {
2400
+ const entries = raw.split(/[\s,;]+/).filter(Boolean);
2401
+ const valid = entries.filter((entry) => EMAIL.test(entry));
2402
+ const invalid = entries.filter((entry) => !EMAIL.test(entry));
2403
+ if (valid.length > 0) {
2404
+ setFormData((prev) => ({ ...prev, guests: mergeGuests(prev.guests || [], valid) }));
2405
+ }
2406
+ setGuestInput(invalid.join(", "));
2407
+ setGuestError(invalid.length > 0);
2408
+ return invalid.length === 0;
2409
+ };
2410
+ const removeGuest = (email) => {
2411
+ setFormData((prev) => ({ ...prev, guests: (prev.guests || []).filter((g) => g !== email) }));
1870
2412
  };
1871
2413
  const handleSubmit = (e) => {
1872
2414
  e.preventDefault();
2415
+ const pending = guestInput.split(/[\s,;]+/).filter(Boolean);
2416
+ if (pending.some((entry) => !EMAIL.test(entry))) {
2417
+ addGuests(guestInput);
2418
+ return;
2419
+ }
1873
2420
  let eventColor = formData.color;
1874
2421
  if (formData.calendarId && calendars) {
1875
2422
  const selectedCal = calendars.find((c) => c.id === formData.calendarId);
@@ -1877,8 +2424,10 @@ var EventModal = ({
1877
2424
  eventColor = selectedCal.color;
1878
2425
  }
1879
2426
  }
2427
+ const finalGuests = mergeGuests(guests, pending);
1880
2428
  onSave({
1881
2429
  ...formData,
2430
+ guests: finalGuests,
1882
2431
  color: eventColor,
1883
2432
  id: event?.id
1884
2433
  });
@@ -1892,9 +2441,38 @@ var EventModal = ({
1892
2441
  };
1893
2442
  const formatDateForInput = (date) => {
1894
2443
  if (!date) return "";
1895
- return (0, import_date_fns13.format)(date, "yyyy-MM-dd'T'HH:mm");
2444
+ return (0, import_date_fns17.format)(date, "yyyy-MM-dd'T'HH:mm");
2445
+ };
2446
+ const allDaySpan = formData.allDay && formData.start && formData.end ? dayEventSpan({ ...formData, allDay: true }) : null;
2447
+ const handleAllDayToggle = () => {
2448
+ if (!formData.start || !formData.end) return;
2449
+ if (!formData.allDay) {
2450
+ const firstDay = (0, import_date_fns17.startOfDay)(formData.start);
2451
+ const lastDay = (0, import_date_fns17.startOfDay)(new Date(Math.max(formData.end.getTime() - 1, formData.start.getTime())));
2452
+ setFormData((prev) => ({ ...prev, allDay: true, start: firstDay, end: (0, import_date_fns17.addDays)(lastDay, 1) }));
2453
+ } else {
2454
+ const start = new Date(formData.start);
2455
+ start.setHours(9, 0, 0, 0);
2456
+ setFormData((prev) => ({ ...prev, allDay: false, start, end: new Date(start.getTime() + 60 * 60 * 1e3) }));
2457
+ }
2458
+ };
2459
+ const handleAllDayDateChange = (field, value) => {
2460
+ const [y, m, d] = value.split("-").map(Number);
2461
+ if (!y || !m || !d || !allDaySpan) return;
2462
+ const day = new Date(y, m - 1, d);
2463
+ if (field === "start") {
2464
+ const days = (0, import_date_fns17.differenceInCalendarDays)(allDaySpan.lastDay, allDaySpan.firstDay);
2465
+ setFormData((prev) => ({ ...prev, start: day, end: (0, import_date_fns17.addDays)(day, days + 1) }));
2466
+ } else {
2467
+ const firstDay = day < allDaySpan.firstDay ? day : allDaySpan.firstDay;
2468
+ setFormData((prev) => ({ ...prev, start: firstDay, end: (0, import_date_fns17.addDays)(day, 1) }));
2469
+ }
1896
2470
  };
1897
2471
  const handleDateChange = (field, value) => {
2472
+ if (formData.allDay) {
2473
+ handleAllDayDateChange(field, value);
2474
+ return;
2475
+ }
1898
2476
  const date = new Date(value);
1899
2477
  if (isNaN(date.getTime())) return;
1900
2478
  if (field === "start") {
@@ -1912,12 +2490,12 @@ var EventModal = ({
1912
2490
  }
1913
2491
  }
1914
2492
  };
1915
- const addReminder = (minutes, label) => {
2493
+ const addReminder = (minutes) => {
1916
2494
  const newReminder = {
1917
- id: Math.random().toString(36).substr(2, 9),
2495
+ id: Math.random().toString(36).slice(2, 11),
1918
2496
  type: "notification",
1919
2497
  time: minutes,
1920
- label
2498
+ label: reminderLabel(minutes, t)
1921
2499
  };
1922
2500
  setFormData((prev) => ({
1923
2501
  ...prev,
@@ -1931,25 +2509,28 @@ var EventModal = ({
1931
2509
  reminders: prev.reminders?.filter((r) => r.id !== id)
1932
2510
  }));
1933
2511
  };
1934
- const handleDownload = (attachment) => {
1935
- const element = document.createElement("a");
1936
- const file = new Blob(["Dummy content for " + attachment.name], { type: "text/plain" });
1937
- element.href = URL.createObjectURL(file);
1938
- element.download = attachment.name;
1939
- document.body.appendChild(element);
1940
- element.click();
1941
- document.body.removeChild(element);
1942
- };
1943
2512
  const getDurationText = () => {
1944
2513
  if (!formData.start || !formData.end) return "";
1945
- const mins = (0, import_date_fns13.differenceInMinutes)(formData.end, formData.start);
1946
- if (mins < 60) return `${mins} min`;
2514
+ if (allDaySpan) {
2515
+ const days = (0, import_date_fns17.differenceInCalendarDays)(allDaySpan.lastDay, allDaySpan.firstDay) + 1;
2516
+ return days === 1 ? t.durationDay : interpolate(t.durationDays, { n: days });
2517
+ }
2518
+ const mins = (0, import_date_fns17.differenceInMinutes)(formData.end, formData.start);
2519
+ if (mins < 60) return interpolate(t.durationMinutes, { n: mins });
1947
2520
  const hours = Math.floor(mins / 60);
1948
2521
  const remainingMins = mins % 60;
1949
- if (remainingMins === 0) return `${hours} hr`;
1950
- return `${hours} hr ${remainingMins} min`;
2522
+ if (remainingMins === 0) return interpolate(t.durationHours, { n: hours });
2523
+ return interpolate(t.durationHoursMinutes, { h: hours, m: remainingMins });
1951
2524
  };
1952
- const renderViewMode = () => /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-col bg-background overflow-hidden w-full max-h-[90vh]" }, /* @__PURE__ */ import_react14.default.createElement(
2525
+ const { time: timeFormat } = timeFormats(locale);
2526
+ const viewEvent = event && { ...event, start: new Date(event.start), end: new Date(event.end) };
2527
+ const viewSpan = viewEvent && isDayEvent(viewEvent) ? dayEventSpan(viewEvent) : null;
2528
+ const renderAttachment = (att) => {
2529
+ const content = /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "p-2 bg-primary/10 rounded-lg" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.File, { className: "w-4 h-4 text-primary" })), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-sm font-medium text-foreground truncate" }, att.name), /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-xs text-muted-foreground" }, att.size)), att.url && /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Download, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" }));
2530
+ const className = "flex items-center gap-3 p-3 rounded-xl border border-border/30 bg-muted/20 transition-all group";
2531
+ return att.url && isSafeUrl(att.url) ? /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement("div", { key: att.id, className }, content);
2532
+ };
2533
+ const renderViewMode = () => /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex flex-col bg-background overflow-hidden w-full max-h-[90vh]" }, /* @__PURE__ */ import_react16.default.createElement(
1953
2534
  "div",
1954
2535
  {
1955
2536
  className: "relative px-6 pt-6 pb-8",
@@ -1957,50 +2538,56 @@ var EventModal = ({
1957
2538
  background: `linear-gradient(135deg, ${event?.color || "#3b82f6"}15 0%, transparent 100%)`
1958
2539
  }
1959
2540
  },
1960
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between mb-6" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(
2541
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between mb-6" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement(
1961
2542
  "div",
1962
2543
  {
1963
2544
  className: "w-3 h-3 rounded-full",
1964
2545
  style: { backgroundColor: event?.color || "#3b82f6" }
1965
2546
  }
1966
- ), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider" }, calendars?.find((c) => c.id === event?.calendarId)?.label || "Event")), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react14.default.createElement(
2547
+ ), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider" }, calendars?.find((c) => c.id === event?.calendarId)?.label || t.event)), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react16.default.createElement(
1967
2548
  "button",
1968
2549
  {
1969
2550
  onClick: () => setMode("edit"),
1970
2551
  className: "p-2 hover:bg-background/80 rounded-lg transition-all text-muted-foreground hover:text-foreground",
1971
- title: "Edit"
2552
+ title: t.edit,
2553
+ "aria-label": t.edit
1972
2554
  },
1973
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Edit2, { className: "w-4 h-4" })
1974
- ), /* @__PURE__ */ import_react14.default.createElement(
2555
+ /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Edit2, { className: "w-4 h-4" })
2556
+ ), /* @__PURE__ */ import_react16.default.createElement(
1975
2557
  "button",
1976
2558
  {
1977
2559
  onClick: handleDelete,
1978
2560
  className: "p-2 hover:bg-destructive/10 rounded-lg transition-all text-muted-foreground hover:text-destructive",
1979
- title: "Delete"
2561
+ title: t.delete,
2562
+ "aria-label": t.delete
1980
2563
  },
1981
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Trash2, { className: "w-4 h-4" })
1982
- ), /* @__PURE__ */ import_react14.default.createElement(
2564
+ /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Trash2, { className: "w-4 h-4" })
2565
+ ), /* @__PURE__ */ import_react16.default.createElement(
1983
2566
  "button",
1984
2567
  {
1985
2568
  onClick: onClose,
1986
2569
  className: "p-2 hover:bg-background/80 rounded-lg transition-all text-muted-foreground hover:text-foreground",
1987
- title: "Close"
2570
+ title: t.close,
2571
+ "aria-label": t.close
1988
2572
  },
1989
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.X, { className: "w-4 h-4" })
2573
+ /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.X, { className: "w-4 h-4" })
1990
2574
  ))),
1991
- /* @__PURE__ */ import_react14.default.createElement("h1", { className: "text-2xl font-bold text-foreground mb-3 leading-tight" }, event?.title || "(No title)"),
1992
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-3 text-sm" }, /* @__PURE__ */ import_react14.default.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__ */ import_react14.default.createElement(import_lucide_react7.Calendar, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "font-medium" }, event?.start && (0, import_date_fns13.format)(new Date(event.start), "EEE, MMM d"))), /* @__PURE__ */ import_react14.default.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__ */ import_react14.default.createElement(import_lucide_react7.Clock, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "font-medium" }, event?.start && (0, import_date_fns13.format)(new Date(event.start), "h:mm a"), " \u2013 ", event?.end && (0, import_date_fns13.format)(new Date(event.end), "h:mm a"))))
1993
- ), /* @__PURE__ */ import_react14.default.createElement("div", { className: "px-6 pb-6 space-y-4 overflow-y-auto flex-1" }, event?.location && /* @__PURE__ */ import_react14.default.createElement(
1994
- import_framer_motion2.motion.div,
2575
+ /* @__PURE__ */ import_react16.default.createElement("h1", { className: "text-2xl font-bold text-foreground mb-3 leading-tight" }, event?.title || t.noTitle),
2576
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-3 text-sm" }, /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(import_lucide_react7.Calendar, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react16.default.createElement("span", { className: "font-medium" }, viewSpan && viewSpan.lastDay > viewSpan.firstDay ? `${(0, import_date_fns17.format)(viewSpan.firstDay, "EEE d MMM", { locale })} \u2013 ${(0, import_date_fns17.format)(viewSpan.lastDay, "EEE d MMM", { locale })}` : event?.start && (0, import_date_fns17.format)(new Date(event.start), "EEE, MMM d", { locale }))), event?.allDay ? /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-primary/10 rounded-lg border border-primary/20" }, /* @__PURE__ */ import_react16.default.createElement("span", { className: "font-medium text-primary" }, t.allDay)) : /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(import_lucide_react7.Clock, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react16.default.createElement("span", { className: "font-medium" }, event?.start && (0, import_date_fns17.format)(new Date(event.start), timeFormat, { locale }), " \u2013 ", event?.end && (0, import_date_fns17.format)(new Date(event.end), timeFormat, { locale }))))
2577
+ ), /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pb-6 space-y-4 overflow-y-auto flex-1" }, event?.location && /* @__PURE__ */ import_react16.default.createElement(
2578
+ import_framer_motion2.motion.a,
1995
2579
  {
2580
+ href: mapsUrl(event.location),
2581
+ target: "_blank",
2582
+ rel: "noopener noreferrer",
1996
2583
  initial: { opacity: 0, y: 10 },
1997
2584
  animate: { opacity: 1, y: 0 },
1998
2585
  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"
1999
2586
  },
2000
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "p-2 bg-primary/10 rounded-xl" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.MapPin, { className: "w-5 h-5 text-primary" })),
2001
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex-1" }, /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-sm font-medium text-foreground" }, event.location), /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-xs text-muted-foreground mt-0.5" }, "Click to open in maps")),
2002
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.ExternalLink, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
2003
- ), event?.guests && event.guests.length > 0 && /* @__PURE__ */ import_react14.default.createElement(
2587
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "p-2 bg-primary/10 rounded-xl" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.MapPin, { className: "w-5 h-5 text-primary" })),
2588
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex-1" }, /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-sm font-medium text-foreground" }, event.location), /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-xs text-muted-foreground mt-0.5" }, t.openInMaps)),
2589
+ /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.ExternalLink, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
2590
+ ), event?.guests && event.guests.length > 0 && /* @__PURE__ */ import_react16.default.createElement(
2004
2591
  import_framer_motion2.motion.div,
2005
2592
  {
2006
2593
  initial: { opacity: 0, y: 10 },
@@ -2008,24 +2595,24 @@ var EventModal = ({
2008
2595
  transition: { delay: 0.05 },
2009
2596
  className: "space-y-3"
2010
2597
  },
2011
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Users, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, event.guests.length, " ", event.guests.length > 1 ? "Guests" : "Guest"))),
2012
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-wrap gap-2" }, event.guests.map((email, index) => /* @__PURE__ */ import_react14.default.createElement(
2598
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Users, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-sm font-medium text-foreground" }, event.guests.length, " ", event.guests.length > 1 ? t.guests : t.guestSingular))),
2599
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex flex-wrap gap-2" }, event.guests.map((email) => /* @__PURE__ */ import_react16.default.createElement(
2013
2600
  "div",
2014
2601
  {
2015
- key: index,
2016
- 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"
2602
+ key: email,
2603
+ className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-muted/30 border border-border/30"
2017
2604
  },
2018
- /* @__PURE__ */ import_react14.default.createElement(
2605
+ /* @__PURE__ */ import_react16.default.createElement(
2019
2606
  "div",
2020
2607
  {
2021
2608
  className: "w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold text-white",
2022
- style: { backgroundColor: `hsl(${index * 60}, 70%, 50%)` }
2609
+ style: { backgroundColor: `hsl(${avatarHue(email)}, 70%, 50%)` }
2023
2610
  },
2024
2611
  email[0].toUpperCase()
2025
2612
  ),
2026
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-sm font-medium text-foreground" }, email.split("@")[0]), /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-xs text-muted-foreground truncate" }, email))
2613
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-sm font-medium text-foreground" }, email.split("@")[0]), /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-xs text-muted-foreground truncate" }, email))
2027
2614
  )))
2028
- ), event?.reminders && event.reminders.length > 0 && /* @__PURE__ */ import_react14.default.createElement(
2615
+ ), event?.reminders && event.reminders.length > 0 && /* @__PURE__ */ import_react16.default.createElement(
2029
2616
  import_framer_motion2.motion.div,
2030
2617
  {
2031
2618
  initial: { opacity: 0, y: 10 },
@@ -2033,16 +2620,16 @@ var EventModal = ({
2033
2620
  transition: { delay: 0.1 },
2034
2621
  className: "flex items-center gap-3"
2035
2622
  },
2036
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "p-2 bg-amber-500/10 rounded-xl" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Bell, { className: "w-4 h-4 text-amber-500" })),
2037
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-wrap gap-2" }, event.reminders.map((reminder) => /* @__PURE__ */ import_react14.default.createElement(
2623
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "p-2 bg-amber-500/10 rounded-xl" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Bell, { className: "w-4 h-4 text-amber-500" })),
2624
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex flex-wrap gap-2" }, event.reminders.map((reminder) => /* @__PURE__ */ import_react16.default.createElement(
2038
2625
  "span",
2039
2626
  {
2040
2627
  key: reminder.id,
2041
2628
  className: "text-xs font-medium px-2.5 py-1 rounded-full bg-amber-500/10 text-amber-600 dark:text-amber-400"
2042
2629
  },
2043
- reminder.label || `${reminder.time} min before`
2630
+ reminder.label || reminderLabel(reminder.time, t)
2044
2631
  )))
2045
- ), event?.description && /* @__PURE__ */ import_react14.default.createElement(
2632
+ ), event?.description && /* @__PURE__ */ import_react16.default.createElement(
2046
2633
  import_framer_motion2.motion.div,
2047
2634
  {
2048
2635
  initial: { opacity: 0, y: 10 },
@@ -2050,9 +2637,9 @@ var EventModal = ({
2050
2637
  transition: { delay: 0.15 },
2051
2638
  className: "space-y-2"
2052
2639
  },
2053
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Notes")),
2054
- /* @__PURE__ */ import_react14.default.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)
2055
- ), event?.attachments && event.attachments.length > 0 && /* @__PURE__ */ import_react14.default.createElement(
2640
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-sm font-medium text-foreground" }, t.notesLabel)),
2641
+ /* @__PURE__ */ import_react16.default.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)
2642
+ ), event?.attachments && event.attachments.length > 0 && /* @__PURE__ */ import_react16.default.createElement(
2056
2643
  import_framer_motion2.motion.div,
2057
2644
  {
2058
2645
  initial: { opacity: 0, y: 10 },
@@ -2060,27 +2647,18 @@ var EventModal = ({
2060
2647
  transition: { delay: 0.2 },
2061
2648
  className: "space-y-2"
2062
2649
  },
2063
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Paperclip, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Attachments")),
2064
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "grid gap-2" }, event.attachments.map((att) => /* @__PURE__ */ import_react14.default.createElement(
2065
- "div",
2066
- {
2067
- key: att.id,
2068
- onClick: () => handleDownload(att),
2069
- 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"
2070
- },
2071
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "p-2 bg-primary/10 rounded-lg" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.File, { className: "w-4 h-4 text-primary" })),
2072
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-sm font-medium text-foreground truncate" }, att.name), /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-xs text-muted-foreground" }, att.size)),
2073
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Download, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
2074
- )))
2650
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Paperclip, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-sm font-medium text-foreground" }, t.attachments)),
2651
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "grid gap-2" }, event.attachments.map(renderAttachment))
2075
2652
  )));
2076
- const renderEditMode = () => /* @__PURE__ */ import_react14.default.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col bg-background overflow-hidden w-full max-h-[85vh]" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between px-5 py-4 border-b border-border/50 shrink-0" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react14.default.createElement(
2653
+ const renderEditMode = () => /* @__PURE__ */ import_react16.default.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col bg-background overflow-hidden w-full max-h-[85vh]" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between px-5 py-4 border-b border-border/50 shrink-0" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react16.default.createElement(
2077
2654
  "button",
2078
2655
  {
2079
2656
  type: "button",
2080
2657
  onClick: () => setIsColorPickerOpen(!isColorPickerOpen),
2081
- className: "relative p-1"
2658
+ className: "relative p-1",
2659
+ "aria-label": t.eventColor
2082
2660
  },
2083
- /* @__PURE__ */ import_react14.default.createElement(
2661
+ /* @__PURE__ */ import_react16.default.createElement(
2084
2662
  "div",
2085
2663
  {
2086
2664
  className: "w-5 h-5 rounded-full cursor-pointer hover:scale-110 transition-transform",
@@ -2090,11 +2668,12 @@ var EventModal = ({
2090
2668
  }
2091
2669
  }
2092
2670
  ),
2093
- isColorPickerOpen && /* @__PURE__ */ import_react14.default.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__ */ import_react14.default.createElement(
2671
+ isColorPickerOpen && /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(
2094
2672
  "button",
2095
2673
  {
2096
2674
  key: color,
2097
2675
  type: "button",
2676
+ "aria-label": color,
2098
2677
  onClick: () => {
2099
2678
  setFormData((prev) => ({ ...prev, color }));
2100
2679
  setIsColorPickerOpen(false);
@@ -2106,15 +2685,16 @@ var EventModal = ({
2106
2685
  style: { backgroundColor: color, color }
2107
2686
  }
2108
2687
  )))
2109
- ), /* @__PURE__ */ import_react14.default.createElement("h2", { className: "text-lg font-semibold text-foreground" }, mode === "edit" ? "Edit Event" : "New Event")), /* @__PURE__ */ import_react14.default.createElement(
2688
+ ), /* @__PURE__ */ import_react16.default.createElement("h2", { className: "text-lg font-semibold text-foreground" }, mode === "edit" ? t.editEvent : t.newEvent)), /* @__PURE__ */ import_react16.default.createElement(
2110
2689
  "button",
2111
2690
  {
2112
2691
  type: "button",
2113
2692
  onClick: onClose,
2114
- className: "p-2 hover:bg-accent rounded-xl transition-all text-muted-foreground hover:text-foreground"
2693
+ className: "p-2 hover:bg-accent rounded-xl transition-all text-muted-foreground hover:text-foreground",
2694
+ "aria-label": t.close
2115
2695
  },
2116
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.X, { className: "w-4 h-4" })
2117
- )), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex-1 overflow-y-auto" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "px-5 py-4 space-y-5" }, /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement(
2696
+ /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.X, { className: "w-4 h-4" })
2697
+ )), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex-1 overflow-y-auto" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-5 py-4 space-y-5" }, /* @__PURE__ */ import_react16.default.createElement("div", null, /* @__PURE__ */ import_react16.default.createElement(
2118
2698
  "input",
2119
2699
  {
2120
2700
  type: "text",
@@ -2123,132 +2703,160 @@ var EventModal = ({
2123
2703
  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",
2124
2704
  value: formData.title,
2125
2705
  onChange: (e) => setFormData({ ...formData, title: e.target.value }),
2126
- placeholder: "Add title"
2706
+ placeholder: t.title,
2707
+ "aria-label": t.title
2127
2708
  }
2128
- )), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-3 p-4 rounded-2xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "p-2 bg-primary/10 rounded-xl shrink-0" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Clock, { className: "w-5 h-5 text-primary" })), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex-1 grid grid-cols-2 gap-3" }, /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement("label", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, "Start"), /* @__PURE__ */ import_react14.default.createElement(
2709
+ )), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between px-1" }, /* @__PURE__ */ import_react16.default.createElement("span", { id: "calendarkit-all-day-label", className: "text-sm font-medium text-foreground" }, t.allDay), /* @__PURE__ */ import_react16.default.createElement(
2710
+ "button",
2711
+ {
2712
+ type: "button",
2713
+ role: "switch",
2714
+ "aria-checked": !!formData.allDay,
2715
+ "aria-labelledby": "calendarkit-all-day-label",
2716
+ onClick: handleAllDayToggle,
2717
+ className: cn(
2718
+ "relative inline-flex h-6 w-11 shrink-0 rounded-full border-2 border-transparent transition-colors cursor-pointer",
2719
+ formData.allDay ? "bg-primary" : "bg-muted"
2720
+ )
2721
+ },
2722
+ /* @__PURE__ */ import_react16.default.createElement(
2723
+ "span",
2724
+ {
2725
+ className: cn(
2726
+ "pointer-events-none inline-block h-5 w-5 rounded-full bg-background shadow transition-transform",
2727
+ formData.allDay ? "translate-x-5" : "translate-x-0"
2728
+ )
2729
+ }
2730
+ )
2731
+ )), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-3 p-4 rounded-2xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "p-2 bg-primary/10 rounded-xl shrink-0" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Clock, { className: "w-5 h-5 text-primary" })), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex-1 grid grid-cols-2 gap-3" }, /* @__PURE__ */ import_react16.default.createElement("div", null, /* @__PURE__ */ import_react16.default.createElement("label", { htmlFor: "calendarkit-event-start", className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, t.start), /* @__PURE__ */ import_react16.default.createElement(
2129
2732
  "input",
2130
2733
  {
2131
- type: "datetime-local",
2734
+ id: "calendarkit-event-start",
2735
+ type: allDaySpan ? "date" : "datetime-local",
2132
2736
  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",
2133
- value: formatDateForInput(formData.start),
2737
+ value: allDaySpan ? (0, import_date_fns17.format)(allDaySpan.firstDay, "yyyy-MM-dd") : formatDateForInput(formData.start),
2134
2738
  onChange: (e) => handleDateChange("start", e.target.value)
2135
2739
  }
2136
- )), /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement("label", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, "End"), /* @__PURE__ */ import_react14.default.createElement(
2740
+ )), /* @__PURE__ */ import_react16.default.createElement("div", null, /* @__PURE__ */ import_react16.default.createElement("label", { htmlFor: "calendarkit-event-end", className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, t.end), /* @__PURE__ */ import_react16.default.createElement(
2137
2741
  "input",
2138
2742
  {
2139
- type: "datetime-local",
2743
+ id: "calendarkit-event-end",
2744
+ type: allDaySpan ? "date" : "datetime-local",
2140
2745
  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",
2141
- value: formatDateForInput(formData.end),
2746
+ value: allDaySpan ? (0, import_date_fns17.format)(allDaySpan.lastDay, "yyyy-MM-dd") : formatDateForInput(formData.end),
2142
2747
  onChange: (e) => handleDateChange("end", e.target.value)
2143
2748
  }
2144
- )))), getDurationText() && /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex justify-center" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs font-medium px-3 py-1 rounded-full bg-primary/10 text-primary" }, getDurationText())), /* @__PURE__ */ import_react14.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Bell, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Reminders")), /* @__PURE__ */ import_react14.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react14.default.createElement(
2749
+ )))), getDurationText() && /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex justify-center" }, /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-xs font-medium px-3 py-1 rounded-full bg-primary/10 text-primary" }, getDurationText())), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Bell, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-sm font-medium text-foreground" }, t.reminders)), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react16.default.createElement(
2145
2750
  "button",
2146
2751
  {
2147
2752
  type: "button",
2148
2753
  onClick: () => setIsReminderDropdownOpen(!isReminderDropdownOpen),
2149
2754
  className: "flex items-center gap-1 text-xs font-medium text-primary hover:text-primary/80 transition-colors"
2150
2755
  },
2151
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Plus, { className: "w-3.5 h-3.5" }),
2152
- "Add"
2153
- ), isReminderDropdownOpen && /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, /* @__PURE__ */ import_react14.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsReminderDropdownOpen(false) }), /* @__PURE__ */ import_react14.default.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__ */ import_react14.default.createElement(
2756
+ /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Plus, { className: "w-3.5 h-3.5" }),
2757
+ t.add
2758
+ ), isReminderDropdownOpen && /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsReminderDropdownOpen(false) }), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(
2154
2759
  "button",
2155
2760
  {
2156
- key: option.value,
2761
+ key: minutes,
2157
2762
  type: "button",
2158
- onClick: () => addReminder(option.value, option.label),
2763
+ onClick: () => addReminder(minutes),
2159
2764
  className: "w-full px-3 py-2 text-left text-sm hover:bg-accent transition-colors"
2160
2765
  },
2161
- option.label
2162
- )))))), formData.reminders && formData.reminders.length > 0 && /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-wrap gap-2" }, formData.reminders.map((reminder) => /* @__PURE__ */ import_react14.default.createElement(
2766
+ reminderLabel(minutes, t)
2767
+ )))))), formData.reminders && formData.reminders.length > 0 && /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex flex-wrap gap-2" }, formData.reminders.map((reminder) => /* @__PURE__ */ import_react16.default.createElement(
2163
2768
  "div",
2164
2769
  {
2165
2770
  key: reminder.id,
2166
2771
  className: "flex items-center gap-2 px-3 py-1.5 rounded-full bg-amber-500/10 border border-amber-500/20"
2167
2772
  },
2168
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.BellRing, { className: "w-3.5 h-3.5 text-amber-500" }),
2169
- /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400" }, reminder.label),
2170
- /* @__PURE__ */ import_react14.default.createElement(
2773
+ /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.BellRing, { className: "w-3.5 h-3.5 text-amber-500" }),
2774
+ /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400" }, reminder.label || reminderLabel(reminder.time, t)),
2775
+ /* @__PURE__ */ import_react16.default.createElement(
2171
2776
  "button",
2172
2777
  {
2173
2778
  type: "button",
2174
2779
  onClick: () => removeReminder(reminder.id),
2175
- className: "p-0.5 hover:bg-amber-500/20 rounded-full transition-colors"
2780
+ className: "p-0.5 hover:bg-amber-500/20 rounded-full transition-colors",
2781
+ "aria-label": t.removeReminder
2176
2782
  },
2177
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.X, { className: "w-3 h-3 text-amber-500" })
2783
+ /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.X, { className: "w-3 h-3 text-amber-500" })
2178
2784
  )
2179
- )))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Users, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Guests")), /* @__PURE__ */ import_react14.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react14.default.createElement(
2180
- "button",
2181
- {
2182
- type: "button",
2183
- onClick: () => setIsGuestsDropdownOpen(!isGuestsDropdownOpen),
2184
- 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"
2185
- },
2186
- /* @__PURE__ */ import_react14.default.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"),
2187
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.ChevronDown, { className: cn("w-4 h-4 text-muted-foreground transition-transform", isGuestsDropdownOpen && "rotate-180") })
2188
- ), isGuestsDropdownOpen && /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, /* @__PURE__ */ import_react14.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsGuestsDropdownOpen(false) }), /* @__PURE__ */ import_react14.default.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__ */ import_react14.default.createElement(
2189
- "div",
2785
+ )))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Users, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react16.default.createElement("label", { htmlFor: "calendarkit-event-guest", className: "text-sm font-medium text-foreground" }, t.guests)), /* @__PURE__ */ import_react16.default.createElement(
2786
+ "input",
2190
2787
  {
2191
- key: email,
2192
- className: "px-4 py-3 hover:bg-accent cursor-pointer flex items-center gap-3 transition-colors",
2193
- onClick: () => toggleGuest(email)
2194
- },
2195
- /* @__PURE__ */ import_react14.default.createElement("div", { className: cn(
2196
- "w-5 h-5 rounded-md border-2 flex items-center justify-center transition-all",
2197
- selectedGuests.includes(email) ? "bg-primary border-primary" : "border-border"
2198
- ) }, selectedGuests.includes(email) && /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Check, { className: "w-3 h-3 text-primary-foreground" })),
2199
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(
2200
- "div",
2201
- {
2202
- className: "w-7 h-7 rounded-full flex items-center justify-center text-xs font-semibold text-white",
2203
- style: { backgroundColor: `hsl(${fakeGuests.indexOf(email) * 60}, 70%, 50%)` }
2788
+ id: "calendarkit-event-guest",
2789
+ type: "text",
2790
+ inputMode: "email",
2791
+ autoComplete: "email",
2792
+ value: guestInput,
2793
+ onChange: (e) => {
2794
+ setGuestInput(e.target.value);
2795
+ setGuestError(false);
2204
2796
  },
2205
- email[0].toUpperCase()
2206
- ), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm" }, email))
2207
- ))))), selectedGuests.length > 0 && /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, selectedGuests.map((email) => /* @__PURE__ */ import_react14.default.createElement(
2797
+ onKeyDown: (e) => {
2798
+ if (e.key === "Enter" || e.key === ",") {
2799
+ e.preventDefault();
2800
+ addGuests(guestInput);
2801
+ }
2802
+ },
2803
+ onBlur: () => guestInput.trim() && addGuests(guestInput),
2804
+ placeholder: t.addGuestPlaceholder,
2805
+ "aria-invalid": guestError,
2806
+ className: cn(
2807
+ "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",
2808
+ guestError ? "border-destructive" : "border-border/30"
2809
+ )
2810
+ }
2811
+ ), guestError && /* @__PURE__ */ import_react16.default.createElement("p", { role: "alert", className: "text-xs text-destructive" }, t.invalidEmail), guests.length > 0 && /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, guests.map((email) => /* @__PURE__ */ import_react16.default.createElement(
2208
2812
  "div",
2209
2813
  {
2210
2814
  key: email,
2211
2815
  className: "flex items-center gap-2 pl-1 pr-2 py-1 bg-muted/30 border border-border/30 rounded-full"
2212
2816
  },
2213
- /* @__PURE__ */ import_react14.default.createElement(
2817
+ /* @__PURE__ */ import_react16.default.createElement(
2214
2818
  "div",
2215
2819
  {
2216
2820
  className: "w-6 h-6 rounded-full flex items-center justify-center text-xs font-semibold text-white",
2217
- style: { backgroundColor: `hsl(${fakeGuests.indexOf(email) * 60}, 70%, 50%)` }
2821
+ style: { backgroundColor: `hsl(${avatarHue(email)}, 70%, 50%)` }
2218
2822
  },
2219
2823
  email[0].toUpperCase()
2220
2824
  ),
2221
- /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs font-medium text-foreground" }, email.split("@")[0]),
2222
- /* @__PURE__ */ import_react14.default.createElement(
2825
+ /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-xs font-medium text-foreground" }, email),
2826
+ /* @__PURE__ */ import_react16.default.createElement(
2223
2827
  "button",
2224
2828
  {
2225
2829
  type: "button",
2226
- onClick: () => toggleGuest(email),
2227
- className: "p-0.5 hover:bg-destructive/10 rounded-full transition-colors"
2830
+ onClick: () => removeGuest(email),
2831
+ className: "p-0.5 hover:bg-destructive/10 rounded-full transition-colors",
2832
+ "aria-label": interpolate(t.removeGuest, { email })
2228
2833
  },
2229
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.X, { className: "w-3 h-3 text-muted-foreground" })
2834
+ /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.X, { className: "w-3 h-3 text-muted-foreground" })
2230
2835
  )
2231
- )))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.MapPin, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ import_react14.default.createElement(
2836
+ )))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.MapPin, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ import_react16.default.createElement(
2232
2837
  "input",
2233
2838
  {
2234
2839
  type: "text",
2235
2840
  className: "flex-1 bg-transparent text-sm text-foreground placeholder-muted-foreground focus:outline-none",
2236
- placeholder: "Add location",
2841
+ placeholder: t.addLocation,
2842
+ "aria-label": t.addLocation,
2237
2843
  value: formData.location || "",
2238
2844
  onChange: (e) => setFormData({ ...formData, location: e.target.value })
2239
2845
  }
2240
- )), /* @__PURE__ */ import_react14.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Notes")), /* @__PURE__ */ import_react14.default.createElement(
2846
+ )), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-sm font-medium text-foreground" }, t.notesLabel)), /* @__PURE__ */ import_react16.default.createElement(
2241
2847
  "textarea",
2242
2848
  {
2243
2849
  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",
2244
- placeholder: "Add description or notes...",
2850
+ placeholder: t.addNotes,
2851
+ "aria-label": t.notesLabel,
2245
2852
  value: formData.description || "",
2246
2853
  onChange: (e) => setFormData({ ...formData, description: e.target.value })
2247
2854
  }
2248
- )), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Repeat, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ import_react14.default.createElement(
2855
+ )), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Repeat, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ import_react16.default.createElement(
2249
2856
  "select",
2250
2857
  {
2251
2858
  className: "flex-1 bg-transparent text-sm text-foreground focus:outline-none cursor-pointer",
2859
+ "aria-label": t.repeat,
2252
2860
  value: formData.recurrence?.freq || "",
2253
2861
  onChange: (e) => {
2254
2862
  if (e.target.value === "") {
@@ -2264,28 +2872,28 @@ var EventModal = ({
2264
2872
  }
2265
2873
  }
2266
2874
  },
2267
- /* @__PURE__ */ import_react14.default.createElement("option", { value: "" }, "Does not repeat"),
2268
- /* @__PURE__ */ import_react14.default.createElement("option", { value: "DAILY" }, "Daily"),
2269
- /* @__PURE__ */ import_react14.default.createElement("option", { value: "WEEKLY" }, "Weekly"),
2270
- /* @__PURE__ */ import_react14.default.createElement("option", { value: "MONTHLY" }, "Monthly"),
2271
- /* @__PURE__ */ import_react14.default.createElement("option", { value: "YEARLY" }, "Yearly")
2272
- )), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Tag, { className: "w-5 h-5 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm text-foreground" }, "Calendar")), /* @__PURE__ */ import_react14.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react14.default.createElement(
2875
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "" }, t.doesNotRepeat),
2876
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "DAILY" }, t.daily),
2877
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "WEEKLY" }, t.weekly),
2878
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "MONTHLY" }, t.monthly),
2879
+ /* @__PURE__ */ import_react16.default.createElement("option", { value: "YEARLY" }, t.yearly)
2880
+ )), calendars && calendars.length > 0 && /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Tag, { className: "w-5 h-5 text-muted-foreground" }), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-sm text-foreground" }, t.calendar)), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react16.default.createElement(
2273
2881
  "button",
2274
2882
  {
2275
2883
  type: "button",
2276
2884
  onClick: () => setIsCalendarDropdownOpen(!isCalendarDropdownOpen),
2277
2885
  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"
2278
2886
  },
2279
- /* @__PURE__ */ import_react14.default.createElement(
2887
+ /* @__PURE__ */ import_react16.default.createElement(
2280
2888
  "div",
2281
2889
  {
2282
2890
  className: "w-3 h-3 rounded-full",
2283
- style: { backgroundColor: calendars?.find((c) => c.id === formData.calendarId)?.color || "#3b82f6" }
2891
+ style: { backgroundColor: calendars.find((c) => c.id === formData.calendarId)?.color || "#3b82f6" }
2284
2892
  }
2285
2893
  ),
2286
- /* @__PURE__ */ import_react14.default.createElement("span", { className: "font-medium" }, calendars?.find((c) => c.id === formData.calendarId)?.label || "Select"),
2287
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.ChevronDown, { className: "w-3.5 h-3.5 text-muted-foreground" })
2288
- ), isCalendarDropdownOpen && /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, /* @__PURE__ */ import_react14.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsCalendarDropdownOpen(false) }), /* @__PURE__ */ import_react14.default.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__ */ import_react14.default.createElement(
2894
+ /* @__PURE__ */ import_react16.default.createElement("span", { className: "font-medium" }, calendars.find((c) => c.id === formData.calendarId)?.label || t.select),
2895
+ /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.ChevronDown, { className: "w-3.5 h-3.5 text-muted-foreground" })
2896
+ ), isCalendarDropdownOpen && /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsCalendarDropdownOpen(false) }), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(
2289
2897
  "button",
2290
2898
  {
2291
2899
  key: cal.id,
@@ -2300,35 +2908,35 @@ var EventModal = ({
2300
2908
  setIsCalendarDropdownOpen(false);
2301
2909
  }
2302
2910
  },
2303
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "w-3 h-3 rounded-full", style: { backgroundColor: cal.color } }),
2304
- /* @__PURE__ */ import_react14.default.createElement("span", { className: "flex-1 text-sm" }, cal.label),
2305
- formData.calendarId === cal.id && /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Check, { className: "w-4 h-4 text-primary" })
2306
- )))))))), /* @__PURE__ */ import_react14.default.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__ */ import_react14.default.createElement(
2911
+ /* @__PURE__ */ import_react16.default.createElement("div", { className: "w-3 h-3 rounded-full", style: { backgroundColor: cal.color } }),
2912
+ /* @__PURE__ */ import_react16.default.createElement("span", { className: "flex-1 text-sm" }, cal.label),
2913
+ formData.calendarId === cal.id && /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Check, { className: "w-4 h-4 text-primary" })
2914
+ )))))))), /* @__PURE__ */ import_react16.default.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__ */ import_react16.default.createElement(
2307
2915
  "button",
2308
2916
  {
2309
2917
  type: "button",
2310
2918
  onClick: handleDelete,
2311
2919
  className: "flex items-center gap-2 px-4 py-2 text-destructive hover:bg-destructive/10 rounded-xl transition-all text-sm font-medium"
2312
2920
  },
2313
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Trash2, { className: "w-4 h-4" }),
2314
- "Delete"
2315
- ), mode === "create" && /* @__PURE__ */ import_react14.default.createElement("div", null), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(
2921
+ /* @__PURE__ */ import_react16.default.createElement(import_lucide_react7.Trash2, { className: "w-4 h-4" }),
2922
+ t.delete
2923
+ ), mode === "create" && /* @__PURE__ */ import_react16.default.createElement("div", null), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement(
2316
2924
  "button",
2317
2925
  {
2318
2926
  type: "button",
2319
2927
  onClick: onClose,
2320
2928
  className: "px-4 py-2.5 text-muted-foreground hover:text-foreground font-medium text-sm rounded-xl transition-all hover:bg-accent"
2321
2929
  },
2322
- "Cancel"
2323
- ), /* @__PURE__ */ import_react14.default.createElement(
2930
+ t.cancel
2931
+ ), /* @__PURE__ */ import_react16.default.createElement(
2324
2932
  "button",
2325
2933
  {
2326
2934
  type: "submit",
2327
2935
  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"
2328
2936
  },
2329
- mode === "edit" ? "Save Changes" : "Create Event"
2937
+ mode === "edit" ? t.saveChanges : t.createEvent
2330
2938
  ))));
2331
- return /* @__PURE__ */ import_react14.default.createElement(Modal, { isOpen, onClose, hideHeader: true, className: "p-0 overflow-hidden max-w-lg rounded-2xl shadow-2xl" }, /* @__PURE__ */ import_react14.default.createElement(import_framer_motion2.AnimatePresence, { mode: "wait" }, mode === "view" && event ? /* @__PURE__ */ import_react14.default.createElement(
2939
+ return /* @__PURE__ */ import_react16.default.createElement(Modal, { isOpen, onClose, hideHeader: true, className: "p-0 overflow-hidden max-w-lg rounded-2xl shadow-2xl" }, /* @__PURE__ */ import_react16.default.createElement(import_framer_motion2.AnimatePresence, { mode: "wait" }, mode === "view" && event ? /* @__PURE__ */ import_react16.default.createElement(
2332
2940
  import_framer_motion2.motion.div,
2333
2941
  {
2334
2942
  key: "view",
@@ -2338,7 +2946,7 @@ var EventModal = ({
2338
2946
  transition: { duration: 0.15 }
2339
2947
  },
2340
2948
  renderViewMode()
2341
- ) : /* @__PURE__ */ import_react14.default.createElement(
2949
+ ) : /* @__PURE__ */ import_react16.default.createElement(
2342
2950
  import_framer_motion2.motion.div,
2343
2951
  {
2344
2952
  key: "edit",
@@ -2352,10 +2960,10 @@ var EventModal = ({
2352
2960
  };
2353
2961
 
2354
2962
  // src/components/Skeleton.tsx
2355
- var import_react15 = __toESM(require("react"));
2356
- var Skeleton = ({ className, style }) => /* @__PURE__ */ import_react15.default.createElement("div", { className: cn("animate-pulse bg-muted/40 rounded", className), style });
2357
- var MonthViewSkeleton = () => /* @__PURE__ */ import_react15.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "grid grid-cols-7 border-b border-border/50 bg-muted/10" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-4 w-8 mx-auto" })))), /* @__PURE__ */ import_react15.default.createElement("div", { className: "grid grid-cols-7 flex-1" }, Array.from({ length: 35 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "min-h-[120px] border-r border-b border-border/30 p-2" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-4 w-6 mb-2" }), /* @__PURE__ */ import_react15.default.createElement("div", { className: "space-y-1" }, Math.random() > 0.5 && /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-5 w-full rounded-md" }), Math.random() > 0.7 && /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-5 w-3/4 rounded-md" }))))));
2358
- var WeekViewSkeleton = () => /* @__PURE__ */ import_react15.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex border-b border-border/50 bg-muted/10" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "w-16 p-3 border-r border-border/30" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-8 w-10 mx-auto" })), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex-1 grid grid-cols-7" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-3 w-8 mx-auto mb-1" }), /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-8 w-8 mx-auto rounded-xl" }))))), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "w-16 border-r border-border/30" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "h-[60px] relative" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-4 w-10 absolute right-2 -translate-y-1/2" })))), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, Array.from({ length: 7 }).map((_, colIdx) => /* @__PURE__ */ import_react15.default.createElement("div", { key: colIdx, className: "relative border-r border-border/30 last:border-r-0" }, Array.from({ length: 10 }).map((_2, rowIdx) => /* @__PURE__ */ import_react15.default.createElement("div", { key: rowIdx, className: "h-[60px] border-b border-dashed border-border/20" })), Math.random() > 0.3 && /* @__PURE__ */ import_react15.default.createElement(
2963
+ var import_react17 = __toESM(require("react"));
2964
+ var Skeleton = ({ className, style }) => /* @__PURE__ */ import_react17.default.createElement("div", { className: cn("animate-pulse bg-muted/40 rounded", className), style });
2965
+ var MonthViewSkeleton = () => /* @__PURE__ */ import_react17.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "grid grid-cols-7 border-b border-border/50 bg-muted/10" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ import_react17.default.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-4 w-8 mx-auto" })))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "grid grid-cols-7 flex-1" }, Array.from({ length: 35 }).map((_, i) => /* @__PURE__ */ import_react17.default.createElement("div", { key: i, className: "min-h-[120px] border-r border-b border-border/30 p-2" }, /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-4 w-6 mb-2" }), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1" }, i * 7 % 10 > 4 && /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-5 w-full rounded-md" }), i * 3 % 10 > 6 && /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-5 w-3/4 rounded-md" }))))));
2966
+ var WeekViewSkeleton = () => /* @__PURE__ */ import_react17.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex border-b border-border/50 bg-muted/10" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "w-16 p-3 border-r border-border/30" }, /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-8 w-10 mx-auto" })), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex-1 grid grid-cols-7" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ import_react17.default.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-3 w-8 mx-auto mb-1" }), /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-8 w-8 mx-auto rounded-xl" }))))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "w-16 border-r border-border/30" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ import_react17.default.createElement("div", { key: i, className: "h-[60px] relative" }, /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-4 w-10 absolute right-2 -translate-y-1/2" })))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, Array.from({ length: 7 }).map((_, colIdx) => /* @__PURE__ */ import_react17.default.createElement("div", { key: colIdx, className: "relative border-r border-border/30 last:border-r-0" }, Array.from({ length: 10 }).map((_2, rowIdx) => /* @__PURE__ */ import_react17.default.createElement("div", { key: rowIdx, className: "h-[60px] border-b border-dashed border-border/20" })), Math.random() > 0.3 && /* @__PURE__ */ import_react17.default.createElement(
2359
2967
  Skeleton,
2360
2968
  {
2361
2969
  className: "absolute rounded-md",
@@ -2367,23 +2975,23 @@ var WeekViewSkeleton = () => /* @__PURE__ */ import_react15.default.createElemen
2367
2975
  }
2368
2976
  }
2369
2977
  ))))));
2370
- var DayViewSkeleton = () => /* @__PURE__ */ import_react15.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "px-6 py-4 border-b border-border/50 bg-muted/10 text-center" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-7 w-64 mx-auto" })), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "w-20 border-r border-border/30 bg-muted/5" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "h-[80px] relative" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-4 w-12 absolute left-1/2 -translate-x-1/2 -translate-y-1/2" })))), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex-1 relative" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "h-[80px] border-b border-dashed border-border/20" })), /* @__PURE__ */ import_react15.default.createElement(
2978
+ var DayViewSkeleton = () => /* @__PURE__ */ import_react17.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "px-6 py-4 border-b border-border/50 bg-muted/10 text-center" }, /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-7 w-64 mx-auto" })), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "w-20 border-r border-border/30 bg-muted/5" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ import_react17.default.createElement("div", { key: i, className: "h-[80px] relative" }, /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-4 w-12 absolute left-1/2 -translate-x-1/2 -translate-y-1/2" })))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex-1 relative" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ import_react17.default.createElement("div", { key: i, className: "h-[80px] border-b border-dashed border-border/20" })), /* @__PURE__ */ import_react17.default.createElement(
2371
2979
  Skeleton,
2372
2980
  {
2373
2981
  className: "absolute rounded-lg left-4 right-4",
2374
2982
  style: { top: "160px", height: "120px" }
2375
2983
  }
2376
- ), /* @__PURE__ */ import_react15.default.createElement(
2984
+ ), /* @__PURE__ */ import_react17.default.createElement(
2377
2985
  Skeleton,
2378
2986
  {
2379
2987
  className: "absolute rounded-lg left-4 right-4",
2380
2988
  style: { top: "400px", height: "80px" }
2381
2989
  }
2382
2990
  ))));
2383
- var AgendaViewSkeleton = () => /* @__PURE__ */ import_react15.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden p-6" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "space-y-6" }, Array.from({ length: 4 }).map((_, dayIdx) => /* @__PURE__ */ import_react15.default.createElement("div", { key: dayIdx }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-5 w-40 mb-4" }), /* @__PURE__ */ import_react15.default.createElement("div", { className: "space-y-3" }, Array.from({ length: 2 + Math.floor(Math.random() * 3) }).map((_2, eventIdx) => /* @__PURE__ */ import_react15.default.createElement("div", { key: eventIdx, className: "flex items-center gap-4 p-3 rounded-xl bg-muted/10" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-10 w-10 rounded-lg" }), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex-1 space-y-2" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-4 w-3/4" }), /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-3 w-1/2" })))))))));
2991
+ var AgendaViewSkeleton = () => /* @__PURE__ */ import_react17.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden p-6" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-6" }, Array.from({ length: 4 }).map((_, dayIdx) => /* @__PURE__ */ import_react17.default.createElement("div", { key: dayIdx }, /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-5 w-40 mb-4" }), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-3" }, Array.from({ length: 2 + Math.floor(Math.random() * 3) }).map((_2, eventIdx) => /* @__PURE__ */ import_react17.default.createElement("div", { key: eventIdx, className: "flex items-center gap-4 p-3 rounded-xl bg-muted/10" }, /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-10 w-10 rounded-lg" }), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex-1 space-y-2" }, /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-4 w-3/4" }), /* @__PURE__ */ import_react17.default.createElement(Skeleton, { className: "h-3 w-1/2" })))))))));
2384
2992
 
2385
2993
  // src/components/ContextMenu.tsx
2386
- var import_react16 = __toESM(require("react"));
2994
+ var import_react18 = __toESM(require("react"));
2387
2995
  var import_lucide_react8 = require("lucide-react");
2388
2996
  var import_framer_motion3 = require("framer-motion");
2389
2997
  var EventContextMenu = ({
@@ -2396,8 +3004,8 @@ var EventContextMenu = ({
2396
3004
  customActions = [],
2397
3005
  translations
2398
3006
  }) => {
2399
- const menuRef = (0, import_react16.useRef)(null);
2400
- (0, import_react16.useEffect)(() => {
3007
+ const menuRef = (0, import_react18.useRef)(null);
3008
+ (0, import_react18.useEffect)(() => {
2401
3009
  const handleKeyDown = (e) => {
2402
3010
  if (e.key === "Escape") {
2403
3011
  onClose();
@@ -2408,7 +3016,7 @@ var EventContextMenu = ({
2408
3016
  return () => document.removeEventListener("keydown", handleKeyDown);
2409
3017
  }
2410
3018
  }, [position, onClose]);
2411
- (0, import_react16.useEffect)(() => {
3019
+ (0, import_react18.useEffect)(() => {
2412
3020
  const handleClickOutside = (e) => {
2413
3021
  if (menuRef.current && !menuRef.current.contains(e.target)) {
2414
3022
  onClose();
@@ -2426,7 +3034,7 @@ var EventContextMenu = ({
2426
3034
  ...onEdit ? [{
2427
3035
  id: "edit",
2428
3036
  label: translations?.edit || "Edit",
2429
- icon: /* @__PURE__ */ import_react16.default.createElement(import_lucide_react8.Edit3, { className: "w-4 h-4" }),
3037
+ icon: /* @__PURE__ */ import_react18.default.createElement(import_lucide_react8.Edit3, { className: "w-4 h-4" }),
2430
3038
  onClick: () => {
2431
3039
  onEdit(event);
2432
3040
  onClose();
@@ -2435,7 +3043,7 @@ var EventContextMenu = ({
2435
3043
  ...onDuplicate ? [{
2436
3044
  id: "duplicate",
2437
3045
  label: translations?.duplicate || "Duplicate",
2438
- icon: /* @__PURE__ */ import_react16.default.createElement(import_lucide_react8.Copy, { className: "w-4 h-4" }),
3046
+ icon: /* @__PURE__ */ import_react18.default.createElement(import_lucide_react8.Copy, { className: "w-4 h-4" }),
2439
3047
  onClick: () => {
2440
3048
  onDuplicate(event);
2441
3049
  onClose();
@@ -2445,7 +3053,7 @@ var EventContextMenu = ({
2445
3053
  ...onDelete ? [{
2446
3054
  id: "delete",
2447
3055
  label: translations?.delete || "Delete",
2448
- icon: /* @__PURE__ */ import_react16.default.createElement(import_lucide_react8.Trash2, { className: "w-4 h-4" }),
3056
+ icon: /* @__PURE__ */ import_react18.default.createElement(import_lucide_react8.Trash2, { className: "w-4 h-4" }),
2449
3057
  onClick: () => {
2450
3058
  onDelete(event.id);
2451
3059
  onClose();
@@ -2457,7 +3065,7 @@ var EventContextMenu = ({
2457
3065
  x: Math.min(position.x, window.innerWidth - 200),
2458
3066
  y: Math.min(position.y, window.innerHeight - (actions.length * 44 + 80))
2459
3067
  };
2460
- return /* @__PURE__ */ import_react16.default.createElement(import_framer_motion3.AnimatePresence, null, /* @__PURE__ */ import_react16.default.createElement(
3068
+ return /* @__PURE__ */ import_react18.default.createElement(import_framer_motion3.AnimatePresence, null, /* @__PURE__ */ import_react18.default.createElement(
2461
3069
  import_framer_motion3.motion.div,
2462
3070
  {
2463
3071
  ref: menuRef,
@@ -2471,14 +3079,14 @@ var EventContextMenu = ({
2471
3079
  top: adjustedPosition.y
2472
3080
  }
2473
3081
  },
2474
- /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-3 py-2 border-b-[0.5px] border-border bg-muted/30" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement(
3082
+ /* @__PURE__ */ import_react18.default.createElement("div", { className: "px-3 py-2 border-b-[0.5px] border-border bg-muted/30" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react18.default.createElement(
2475
3083
  "div",
2476
3084
  {
2477
3085
  className: "w-2.5 h-2.5 rounded-full shrink-0",
2478
3086
  style: { backgroundColor: event.color || "var(--primary)" }
2479
3087
  }
2480
- ), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-sm font-medium truncate text-foreground" }, event.title))),
2481
- /* @__PURE__ */ import_react16.default.createElement("div", { className: "py-1" }, actions.map((action, index) => /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, { key: action.id }, index > 0 && action.variant === "danger" && /* @__PURE__ */ import_react16.default.createElement("div", { className: "h-px bg-border my-1" }), /* @__PURE__ */ import_react16.default.createElement(
3088
+ ), /* @__PURE__ */ import_react18.default.createElement("span", { className: "text-sm font-medium truncate text-foreground" }, event.title))),
3089
+ /* @__PURE__ */ import_react18.default.createElement("div", { className: "py-1" }, actions.map((action, index) => /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, { key: action.id }, index > 0 && action.variant === "danger" && /* @__PURE__ */ import_react18.default.createElement("div", { className: "h-px bg-border my-1" }), /* @__PURE__ */ import_react18.default.createElement(
2482
3090
  "button",
2483
3091
  {
2484
3092
  onClick: action.onClick,
@@ -2490,13 +3098,13 @@ var EventContextMenu = ({
2490
3098
  )
2491
3099
  },
2492
3100
  action.icon,
2493
- /* @__PURE__ */ import_react16.default.createElement("span", null, action.label)
3101
+ /* @__PURE__ */ import_react18.default.createElement("span", null, action.label)
2494
3102
  ))))
2495
3103
  ));
2496
3104
  };
2497
3105
  var useEventContextMenu = () => {
2498
- const [contextMenu, setContextMenu] = (0, import_react16.useState)({ event: null, position: null });
2499
- const openContextMenu = (0, import_react16.useCallback)((event, e) => {
3106
+ const [contextMenu, setContextMenu] = (0, import_react18.useState)({ event: null, position: null });
3107
+ const openContextMenu = (0, import_react18.useCallback)((event, e) => {
2500
3108
  e.preventDefault();
2501
3109
  e.stopPropagation();
2502
3110
  setContextMenu({
@@ -2504,7 +3112,7 @@ var useEventContextMenu = () => {
2504
3112
  position: { x: e.clientX, y: e.clientY }
2505
3113
  });
2506
3114
  }, []);
2507
- const closeContextMenu = (0, import_react16.useCallback)(() => {
3115
+ const closeContextMenu = (0, import_react18.useCallback)(() => {
2508
3116
  setContextMenu({ event: null, position: null });
2509
3117
  }, []);
2510
3118
  return {
@@ -2595,11 +3203,11 @@ function getThemeStyles(theme) {
2595
3203
  }
2596
3204
 
2597
3205
  // src/hooks/useCalendarLogic.ts
2598
- var import_react18 = require("react");
2599
- var import_date_fns15 = require("date-fns");
3206
+ var import_react20 = require("react");
3207
+ var import_date_fns19 = require("date-fns");
2600
3208
 
2601
3209
  // src/core/recurrence.ts
2602
- var import_date_fns14 = require("date-fns");
3210
+ var import_date_fns18 = require("date-fns");
2603
3211
  var import_rrule = require("rrule");
2604
3212
  var WEEKDAYS = [import_rrule.RRule.MO, import_rrule.RRule.TU, import_rrule.RRule.WE, import_rrule.RRule.TH, import_rrule.RRule.FR, import_rrule.RRule.SA, import_rrule.RRule.SU];
2605
3213
  var toFloating = (instant, tz) => {
@@ -2638,7 +3246,7 @@ function occurrencesInMonth(event, monthStart, tz) {
2638
3246
  const excluded = new Set((event.recurrence.exdates ?? []).map(minuteKey));
2639
3247
  const duration = event.end.getTime() - event.start.getTime();
2640
3248
  const from = toFloating(monthStart, tz);
2641
- const to = toFloating((0, import_date_fns14.addMonths)(monthStart, 1), tz);
3249
+ const to = toFloating((0, import_date_fns18.addMonths)(monthStart, 1), tz);
2642
3250
  const result = [];
2643
3251
  for (const floating of rule.between(from, to, true)) {
2644
3252
  if (floating.getTime() === to.getTime()) continue;
@@ -2676,16 +3284,18 @@ function cachedMonth(event, monthStart, tz) {
2676
3284
  }
2677
3285
  function expandRecurrences(events, range, anchorTz) {
2678
3286
  const result = [];
2679
- const firstMonth = (0, import_date_fns14.startOfMonth)(toDisplay(range.start, anchorTz));
2680
- const lastMonth = (0, import_date_fns14.startOfMonth)(toDisplay(range.end, anchorTz));
2681
3287
  for (const event of events) {
2682
3288
  if (!event.recurrence) {
2683
3289
  result.push(event);
2684
3290
  continue;
2685
3291
  }
3292
+ const tz = event.allDay ? void 0 : anchorTz;
3293
+ const lastMonth = (0, import_date_fns18.startOfMonth)(toDisplay(range.end, tz));
3294
+ const duration = event.end.getTime() - event.start.getTime();
3295
+ const firstMonth = (0, import_date_fns18.startOfMonth)(toDisplay(new Date(range.start.getTime() - duration), tz));
2686
3296
  try {
2687
- for (let month = firstMonth; month <= lastMonth; month = (0, import_date_fns14.addMonths)(month, 1)) {
2688
- for (const occurrence of cachedMonth(event, fromDisplay(month, anchorTz), anchorTz)) {
3297
+ for (let month = firstMonth; month <= lastMonth; month = (0, import_date_fns18.addMonths)(month, 1)) {
3298
+ for (const occurrence of cachedMonth(event, fromDisplay(month, tz), tz)) {
2689
3299
  if (occurrence.end >= range.start && occurrence.start <= range.end) result.push(occurrence);
2690
3300
  }
2691
3301
  }
@@ -2701,8 +3311,8 @@ function stripOccurrenceFields(event) {
2701
3311
  return rest;
2702
3312
  }
2703
3313
  var shiftFloating = (instant, deltaMs, tz) => fromFloating(new Date(toFloating(instant, tz).getTime() + deltaMs), tz);
2704
- var DAY_MS = 24 * 60 * 60 * 1e3;
2705
- var floatingDay = (floating) => Math.floor(floating.getTime() / DAY_MS);
3314
+ var DAY_MS2 = 24 * 60 * 60 * 1e3;
3315
+ var floatingDay = (floating) => Math.floor(floating.getTime() / DAY_MS2);
2706
3316
  function shiftSeries(master, occurrence, newStart, newEnd, anchorTz) {
2707
3317
  const fromFloat = toFloating(occurrence.start, anchorTz);
2708
3318
  const toFloat = toFloating(newStart, anchorTz);
@@ -2713,6 +3323,7 @@ function shiftSeries(master, occurrence, newStart, newEnd, anchorTz) {
2713
3323
  const recurrence = master.recurrence && {
2714
3324
  ...master.recurrence,
2715
3325
  byweekday: master.recurrence.byweekday && dayDelta % 7 !== 0 ? master.recurrence.byweekday.map((d) => ((d + dayDelta) % 7 + 7) % 7) : master.recurrence.byweekday,
3326
+ until: master.recurrence.until && shiftFloating(master.recurrence.until, deltaMs, anchorTz),
2716
3327
  exdates: master.recurrence.exdates?.map((d) => shiftFloating(d, deltaMs, anchorTz))
2717
3328
  };
2718
3329
  return stripOccurrenceFields({ ...master, start, end, recurrence });
@@ -2723,21 +3334,23 @@ function excludeOccurrence(master, occurrenceStart) {
2723
3334
  }
2724
3335
 
2725
3336
  // src/hooks/useStableCallback.ts
2726
- var import_react17 = require("react");
3337
+ var import_react19 = require("react");
2727
3338
  function useStableCallback(fn) {
2728
- const ref = (0, import_react17.useRef)(fn);
2729
- ref.current = fn;
2730
- return (0, import_react17.useCallback)((...args) => ref.current(...args), []);
3339
+ const ref = (0, import_react19.useRef)(fn);
3340
+ (0, import_react19.useInsertionEffect)(() => {
3341
+ ref.current = fn;
3342
+ });
3343
+ return (0, import_react19.useCallback)((...args) => ref.current(...args), []);
2731
3344
  }
2732
3345
 
2733
3346
  // src/hooks/useCalendarLogic.ts
2734
3347
  function expansionRange(monthStart) {
2735
3348
  return {
2736
- start: (0, import_date_fns15.startOfWeek)((0, import_date_fns15.startOfMonth)((0, import_date_fns15.subMonths)(monthStart, 1))),
2737
- end: (0, import_date_fns15.addDays)((0, import_date_fns15.endOfMonth)((0, import_date_fns15.addMonths)(monthStart, 1)), 37)
3349
+ start: (0, import_date_fns19.startOfWeek)((0, import_date_fns19.startOfMonth)((0, import_date_fns19.subMonths)(monthStart, 1))),
3350
+ end: (0, import_date_fns19.addDays)((0, import_date_fns19.endOfMonth)((0, import_date_fns19.addMonths)(monthStart, 1)), 37)
2738
3351
  };
2739
3352
  }
2740
- var DAY_MS2 = 24 * 60 * 60 * 1e3;
3353
+ var DAY_MS3 = 24 * 60 * 60 * 1e3;
2741
3354
  var useCalendarLogic = ({
2742
3355
  events,
2743
3356
  view: controlledView,
@@ -2754,19 +3367,20 @@ var useCalendarLogic = ({
2754
3367
  readOnly,
2755
3368
  timezone
2756
3369
  }) => {
2757
- const [internalView, setInternalView] = (0, import_react18.useState)("week");
2758
- const [internalDate, setInternalDate] = (0, import_react18.useState)(() => /* @__PURE__ */ new Date());
2759
- const [isSidebarOpen, setIsSidebarOpen] = (0, import_react18.useState)(true);
2760
- const [isModalOpen, setIsModalOpen] = (0, import_react18.useState)(false);
2761
- const [selectedEvent, setSelectedEvent] = (0, import_react18.useState)(null);
2762
- const [modalInitialDate, setModalInitialDate] = (0, import_react18.useState)(void 0);
2763
- const [modalInitialResourceId, setModalInitialResourceId] = (0, import_react18.useState)(void 0);
3370
+ const [internalView, setInternalView] = (0, import_react20.useState)("week");
3371
+ const [internalDate, setInternalDate] = (0, import_react20.useState)(() => /* @__PURE__ */ new Date());
3372
+ const [isSidebarOpen, setIsSidebarOpen] = (0, import_react20.useState)(true);
3373
+ const [isModalOpen, setIsModalOpen] = (0, import_react20.useState)(false);
3374
+ const [selectedEvent, setSelectedEvent] = (0, import_react20.useState)(null);
3375
+ const [modalInitialDate, setModalInitialDate] = (0, import_react20.useState)(void 0);
3376
+ const [modalInitialResourceId, setModalInitialResourceId] = (0, import_react20.useState)(void 0);
3377
+ const [modalInitialAllDay, setModalInitialAllDay] = (0, import_react20.useState)(false);
2764
3378
  const view = controlledView ?? internalView;
2765
3379
  const currentDate = controlledDate ?? internalDate;
2766
- const normalizedEvents = (0, import_react18.useMemo)(() => normalizeEvents(events), [events]);
2767
- const monthKey = (0, import_date_fns15.format)(currentDate, "yyyy-MM");
2768
- const range = (0, import_react18.useMemo)(() => expansionRange(/* @__PURE__ */ new Date(`${monthKey}-01T00:00:00`)), [monthKey]);
2769
- const expandedEvents = (0, import_react18.useMemo)(
3380
+ const normalizedEvents = (0, import_react20.useMemo)(() => normalizeEvents(events), [events]);
3381
+ const monthKey = (0, import_date_fns19.format)(currentDate, "yyyy-MM");
3382
+ const range = (0, import_react20.useMemo)(() => expansionRange(/* @__PURE__ */ new Date(`${monthKey}-01T00:00:00`)), [monthKey]);
3383
+ const expandedEvents = (0, import_react20.useMemo)(
2770
3384
  () => expandRecurrences(normalizedEvents, range, timezone),
2771
3385
  [normalizedEvents, range, timezone]
2772
3386
  );
@@ -2788,34 +3402,34 @@ var useCalendarLogic = ({
2788
3402
  const handlePrev = useStableCallback(() => {
2789
3403
  switch (view) {
2790
3404
  case "month":
2791
- handleDateChange((0, import_date_fns15.subMonths)(currentDate, 1));
3405
+ handleDateChange((0, import_date_fns19.subMonths)(currentDate, 1));
2792
3406
  break;
2793
3407
  case "week":
2794
- handleDateChange((0, import_date_fns15.subWeeks)(currentDate, 1));
3408
+ handleDateChange((0, import_date_fns19.subWeeks)(currentDate, 1));
2795
3409
  break;
2796
3410
  case "day":
2797
3411
  case "resource":
2798
- handleDateChange((0, import_date_fns15.subDays)(currentDate, 1));
3412
+ handleDateChange((0, import_date_fns19.subDays)(currentDate, 1));
2799
3413
  break;
2800
3414
  case "agenda":
2801
- handleDateChange((0, import_date_fns15.subDays)(currentDate, 7));
3415
+ handleDateChange((0, import_date_fns19.subDays)(currentDate, 7));
2802
3416
  break;
2803
3417
  }
2804
3418
  });
2805
3419
  const handleNext = useStableCallback(() => {
2806
3420
  switch (view) {
2807
3421
  case "month":
2808
- handleDateChange((0, import_date_fns15.addMonths)(currentDate, 1));
3422
+ handleDateChange((0, import_date_fns19.addMonths)(currentDate, 1));
2809
3423
  break;
2810
3424
  case "week":
2811
- handleDateChange((0, import_date_fns15.addWeeks)(currentDate, 1));
3425
+ handleDateChange((0, import_date_fns19.addWeeks)(currentDate, 1));
2812
3426
  break;
2813
3427
  case "day":
2814
3428
  case "resource":
2815
- handleDateChange((0, import_date_fns15.addDays)(currentDate, 1));
3429
+ handleDateChange((0, import_date_fns19.addDays)(currentDate, 1));
2816
3430
  break;
2817
3431
  case "agenda":
2818
- handleDateChange((0, import_date_fns15.addDays)(currentDate, 7));
3432
+ handleDateChange((0, import_date_fns19.addDays)(currentDate, 7));
2819
3433
  break;
2820
3434
  }
2821
3435
  });
@@ -2831,6 +3445,15 @@ var useCalendarLogic = ({
2831
3445
  setSelectedEvent(null);
2832
3446
  setModalInitialDate(date);
2833
3447
  setModalInitialResourceId(resourceId);
3448
+ setModalInitialAllDay(false);
3449
+ setIsModalOpen(true);
3450
+ });
3451
+ const handleAllDaySlotClick = useStableCallback((day) => {
3452
+ if (readOnly) return;
3453
+ setSelectedEvent(null);
3454
+ setModalInitialDate(day);
3455
+ setModalInitialResourceId(void 0);
3456
+ setModalInitialAllDay(true);
2834
3457
  setIsModalOpen(true);
2835
3458
  });
2836
3459
  const handleEventClickInternal = useStableCallback((event) => {
@@ -2839,6 +3462,7 @@ var useCalendarLogic = ({
2839
3462
  setSelectedEvent(event);
2840
3463
  setModalInitialDate(void 0);
2841
3464
  setModalInitialResourceId(void 0);
3465
+ setModalInitialAllDay(false);
2842
3466
  setIsModalOpen(true);
2843
3467
  }
2844
3468
  });
@@ -2847,6 +3471,7 @@ var useCalendarLogic = ({
2847
3471
  setSelectedEvent(null);
2848
3472
  setModalInitialDate(/* @__PURE__ */ new Date());
2849
3473
  setModalInitialResourceId(void 0);
3474
+ setModalInitialAllDay(false);
2850
3475
  setIsModalOpen(true);
2851
3476
  });
2852
3477
  const handleModalSave = useStableCallback((eventData) => {
@@ -2861,7 +3486,7 @@ var useCalendarLogic = ({
2861
3486
  end: master.end
2862
3487
  };
2863
3488
  onEventUpdate?.(
2864
- shiftSeries(edited, selectedEvent, eventData.start ?? selectedEvent.start, eventData.end ?? selectedEvent.end, timezone)
3489
+ shiftSeries(edited, selectedEvent, eventData.start ?? selectedEvent.start, eventData.end ?? selectedEvent.end, edited.allDay ? void 0 : timezone)
2865
3490
  );
2866
3491
  } else if (selectedEvent) {
2867
3492
  onEventUpdate?.({ ...eventData, id: selectedEvent.id });
@@ -2896,28 +3521,39 @@ var useCalendarLogic = ({
2896
3521
  ...copy,
2897
3522
  id: `${event.originalEventId ?? event.id}-copy-${Date.now()}`,
2898
3523
  title: `${event.title} (Copy)`,
2899
- start: new Date(event.start.getTime() + DAY_MS2),
2900
- end: new Date(event.end.getTime() + DAY_MS2)
3524
+ start: new Date(event.start.getTime() + DAY_MS3),
3525
+ end: new Date(event.end.getTime() + DAY_MS3)
2901
3526
  });
2902
3527
  });
2903
3528
  const applyChange = (event, start, end) => {
2904
3529
  if (!event.originalEventId) return { original: event, updated: { ...event, start, end } };
2905
3530
  const master = masterOf(event);
2906
3531
  if (!master) return null;
2907
- return { original: master, updated: shiftSeries(master, event, start, end, timezone) };
3532
+ return { original: master, updated: shiftSeries(master, event, start, end, event.allDay ? void 0 : timezone) };
2908
3533
  };
2909
3534
  const handleDragEnd = useStableCallback((dragEvent) => {
3535
+ if (readOnly) return;
2910
3536
  const { active, over } = dragEvent;
2911
3537
  if (!over) return;
2912
3538
  const dragged = active.data.current?.event;
2913
3539
  const overDate = over.data.current?.date;
2914
3540
  if (!dragged || !overDate) return;
3541
+ const grabDayOffset = active.data.current?.grabDayOffset;
3542
+ if (grabDayOffset !== void 0) {
3543
+ const move = computeDayMove(dragged, overDate, grabDayOffset, timezone);
3544
+ const dayChange = move && applyChange(dragged, move.start, move.end);
3545
+ if (!dayChange) return;
3546
+ onEventDrop?.(dayChange.original, dayChange.updated.start, dayChange.updated.end);
3547
+ onEventUpdate?.(dayChange.updated);
3548
+ return;
3549
+ }
2915
3550
  const drop = computeDrop({
2916
3551
  event: dragged,
2917
3552
  overDate,
2918
3553
  overResourceId: over.data.current?.resourceId,
2919
3554
  grabOffsetMs: active.data.current?.grabOffsetMs,
2920
- view,
3555
+ // A timed event dropped in the all-day row only changes day (keeps its time), like in month view.
3556
+ view: over.data.current?.allDayRow ? "month" : view,
2921
3557
  tz: timezone
2922
3558
  });
2923
3559
  if (!drop) return;
@@ -2927,6 +3563,14 @@ var useCalendarLogic = ({
2927
3563
  onEventDrop?.(change.original, updated.start, updated.end);
2928
3564
  onEventUpdate?.(updated);
2929
3565
  });
3566
+ const handleDayEventResize = useStableCallback((event, newLastDay) => {
3567
+ if (readOnly) return;
3568
+ const end = computeDayResize(event, newLastDay, timezone);
3569
+ const change = end && applyChange(event, event.start, end);
3570
+ if (!change) return;
3571
+ onEventResize?.(change.original, change.updated.start, change.updated.end);
3572
+ onEventUpdate?.(change.updated);
3573
+ });
2930
3574
  const handleEventResize = useStableCallback((event, newEnd) => {
2931
3575
  if (readOnly) return;
2932
3576
  const change = applyChange(event, event.start, newEnd);
@@ -2943,6 +3587,7 @@ var useCalendarLogic = ({
2943
3587
  setIsModalOpen,
2944
3588
  selectedEvent,
2945
3589
  modalInitialDate,
3590
+ modalInitialAllDay,
2946
3591
  expandedEvents,
2947
3592
  handleViewChange,
2948
3593
  handleDateChange,
@@ -2951,6 +3596,7 @@ var useCalendarLogic = ({
2951
3596
  handleToday,
2952
3597
  handleDateClick,
2953
3598
  handleTimeSlotClick,
3599
+ handleAllDaySlotClick,
2954
3600
  handleEventClickInternal,
2955
3601
  handleCreateEvent,
2956
3602
  handleModalSave,
@@ -2958,15 +3604,16 @@ var useCalendarLogic = ({
2958
3604
  handleEventDelete,
2959
3605
  handleEventDuplicate,
2960
3606
  handleEventResize,
3607
+ handleDayEventResize,
2961
3608
  handleDragEnd
2962
3609
  };
2963
3610
  };
2964
3611
 
2965
3612
  // src/index.tsx
2966
- var import_date_fns16 = require("date-fns");
3613
+ var import_date_fns21 = require("date-fns");
2967
3614
 
2968
3615
  // src/hooks/useSwipeGesture.ts
2969
- var import_react19 = require("react");
3616
+ var import_react21 = require("react");
2970
3617
  var useSwipeGesture = (options) => {
2971
3618
  const {
2972
3619
  onSwipeLeft,
@@ -2978,9 +3625,9 @@ var useSwipeGesture = (options) => {
2978
3625
  allowedTime = 500,
2979
3626
  enabled = true
2980
3627
  } = options;
2981
- const touchInfoRef = (0, import_react19.useRef)(null);
2982
- const elementRef = (0, import_react19.useRef)(null);
2983
- const handleTouchStart = (0, import_react19.useCallback)((e) => {
3628
+ const touchInfoRef = (0, import_react21.useRef)(null);
3629
+ const elementRef = (0, import_react21.useRef)(null);
3630
+ const handleTouchStart = (0, import_react21.useCallback)((e) => {
2984
3631
  if (!enabled) return;
2985
3632
  const touch = e.touches[0];
2986
3633
  touchInfoRef.current = {
@@ -2989,7 +3636,7 @@ var useSwipeGesture = (options) => {
2989
3636
  startTime: Date.now()
2990
3637
  };
2991
3638
  }, [enabled]);
2992
- const handleTouchEnd = (0, import_react19.useCallback)((e) => {
3639
+ const handleTouchEnd = (0, import_react21.useCallback)((e) => {
2993
3640
  if (!enabled || !touchInfoRef.current) return;
2994
3641
  const touch = e.changedTouches[0];
2995
3642
  const { startX, startY, startTime } = touchInfoRef.current;
@@ -3013,7 +3660,7 @@ var useSwipeGesture = (options) => {
3013
3660
  }
3014
3661
  touchInfoRef.current = null;
3015
3662
  }, [enabled, threshold, restraint, allowedTime, onSwipeLeft, onSwipeRight, onSwipeUp, onSwipeDown]);
3016
- (0, import_react19.useEffect)(() => {
3663
+ (0, import_react21.useEffect)(() => {
3017
3664
  const element = elementRef.current;
3018
3665
  if (!element) return;
3019
3666
  element.addEventListener("touchstart", handleTouchStart, { passive: true });
@@ -3036,6 +3683,25 @@ var useViewSwipe = (onPrev, onNext, enabled = true) => {
3036
3683
  });
3037
3684
  };
3038
3685
 
3686
+ // src/components/dnd/dragOverlay.ts
3687
+ var import_core4 = require("@dnd-kit/core");
3688
+ var import_date_fns20 = require("date-fns");
3689
+ var dayAwareCollision = (args) => {
3690
+ if (args.active.data.current?.grabDayOffset !== void 0) {
3691
+ const underPointer = (0, import_core4.pointerWithin)(args);
3692
+ if (underPointer.length > 0) return underPointer;
3693
+ }
3694
+ return (0, import_core4.rectIntersection)(args);
3695
+ };
3696
+ function dragOverlaySize(view, event, isDayDrag) {
3697
+ if (isDayDrag) return {};
3698
+ const minutes = (0, import_date_fns20.differenceInMinutes)(event.end, event.start);
3699
+ if (view === "month") return { width: "100%" };
3700
+ if (view === "resource") return { width: `${Math.max(minutes / 60 * 100, 4)}px`, height: 80 };
3701
+ if (view === "week" || view === "day") return { width: "150px", height: minutes / 60 * (view === "day" ? 80 : 60) };
3702
+ return { width: "150px" };
3703
+ }
3704
+
3039
3705
  // src/index.tsx
3040
3706
  var Scheduler = ({
3041
3707
  events = [],
@@ -3071,10 +3737,12 @@ var Scheduler = ({
3071
3737
  locale
3072
3738
  // Date-fns locale
3073
3739
  }) => {
3074
- const [activeDragEvent, setActiveDragEvent] = (0, import_react20.useState)(null);
3740
+ const [activeDragEvent, setActiveDragEvent] = (0, import_react22.useState)(null);
3741
+ const [activeDayDrag, setActiveDayDrag] = (0, import_react22.useState)(false);
3075
3742
  const {
3076
3743
  contextMenuEvent,
3077
3744
  contextMenuPosition,
3745
+ openContextMenu,
3078
3746
  closeContextMenu
3079
3747
  } = useEventContextMenu();
3080
3748
  const {
@@ -3086,6 +3754,7 @@ var Scheduler = ({
3086
3754
  setIsModalOpen,
3087
3755
  selectedEvent,
3088
3756
  modalInitialDate,
3757
+ modalInitialAllDay,
3089
3758
  handleViewChange,
3090
3759
  handleDateChange,
3091
3760
  handlePrev,
@@ -3093,6 +3762,7 @@ var Scheduler = ({
3093
3762
  handleToday,
3094
3763
  handleDateClick,
3095
3764
  handleTimeSlotClick,
3765
+ handleAllDaySlotClick,
3096
3766
  handleEventClickInternal,
3097
3767
  handleCreateEvent,
3098
3768
  handleModalSave,
@@ -3100,6 +3770,7 @@ var Scheduler = ({
3100
3770
  handleEventDelete,
3101
3771
  handleEventDuplicate,
3102
3772
  handleEventResize,
3773
+ handleDayEventResize,
3103
3774
  handleDragEnd,
3104
3775
  expandedEvents
3105
3776
  } = useCalendarLogic({
@@ -3118,8 +3789,8 @@ var Scheduler = ({
3118
3789
  readOnly,
3119
3790
  timezone
3120
3791
  });
3121
- const sensors = (0, import_core3.useSensors)(
3122
- (0, import_core3.useSensor)(import_core3.PointerSensor, {
3792
+ const sensors = (0, import_core5.useSensors)(
3793
+ (0, import_core5.useSensor)(import_core5.PointerSensor, {
3123
3794
  activationConstraint: {
3124
3795
  distance: 8
3125
3796
  }
@@ -3129,63 +3800,49 @@ var Scheduler = ({
3129
3800
  const snapToGrid = (0, import_modifiers.createSnapModifier)(gridSize);
3130
3801
  const modifiers = [snapToGrid, import_modifiers.restrictToWindowEdges];
3131
3802
  const dndSensors = readOnly ? [] : sensors;
3132
- const id = (0, import_react20.useId)();
3803
+ const id = (0, import_react22.useId)();
3133
3804
  const swipeRef = useViewSwipe(handlePrev, handleNext, true);
3134
- const t = (0, import_react20.useMemo)(() => resolveTranslations(language, translations), [language, translations]);
3805
+ const t = (0, import_react22.useMemo)(() => resolveTranslations(language, translations), [language, translations]);
3135
3806
  const overlayTimeFormat = timeFormats(locale).time;
3136
- const handleDragStart = (0, import_react20.useCallback)((event) => {
3807
+ const handleDragStart = (0, import_react22.useCallback)((event) => {
3137
3808
  const draggedEvent = event.active.data.current?.event;
3138
3809
  if (draggedEvent) {
3139
3810
  setActiveDragEvent(draggedEvent);
3811
+ setActiveDayDrag(event.active.data.current?.grabDayOffset !== void 0);
3140
3812
  }
3141
3813
  }, []);
3142
- const onDragEndWrapper = (0, import_react20.useCallback)((event) => {
3814
+ const onDragEndWrapper = (0, import_react22.useCallback)((event) => {
3143
3815
  setActiveDragEvent(null);
3144
3816
  handleDragEnd(event);
3145
3817
  }, [handleDragEnd]);
3146
- const getDragHeight = () => {
3147
- if (!activeDragEvent) return void 0;
3148
- if (view === "resource") {
3149
- return 80;
3150
- }
3151
- if (view !== "week" && view !== "day") return void 0;
3152
- const duration = (0, import_date_fns16.differenceInMinutes)(activeDragEvent.end, activeDragEvent.start);
3153
- const hourHeight = view === "day" ? 80 : 60;
3154
- return duration / 60 * hourHeight;
3155
- };
3156
- const getDragWidth = () => {
3157
- if (view === "month") return "100%";
3158
- if (view === "resource" && activeDragEvent) {
3159
- const duration = (0, import_date_fns16.differenceInMinutes)(activeDragEvent.end, activeDragEvent.start);
3160
- const width = duration / 60 * 100;
3161
- return `${Math.max(width, 4)}px`;
3162
- }
3163
- return "150px";
3164
- };
3165
- const filteredEvents = (0, import_react20.useMemo)(() => {
3166
- if (!calendars) return expandedEvents;
3167
- const activeCalendarIds = calendars.filter((c) => c.active !== false).map((c) => c.id);
3168
- return expandedEvents.filter((e) => {
3169
- if (!e.calendarId) return true;
3170
- return activeCalendarIds.includes(e.calendarId);
3171
- });
3172
- }, [expandedEvents, calendars]);
3173
- return /* @__PURE__ */ import_react20.default.createElement(
3174
- import_core3.DndContext,
3818
+ const dragSize = activeDragEvent ? dragOverlaySize(view, activeDragEvent, activeDayDrag) : {};
3819
+ const activeCalendarKey = calendars ? calendars.filter((c) => c.active !== false).map((c) => c.id).join("\0") : null;
3820
+ const filteredEvents = (0, import_react22.useMemo)(() => {
3821
+ if (activeCalendarKey === null) return expandedEvents;
3822
+ const activeCalendarIds = new Set(activeCalendarKey.split("\0"));
3823
+ return expandedEvents.filter((e) => !e.calendarId || activeCalendarIds.has(String(e.calendarId)));
3824
+ }, [expandedEvents, activeCalendarKey]);
3825
+ const periodKey = view === "month" ? (0, import_date_fns21.format)(currentDate, "yyyy-MM") : view === "week" ? (0, import_date_fns21.format)((0, import_date_fns21.startOfWeek)(currentDate, { weekStartsOn: resolveWeekStartsOn(locale, 1) }), "yyyy-MM-dd") : (0, import_date_fns21.format)(currentDate, "yyyy-MM-dd");
3826
+ const slotClickHandler = readOnly ? void 0 : handleTimeSlotClick;
3827
+ const allDaySlotClickHandler = readOnly ? void 0 : handleAllDaySlotClick;
3828
+ const contextMenuHandler = readOnly ? void 0 : openContextMenu;
3829
+ return /* @__PURE__ */ import_react22.default.createElement(
3830
+ import_core5.DndContext,
3175
3831
  {
3176
3832
  id,
3177
3833
  sensors: dndSensors,
3178
3834
  onDragStart: handleDragStart,
3179
3835
  onDragEnd: onDragEndWrapper,
3180
- modifiers
3836
+ modifiers,
3837
+ collisionDetection: dayAwareCollision
3181
3838
  },
3182
- /* @__PURE__ */ import_react20.default.createElement(
3839
+ /* @__PURE__ */ import_react22.default.createElement(
3183
3840
  "div",
3184
3841
  {
3185
3842
  className: cn("flex flex-col h-full bg-background text-foreground relative", className),
3186
3843
  style: getThemeStyles(theme)
3187
3844
  },
3188
- /* @__PURE__ */ import_react20.default.createElement(
3845
+ /* @__PURE__ */ import_react22.default.createElement(
3189
3846
  CalendarHeader,
3190
3847
  {
3191
3848
  currentDate,
@@ -3204,7 +3861,7 @@ var Scheduler = ({
3204
3861
  locale
3205
3862
  }
3206
3863
  ),
3207
- /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react20.default.createElement(
3864
+ /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react22.default.createElement(
3208
3865
  import_framer_motion4.motion.div,
3209
3866
  {
3210
3867
  className: cn(
@@ -3220,7 +3877,7 @@ var Scheduler = ({
3220
3877
  ease: [0.4, 0, 0.2, 1]
3221
3878
  }
3222
3879
  },
3223
- /* @__PURE__ */ import_react20.default.createElement(
3880
+ /* @__PURE__ */ import_react22.default.createElement(
3224
3881
  Sidebar,
3225
3882
  {
3226
3883
  currentDate,
@@ -3237,10 +3894,10 @@ var Scheduler = ({
3237
3894
  locale
3238
3895
  }
3239
3896
  )
3240
- ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex-1 flex flex-col overflow-hidden relative" }, isLoading ? /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex-1 overflow-auto p-0 md:p-4" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-full min-w-full" }, view === "month" && /* @__PURE__ */ import_react20.default.createElement(MonthViewSkeleton, null), view === "week" && /* @__PURE__ */ import_react20.default.createElement(WeekViewSkeleton, null), view === "day" && /* @__PURE__ */ import_react20.default.createElement(DayViewSkeleton, null), view === "agenda" && /* @__PURE__ */ import_react20.default.createElement(AgendaViewSkeleton, null), view === "resource" && /* @__PURE__ */ import_react20.default.createElement(WeekViewSkeleton, null))) : /* @__PURE__ */ import_react20.default.createElement("div", { ref: swipeRef, className: "flex-1 overflow-auto p-0 md:p-4 touch-pan-y" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-full min-w-full" }, /* @__PURE__ */ import_react20.default.createElement(import_framer_motion4.AnimatePresence, { mode: "wait", initial: false }, /* @__PURE__ */ import_react20.default.createElement(
3897
+ ), /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex-1 flex flex-col overflow-hidden relative" }, isLoading ? /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex-1 overflow-auto p-0 md:p-4" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "h-full min-w-full" }, view === "month" && /* @__PURE__ */ import_react22.default.createElement(MonthViewSkeleton, null), view === "week" && /* @__PURE__ */ import_react22.default.createElement(WeekViewSkeleton, null), view === "day" && /* @__PURE__ */ import_react22.default.createElement(DayViewSkeleton, null), view === "agenda" && /* @__PURE__ */ import_react22.default.createElement(AgendaViewSkeleton, null), view === "resource" && /* @__PURE__ */ import_react22.default.createElement(WeekViewSkeleton, null))) : /* @__PURE__ */ import_react22.default.createElement("div", { ref: swipeRef, className: "flex-1 overflow-auto p-0 md:p-4 touch-pan-y" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "h-full min-w-full" }, /* @__PURE__ */ import_react22.default.createElement(import_framer_motion4.AnimatePresence, { mode: "wait", initial: false }, /* @__PURE__ */ import_react22.default.createElement(
3241
3898
  import_framer_motion4.motion.div,
3242
3899
  {
3243
- key: `${view}-${currentDate.toISOString()}-${timezone || "local"}`,
3900
+ key: `${view}-${periodKey}-${timezone || "local"}`,
3244
3901
  initial: { opacity: 0, scale: 0.98, y: 15 },
3245
3902
  animate: {
3246
3903
  opacity: 1,
@@ -3262,7 +3919,7 @@ var Scheduler = ({
3262
3919
  },
3263
3920
  className: "h-full"
3264
3921
  },
3265
- view === "month" && /* @__PURE__ */ import_react20.default.createElement(
3922
+ view === "month" && /* @__PURE__ */ import_react22.default.createElement(
3266
3923
  MonthView,
3267
3924
  {
3268
3925
  currentDate,
@@ -3270,36 +3927,48 @@ var Scheduler = ({
3270
3927
  onEventClick: handleEventClickInternal,
3271
3928
  onDateClick: handleDateClick,
3272
3929
  timezone,
3273
- locale
3930
+ locale,
3931
+ translations: t,
3932
+ onEventContextMenu: contextMenuHandler,
3933
+ onDayEventResize: handleDayEventResize,
3934
+ readonly: readOnly
3274
3935
  }
3275
3936
  ),
3276
- view === "week" && /* @__PURE__ */ import_react20.default.createElement(
3937
+ view === "week" && /* @__PURE__ */ import_react22.default.createElement(
3277
3938
  WeekView,
3278
3939
  {
3279
3940
  currentDate,
3280
3941
  events: filteredEvents,
3281
3942
  onEventClick: handleEventClickInternal,
3282
- onTimeSlotClick: handleTimeSlotClick,
3943
+ onTimeSlotClick: slotClickHandler,
3283
3944
  onEventResize: handleEventResize,
3284
3945
  timezone,
3285
3946
  locale,
3286
- readonly: readOnly
3947
+ readonly: readOnly,
3948
+ onEventContextMenu: contextMenuHandler,
3949
+ onDayEventResize: handleDayEventResize,
3950
+ onAllDaySlotClick: allDaySlotClickHandler,
3951
+ translations: t
3287
3952
  }
3288
3953
  ),
3289
- view === "day" && /* @__PURE__ */ import_react20.default.createElement(
3954
+ view === "day" && /* @__PURE__ */ import_react22.default.createElement(
3290
3955
  DayView,
3291
3956
  {
3292
3957
  currentDate,
3293
3958
  events: filteredEvents,
3294
3959
  onEventClick: handleEventClickInternal,
3295
- onTimeSlotClick: handleTimeSlotClick,
3960
+ onTimeSlotClick: slotClickHandler,
3296
3961
  onEventResize: handleEventResize,
3297
3962
  timezone,
3298
3963
  locale,
3299
- readonly: readOnly
3964
+ readonly: readOnly,
3965
+ translations: t,
3966
+ onEventContextMenu: contextMenuHandler,
3967
+ onDayEventResize: handleDayEventResize,
3968
+ onAllDaySlotClick: allDaySlotClickHandler
3300
3969
  }
3301
3970
  ),
3302
- view === "agenda" && /* @__PURE__ */ import_react20.default.createElement(
3971
+ view === "agenda" && /* @__PURE__ */ import_react22.default.createElement(
3303
3972
  AgendaView,
3304
3973
  {
3305
3974
  currentDate,
@@ -3308,37 +3977,42 @@ var Scheduler = ({
3308
3977
  onCreateEvent: handleCreateEvent,
3309
3978
  locale,
3310
3979
  translations: t,
3311
- timezone
3980
+ timezone,
3981
+ onEventContextMenu: contextMenuHandler
3312
3982
  }
3313
3983
  ),
3314
- view === "resource" && resources && /* @__PURE__ */ import_react20.default.createElement(
3984
+ view === "resource" && resources && /* @__PURE__ */ import_react22.default.createElement(
3315
3985
  ResourceView,
3316
3986
  {
3317
3987
  currentDate,
3318
3988
  events: filteredEvents,
3319
3989
  resources,
3320
3990
  onEventClick: handleEventClickInternal,
3321
- onTimeSlotClick: handleTimeSlotClick,
3991
+ onTimeSlotClick: slotClickHandler,
3322
3992
  locale,
3323
- timezone
3993
+ timezone,
3994
+ translations: t,
3995
+ onEventContextMenu: contextMenuHandler
3324
3996
  }
3325
3997
  )
3326
- )))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "md:hidden absolute bottom-6 right-6 z-50" }, /* @__PURE__ */ import_react20.default.createElement(
3998
+ )))), !readOnly && /* @__PURE__ */ import_react22.default.createElement("div", { className: "md:hidden absolute bottom-6 right-6 z-50" }, /* @__PURE__ */ import_react22.default.createElement(
3327
3999
  "button",
3328
4000
  {
3329
4001
  onClick: handleCreateEvent,
4002
+ "aria-label": t.createEvent,
3330
4003
  className: "w-14 h-14 bg-blue-600 rounded-full shadow-lg flex items-center justify-center text-white active:scale-90 transition-transform"
3331
4004
  },
3332
- /* @__PURE__ */ import_react20.default.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__ */ import_react20.default.createElement("path", { d: "M5 12h14" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M12 5v14" }))
4005
+ /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement("path", { d: "M5 12h14" }), /* @__PURE__ */ import_react22.default.createElement("path", { d: "M12 5v14" }))
3333
4006
  )))),
3334
4007
  renderEventForm ? renderEventForm({
3335
4008
  isOpen: isModalOpen,
3336
4009
  onClose: () => setIsModalOpen(false),
3337
4010
  event: selectedEvent,
3338
4011
  initialDate: modalInitialDate,
4012
+ initialAllDay: modalInitialAllDay,
3339
4013
  onSave: handleModalSave,
3340
4014
  onDelete: handleModalDelete
3341
- }) : /* @__PURE__ */ import_react20.default.createElement(
4015
+ }) : /* @__PURE__ */ import_react22.default.createElement(
3342
4016
  EventModal,
3343
4017
  {
3344
4018
  isOpen: isModalOpen,
@@ -3349,10 +4023,12 @@ var Scheduler = ({
3349
4023
  onDelete: handleModalDelete,
3350
4024
  calendars,
3351
4025
  eventTypes,
3352
- translations: t
4026
+ translations: t,
4027
+ locale,
4028
+ initialAllDay: modalInitialAllDay
3353
4029
  }
3354
4030
  ),
3355
- /* @__PURE__ */ import_react20.default.createElement(
4031
+ /* @__PURE__ */ import_react22.default.createElement(
3356
4032
  EventContextMenu,
3357
4033
  {
3358
4034
  event: contextMenuEvent,
@@ -3377,7 +4053,7 @@ var Scheduler = ({
3377
4053
  }
3378
4054
  }
3379
4055
  ),
3380
- /* @__PURE__ */ import_react20.default.createElement(import_core3.DragOverlay, { dropAnimation: null }, activeDragEvent ? /* @__PURE__ */ import_react20.default.createElement(
4056
+ /* @__PURE__ */ import_react22.default.createElement(import_core5.DragOverlay, { dropAnimation: null }, activeDragEvent ? /* @__PURE__ */ import_react22.default.createElement(
3381
4057
  "div",
3382
4058
  {
3383
4059
  className: cn(
@@ -3389,19 +4065,19 @@ var Scheduler = ({
3389
4065
  backgroundColor: activeDragEvent.color ? `${activeDragEvent.color}e0` : void 0,
3390
4066
  borderColor: activeDragEvent.color ? `${activeDragEvent.color}80` : void 0,
3391
4067
  color: activeDragEvent.color ? "#fff" : void 0,
3392
- width: getDragWidth(),
3393
- height: getDragHeight() ? `${getDragHeight()}px` : void 0,
4068
+ width: dragSize.width,
4069
+ height: dragSize.height ? `${dragSize.height}px` : void 0,
3394
4070
  boxShadow: `0 20px 40px -15px ${activeDragEvent.color || "var(--primary)"}40, 0 10px 20px -10px rgba(0,0,0,0.2)`,
3395
4071
  transform: "rotate(-2deg) scale(1.02)"
3396
4072
  }
3397
4073
  },
3398
- /* @__PURE__ */ import_react20.default.createElement("div", { className: "p-2.5 h-full flex flex-col" }, /* @__PURE__ */ import_react20.default.createElement(
4074
+ /* @__PURE__ */ import_react22.default.createElement("div", { className: "p-2.5 h-full flex flex-col" }, /* @__PURE__ */ import_react22.default.createElement(
3399
4075
  "div",
3400
4076
  {
3401
4077
  className: "absolute left-0 top-0 bottom-0 w-1 rounded-l-lg",
3402
4078
  style: { backgroundColor: activeDragEvent.color || "var(--primary)" }
3403
4079
  }
3404
- ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "pl-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "font-semibold truncate text-sm" }, activeDragEvent.title), (view === "week" || view === "day") && getDragHeight() && getDragHeight() > 40 && /* @__PURE__ */ import_react20.default.createElement("div", { className: "text-xs opacity-80 mt-0.5 flex items-center gap-1" }, /* @__PURE__ */ import_react20.default.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M12 6v6l4 2" })), (0, import_date_fns16.format)(activeDragEvent.start, overlayTimeFormat, { locale }), " - ", (0, import_date_fns16.format)(activeDragEvent.end, overlayTimeFormat, { locale }))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "absolute bottom-1.5 right-1.5 opacity-60" }, /* @__PURE__ */ import_react20.default.createElement("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "9", cy: "5", r: "1.5" }), /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "15", cy: "5", r: "1.5" }), /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "9", cy: "12", r: "1.5" }), /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "15", cy: "12", r: "1.5" }), /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "9", cy: "19", r: "1.5" }), /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "15", cy: "19", r: "1.5" }))))
4080
+ ), /* @__PURE__ */ import_react22.default.createElement("div", { className: "pl-2" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "font-semibold truncate text-sm" }, activeDragEvent.title), (view === "week" || view === "day") && dragSize.height !== void 0 && dragSize.height > 40 && /* @__PURE__ */ import_react22.default.createElement("div", { className: "text-xs opacity-80 mt-0.5 flex items-center gap-1" }, /* @__PURE__ */ import_react22.default.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ import_react22.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react22.default.createElement("path", { d: "M12 6v6l4 2" })), (0, import_date_fns21.format)(toDisplay(activeDragEvent.start, timezone), overlayTimeFormat, { locale }), " - ", (0, import_date_fns21.format)(toDisplay(activeDragEvent.end, timezone), overlayTimeFormat, { locale }))), /* @__PURE__ */ import_react22.default.createElement("div", { className: "absolute bottom-1.5 right-1.5 opacity-60" }, /* @__PURE__ */ import_react22.default.createElement("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react22.default.createElement("circle", { cx: "9", cy: "5", r: "1.5" }), /* @__PURE__ */ import_react22.default.createElement("circle", { cx: "15", cy: "5", r: "1.5" }), /* @__PURE__ */ import_react22.default.createElement("circle", { cx: "9", cy: "12", r: "1.5" }), /* @__PURE__ */ import_react22.default.createElement("circle", { cx: "15", cy: "12", r: "1.5" }), /* @__PURE__ */ import_react22.default.createElement("circle", { cx: "9", cy: "19", r: "1.5" }), /* @__PURE__ */ import_react22.default.createElement("circle", { cx: "15", cy: "19", r: "1.5" }))))
3405
4081
  ) : null)
3406
4082
  )
3407
4083
  );