calendarkit-pro 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,17 +1,22 @@
1
- import * as React15 from 'react';
2
- import React15__default, { useState, useId, useMemo, useCallback, useEffect, useRef } from 'react';
3
- import { useDraggable, useSensors, useSensor, PointerSensor, DndContext, DragOverlay, useDroppable } from '@dnd-kit/core';
4
- import { createSnapModifier, restrictToWindowEdges } from '@dnd-kit/modifiers';
5
- import { motion, AnimatePresence } from 'framer-motion';
6
- import { format, differenceInMinutes, subDays, addDays, differenceInMilliseconds, startOfWeek, endOfWeek, eachDayOfInterval, isSameMonth, isToday, isSameDay, startOfDay, addWeeks, addMonths, subWeeks, subMonths, startOfMonth, endOfMonth, isTomorrow } from 'date-fns';
7
- import { cva } from 'class-variance-authority';
8
- import { clsx } from 'clsx';
9
- import { twMerge } from 'tailwind-merge';
10
- import { Menu, ChevronLeft, ChevronRight, Sun, Moon, CalendarDays, CalendarRange, Calendar, ListTodo, Plus, ChevronDown, Globe, Clock, Users, Paperclip, Bell, Edit3, Copy, Trash2, X, Edit2, MapPin, ExternalLink, AlignLeft, File, Download, BellRing, Check, Repeat, Tag } from 'lucide-react';
11
- import { toZonedTime, fromZonedTime } from 'date-fns-tz';
12
- import { CSS } from '@dnd-kit/utilities';
13
- import { RRule } from 'rrule';
1
+ "use client";
14
2
 
3
+ // src/index.tsx
4
+ import React18, { useCallback as useCallback5, useId, useState as useState6, useMemo as useMemo4 } from "react";
5
+ import { DndContext, useSensor, useSensors, PointerSensor, DragOverlay } from "@dnd-kit/core";
6
+ import { createSnapModifier, restrictToWindowEdges } from "@dnd-kit/modifiers";
7
+ import { AnimatePresence as AnimatePresence3, motion as motion4 } from "framer-motion";
8
+
9
+ // src/components/CalendarHeader.tsx
10
+ import React2 from "react";
11
+ import { format } from "date-fns";
12
+
13
+ // src/components/ui/button.tsx
14
+ import * as React from "react";
15
+ import { cva } from "class-variance-authority";
16
+
17
+ // src/utils.ts
18
+ import { clsx } from "clsx";
19
+ import { twMerge } from "tailwind-merge";
15
20
  function cn(...inputs) {
16
21
  return twMerge(clsx(inputs));
17
22
  }
@@ -44,10 +49,10 @@ var buttonVariants = cva(
44
49
  }
45
50
  }
46
51
  );
47
- var Button = React15.forwardRef(
48
- ({ className, variant, size, asChild = false, ...props }, ref) => {
52
+ var Button = React.forwardRef(
53
+ ({ className, variant, size, ...props }, ref) => {
49
54
  const Comp = "button";
50
- return /* @__PURE__ */ React15.createElement(
55
+ return /* @__PURE__ */ React.createElement(
51
56
  Comp,
52
57
  {
53
58
  className: cn(buttonVariants({ variant, size, className })),
@@ -58,6 +63,9 @@ var Button = React15.forwardRef(
58
63
  }
59
64
  );
60
65
  Button.displayName = "Button";
66
+
67
+ // src/components/CalendarHeader.tsx
68
+ import { ChevronLeft, ChevronRight, Menu, Moon, Sun, CalendarDays, CalendarRange, Calendar, ListTodo } from "lucide-react";
61
69
  var CalendarHeader = ({
62
70
  currentDate,
63
71
  onPrev,
@@ -80,7 +88,7 @@ var CalendarHeader = ({
80
88
  { key: "day", icon: Calendar },
81
89
  { key: "agenda", icon: ListTodo }
82
90
  ];
83
- return /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col md:flex-row items-center justify-between px-3 md:px-5 py-3 border-b-[0px] border-border/50 bg-gradient-to-r from-background via-background to-muted/20 gap-3 md:gap-0 min-h-[64px]" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2 w-full md:w-auto justify-between md:justify-start" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2 md:gap-3" }, /* @__PURE__ */ React15__default.createElement(
91
+ return /* @__PURE__ */ React2.createElement("div", { className: "flex flex-col md:flex-row items-center justify-between px-3 md:px-5 py-3 border-b-[0px] border-border/50 bg-gradient-to-r from-background via-background to-muted/20 gap-3 md:gap-0 min-h-[64px]" }, /* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-2 w-full md:w-auto justify-between md:justify-start" }, /* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-2 md:gap-3" }, /* @__PURE__ */ React2.createElement(
84
92
  Button,
85
93
  {
86
94
  variant: "ghost",
@@ -88,8 +96,8 @@ var CalendarHeader = ({
88
96
  className: "text-muted-foreground hover:text-foreground hover:bg-accent/80 rounded-xl h-10 w-10 hidden md:inline-flex transition-all duration-200",
89
97
  onClick: onMenuClick
90
98
  },
91
- /* @__PURE__ */ React15__default.createElement(Menu, { className: "h-5 w-5" })
92
- ), /* @__PURE__ */ React15__default.createElement(
99
+ /* @__PURE__ */ React2.createElement(Menu, { className: "h-5 w-5" })
100
+ ), /* @__PURE__ */ React2.createElement(
93
101
  Button,
94
102
  {
95
103
  variant: "outline",
@@ -97,7 +105,7 @@ var CalendarHeader = ({
97
105
  className: "h-9 px-5 rounded-xl text-sm font-medium hidden sm:inline-flex border-[0.5px] border-border/60 hover:border-primary/40 hover:bg-primary/5 hover:text-primary transition-all duration-200"
98
106
  },
99
107
  translations.today
100
- ), /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center bg-muted/40 rounded-xl p-0.5" }, /* @__PURE__ */ React15__default.createElement(
108
+ ), /* @__PURE__ */ React2.createElement("div", { className: "flex items-center bg-muted/40 rounded-xl p-0.5" }, /* @__PURE__ */ React2.createElement(
101
109
  Button,
102
110
  {
103
111
  variant: "ghost",
@@ -105,8 +113,8 @@ var CalendarHeader = ({
105
113
  onClick: onPrev,
106
114
  className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200"
107
115
  },
108
- /* @__PURE__ */ React15__default.createElement(ChevronLeft, { className: "h-4 w-4 text-muted-foreground" })
109
- ), /* @__PURE__ */ React15__default.createElement(
116
+ /* @__PURE__ */ React2.createElement(ChevronLeft, { className: "h-4 w-4 text-muted-foreground" })
117
+ ), /* @__PURE__ */ React2.createElement(
110
118
  Button,
111
119
  {
112
120
  variant: "ghost",
@@ -114,8 +122,8 @@ var CalendarHeader = ({
114
122
  onClick: onNext,
115
123
  className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200"
116
124
  },
117
- /* @__PURE__ */ React15__default.createElement(ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
118
- )), /* @__PURE__ */ React15__default.createElement("div", { className: "ml-2 md:ml-4" }, /* @__PURE__ */ React15__default.createElement("h2", { className: "text-lg md:text-xl font-semibold text-foreground whitespace-nowrap capitalize tracking-tight" }, format(currentDate, "MMMM yyyy", { locale }))))), /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2 md:gap-3 w-full md:w-auto justify-end" }, onLanguageChange && language && /* @__PURE__ */ React15__default.createElement(
125
+ /* @__PURE__ */ React2.createElement(ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
126
+ )), /* @__PURE__ */ React2.createElement("div", { className: "ml-2 md:ml-4" }, /* @__PURE__ */ React2.createElement("h2", { className: "text-lg md:text-xl font-semibold text-foreground whitespace-nowrap capitalize tracking-tight" }, format(currentDate, "MMMM yyyy", { locale }))))), /* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-2 md:gap-3 w-full md:w-auto justify-end" }, onLanguageChange && language && /* @__PURE__ */ React2.createElement(
119
127
  Button,
120
128
  {
121
129
  variant: "ghost",
@@ -124,7 +132,7 @@ var CalendarHeader = ({
124
132
  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"
125
133
  },
126
134
  language
127
- ), onThemeToggle && /* @__PURE__ */ React15__default.createElement(
135
+ ), onThemeToggle && /* @__PURE__ */ React2.createElement(
128
136
  Button,
129
137
  {
130
138
  variant: "ghost",
@@ -132,8 +140,8 @@ var CalendarHeader = ({
132
140
  className: "rounded-xl h-9 w-9 hover:bg-accent/80 transition-all duration-200",
133
141
  onClick: onThemeToggle
134
142
  },
135
- isDarkMode ? /* @__PURE__ */ React15__default.createElement(Sun, { className: "h-4 w-4 text-amber-500" }) : /* @__PURE__ */ React15__default.createElement(Moon, { className: "h-4 w-4 text-muted-foreground" })
136
- ), !hideViewSwitcher && /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center bg-muted/50 backdrop-blur-sm rounded-xl p-1" }, viewConfig.map(({ key, icon: Icon }) => /* @__PURE__ */ React15__default.createElement(
143
+ isDarkMode ? /* @__PURE__ */ React2.createElement(Sun, { className: "h-4 w-4 text-amber-500" }) : /* @__PURE__ */ React2.createElement(Moon, { className: "h-4 w-4 text-muted-foreground" })
144
+ ), !hideViewSwitcher && /* @__PURE__ */ React2.createElement("div", { className: "flex items-center bg-muted/50 backdrop-blur-sm rounded-xl p-1" }, viewConfig.map(({ key, icon: Icon }) => /* @__PURE__ */ React2.createElement(
137
145
  Button,
138
146
  {
139
147
  key,
@@ -145,24 +153,40 @@ var CalendarHeader = ({
145
153
  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"
146
154
  )
147
155
  },
148
- /* @__PURE__ */ React15__default.createElement(Icon, { className: "h-3.5 w-3.5" }),
149
- /* @__PURE__ */ React15__default.createElement("span", { className: "hidden sm:inline" }, translations[key])
156
+ /* @__PURE__ */ React2.createElement(Icon, { className: "h-3.5 w-3.5" }),
157
+ /* @__PURE__ */ React2.createElement("span", { className: "hidden sm:inline" }, translations[key])
150
158
  )))));
151
159
  };
152
- var getMonthGrid = (date, weekStartOn = 0) => {
160
+
161
+ // src/components/Sidebar.tsx
162
+ import React4, { useState, useEffect } from "react";
163
+ import { Plus, ChevronDown, Globe } from "lucide-react";
164
+
165
+ // src/components/MiniCalendar.tsx
166
+ import React3 from "react";
167
+ import { format as format2, isSameMonth, isSameDay, isToday, addMonths, subMonths } from "date-fns";
168
+
169
+ // src/core/week.ts
170
+ import { eachDayOfInterval, endOfMonth, endOfWeek, startOfMonth, startOfWeek } from "date-fns";
171
+ function resolveWeekStartsOn(locale, fallback) {
172
+ return locale?.options?.weekStartsOn ?? fallback;
173
+ }
174
+ function getWeekDays(date, weekStartsOn) {
175
+ return eachDayOfInterval({
176
+ start: startOfWeek(date, { weekStartsOn }),
177
+ end: endOfWeek(date, { weekStartsOn })
178
+ });
179
+ }
180
+ function getMonthGrid(date, weekStartsOn) {
153
181
  const monthStart = startOfMonth(date);
154
- const monthEnd = endOfMonth(monthStart);
155
- const startDate = startOfWeek(monthStart, { weekStartsOn: weekStartOn });
156
- const endDate = endOfWeek(monthEnd, { weekStartsOn: weekStartOn });
157
182
  return eachDayOfInterval({
158
- start: startDate,
159
- end: endDate
183
+ start: startOfWeek(monthStart, { weekStartsOn }),
184
+ end: endOfWeek(endOfMonth(monthStart), { weekStartsOn })
160
185
  });
161
- };
162
- var uses24HourClock = (locale) => {
163
- if (!locale) return false;
164
- return !/[ap]\.?m/i.test(format(new Date(2e3, 0, 1, 13, 0), "p", { locale }));
165
- };
186
+ }
187
+
188
+ // src/components/MiniCalendar.tsx
189
+ import { ChevronLeft as ChevronLeft2, ChevronRight as ChevronRight2 } from "lucide-react";
166
190
  var MiniCalendar = ({
167
191
  currentDate,
168
192
  onDateChange,
@@ -170,12 +194,12 @@ var MiniCalendar = ({
170
194
  className,
171
195
  locale
172
196
  }) => {
173
- const [viewDate, setViewDate] = React15__default.useState(currentDate);
174
- React15__default.useEffect(() => {
197
+ const [viewDate, setViewDate] = React3.useState(currentDate);
198
+ React3.useEffect(() => {
175
199
  setViewDate(currentDate);
176
200
  }, [currentDate]);
177
- const weekStartsOn = locale?.options?.weekStartsOn ?? 0;
178
- const days = React15__default.useMemo(
201
+ const weekStartsOn = resolveWeekStartsOn(locale, 0);
202
+ const days = React3.useMemo(
179
203
  () => getMonthGrid(viewDate, weekStartsOn),
180
204
  [viewDate, weekStartsOn]
181
205
  );
@@ -199,7 +223,7 @@ var MiniCalendar = ({
199
223
  onDateChange(day);
200
224
  if (onViewChange) onViewChange("day");
201
225
  };
202
- return /* @__PURE__ */ React15__default.createElement("div", { className: cn("px-4 w-[260px]", className) }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm font-semibold text-foreground capitalize" }, format(viewDate, "MMMM yyyy", { locale })), /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center bg-muted/40 rounded-lg p-0.5" }, /* @__PURE__ */ React15__default.createElement(
226
+ return /* @__PURE__ */ React3.createElement("div", { className: cn("px-4 w-[260px]", className) }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ React3.createElement("span", { className: "text-sm font-semibold text-foreground capitalize" }, format2(viewDate, "MMMM yyyy", { locale })), /* @__PURE__ */ React3.createElement("div", { className: "flex items-center bg-muted/40 rounded-lg p-0.5" }, /* @__PURE__ */ React3.createElement(
203
227
  Button,
204
228
  {
205
229
  variant: "ghost",
@@ -208,8 +232,8 @@ var MiniCalendar = ({
208
232
  onClick: handlePrev,
209
233
  "aria-label": "Previous month"
210
234
  },
211
- /* @__PURE__ */ React15__default.createElement(ChevronLeft, { className: "h-4 w-4" })
212
- ), /* @__PURE__ */ React15__default.createElement(
235
+ /* @__PURE__ */ React3.createElement(ChevronLeft2, { className: "h-4 w-4" })
236
+ ), /* @__PURE__ */ React3.createElement(
213
237
  Button,
214
238
  {
215
239
  variant: "ghost",
@@ -218,12 +242,12 @@ var MiniCalendar = ({
218
242
  onClick: handleNext,
219
243
  "aria-label": "Next month"
220
244
  },
221
- /* @__PURE__ */ React15__default.createElement(ChevronRight, { className: "h-4 w-4" })
222
- ))), /* @__PURE__ */ React15__default.createElement("div", { className: "grid grid-cols-7 gap-y-2 text-center mb-2" }, weekDays.map((day, i) => /* @__PURE__ */ React15__default.createElement("div", { key: `${day}-${i}`, className: "text-[10px] text-muted-foreground/70 font-semibold uppercase" }, day))), /* @__PURE__ */ React15__default.createElement("div", { className: "grid grid-cols-7 gap-y-1 text-center" }, days.map((day) => {
245
+ /* @__PURE__ */ React3.createElement(ChevronRight2, { className: "h-4 w-4" })
246
+ ))), /* @__PURE__ */ React3.createElement("div", { className: "grid grid-cols-7 gap-y-2 text-center mb-2" }, weekDays.map((day, i) => /* @__PURE__ */ React3.createElement("div", { key: `${day}-${i}`, className: "text-[10px] text-muted-foreground/70 font-semibold uppercase" }, day))), /* @__PURE__ */ React3.createElement("div", { className: "grid grid-cols-7 gap-y-1 text-center" }, days.map((day) => {
223
247
  const isSelected = isSameDay(day, currentDate);
224
248
  const isCurrentMonth = isSameMonth(day, viewDate);
225
249
  const isTodayDate = isToday(day);
226
- return /* @__PURE__ */ React15__default.createElement(
250
+ return /* @__PURE__ */ React3.createElement(
227
251
  "button",
228
252
  {
229
253
  key: day.toISOString(),
@@ -236,10 +260,202 @@ var MiniCalendar = ({
236
260
  !isSelected && isTodayDate && "bg-primary/10 text-primary ring-1 ring-primary/30"
237
261
  )
238
262
  },
239
- format(day, "d")
263
+ format2(day, "d")
240
264
  );
241
265
  })));
242
266
  };
267
+
268
+ // src/components/Sidebar.tsx
269
+ import { toZonedTime } from "date-fns-tz";
270
+ import { format as format4 } from "date-fns";
271
+
272
+ // src/core/format.ts
273
+ import { format as format3 } from "date-fns";
274
+
275
+ // src/locales/index.ts
276
+ var en = {
277
+ today: "Today",
278
+ month: "Month",
279
+ week: "Week",
280
+ day: "Day",
281
+ agenda: "Agenda",
282
+ resource: "Resources",
283
+ createEvent: "Create Event",
284
+ editEvent: "Edit Event",
285
+ delete: "Delete",
286
+ save: "Save",
287
+ cancel: "Cancel",
288
+ title: "Add title",
289
+ start: "Start",
290
+ end: "End",
291
+ allDay: "All Day",
292
+ description: "Description",
293
+ repeat: "Repeat",
294
+ noRepeat: "Does not repeat",
295
+ selectCalendar: "Select Calendar",
296
+ selectType: "Select Type",
297
+ daily: "Daily",
298
+ weekly: "Weekly",
299
+ monthly: "Monthly",
300
+ yearly: "Yearly",
301
+ search: "Search events...",
302
+ allTypes: "All Types",
303
+ timezone: "Time zone",
304
+ localTime: "Local Time",
305
+ create: "Create",
306
+ calendars: "Calendars",
307
+ event: "Event",
308
+ task: "Task",
309
+ appointmentSchedule: "Appointment schedule",
310
+ new: "New",
311
+ dateAndTime: "Date & Time",
312
+ whosJoining: "Who's joining?",
313
+ suggestedTimes: "Suggested times for guests",
314
+ viewSuggestions: "View suggestions",
315
+ whereWillItBe: "Where will it be?",
316
+ location: "Enter address",
317
+ descriptionAndAttachments: "Description",
318
+ dragAndDrop: "Drag & drop files or",
319
+ guests: "Guests",
320
+ addGuests: "Add guests",
321
+ addAttachment: "Upload files",
322
+ moreOptions: "More options",
323
+ doesNotRepeat: "Does not repeat",
324
+ locationHelpText: 'Enter a physical address (e.g. "123 Main St") to generate the map.',
325
+ notes: "Notes...",
326
+ guestCount: "guest",
327
+ guestsCount: "guests",
328
+ repeatFor: "Repeat for",
329
+ times: "times",
330
+ until: "Until",
331
+ endRepeat: "End repeat",
332
+ never: "Never",
333
+ afterOccurrences: "After occurrences",
334
+ onDate: "On date",
335
+ tomorrow: "Tomorrow",
336
+ edit: "Edit",
337
+ duplicate: "Duplicate",
338
+ eventSingular: "event",
339
+ eventPlural: "events",
340
+ allCaughtUp: "All caught up!",
341
+ noEventsScheduled: "No events scheduled",
342
+ noUpcoming: "Your schedule is clear",
343
+ noUpcomingHint: "No upcoming events to show. Create a new event to start planning."
344
+ };
345
+ var fr = {
346
+ today: "Aujourd'hui",
347
+ month: "Mois",
348
+ week: "Semaine",
349
+ day: "Jour",
350
+ agenda: "Agenda",
351
+ resource: "Ressources",
352
+ createEvent: "Cr\xE9er un \xE9v\xE9nement",
353
+ editEvent: "Modifier l'\xE9v\xE9nement",
354
+ delete: "Supprimer",
355
+ save: "Enregistrer",
356
+ cancel: "Annuler",
357
+ title: "Ajouter un titre",
358
+ start: "D\xE9but",
359
+ end: "Fin",
360
+ allDay: "Toute la journ\xE9e",
361
+ description: "Description",
362
+ repeat: "R\xE9p\xE9ter",
363
+ noRepeat: "Ne se r\xE9p\xE8te pas",
364
+ selectCalendar: "S\xE9lectionner un calendrier",
365
+ selectType: "S\xE9lectionner un type",
366
+ daily: "Quotidien",
367
+ weekly: "Hebdomadaire",
368
+ monthly: "Mensuel",
369
+ yearly: "Annuel",
370
+ search: "Rechercher...",
371
+ allTypes: "Tous les types",
372
+ timezone: "Fuseau horaire",
373
+ localTime: "Heure locale",
374
+ create: "Cr\xE9er",
375
+ calendars: "Calendriers",
376
+ event: "\xC9v\xE9nement",
377
+ task: "T\xE2che",
378
+ appointmentSchedule: "Planning de rendez-vous",
379
+ new: "Nouveau",
380
+ dateAndTime: "Date et heure",
381
+ whosJoining: "Qui participe ?",
382
+ suggestedTimes: "Horaires sugg\xE9r\xE9s",
383
+ viewSuggestions: "Voir les suggestions",
384
+ whereWillItBe: "O\xF9 aura lieu ?",
385
+ location: "Entrer une adresse",
386
+ descriptionAndAttachments: "Description",
387
+ dragAndDrop: "Glisser-d\xE9poser des fichiers ou",
388
+ guests: "Invit\xE9s",
389
+ addGuests: "Ajouter des invit\xE9s",
390
+ addAttachment: "T\xE9l\xE9charger des fichiers",
391
+ moreOptions: "Plus d'options",
392
+ doesNotRepeat: "Ne se r\xE9p\xE8te pas",
393
+ locationHelpText: 'Entrez une adresse physique (ex: "123 Rue Principale") pour g\xE9n\xE9rer la carte.',
394
+ notes: "Notes...",
395
+ guestCount: "invit\xE9",
396
+ guestsCount: "invit\xE9s",
397
+ repeatFor: "R\xE9p\xE9ter pendant",
398
+ times: "fois",
399
+ until: "Jusqu'au",
400
+ endRepeat: "Fin de r\xE9p\xE9tition",
401
+ never: "Jamais",
402
+ afterOccurrences: "Apr\xE8s occurrences",
403
+ onDate: "\xC0 la date",
404
+ tomorrow: "Demain",
405
+ edit: "Modifier",
406
+ duplicate: "Dupliquer",
407
+ eventSingular: "\xE9v\xE9nement",
408
+ eventPlural: "\xE9v\xE9nements",
409
+ allCaughtUp: "Tout est \xE0 jour !",
410
+ noEventsScheduled: "Aucun \xE9v\xE9nement pr\xE9vu",
411
+ noUpcoming: "Votre planning est libre",
412
+ noUpcomingHint: "Aucun \xE9v\xE9nement \xE0 venir. Cr\xE9ez un nouvel \xE9v\xE9nement pour commencer \xE0 planifier."
413
+ };
414
+
415
+ // src/core/format.ts
416
+ var clockCache = /* @__PURE__ */ new WeakMap();
417
+ function uses24HourClock(locale) {
418
+ if (!locale) return false;
419
+ let is24 = clockCache.get(locale);
420
+ if (is24 === void 0) {
421
+ is24 = !/[ap]\.?m/i.test(format3(new Date(2e3, 0, 1, 13, 0), "p", { locale }));
422
+ clockCache.set(locale, is24);
423
+ }
424
+ return is24;
425
+ }
426
+ var H24 = { hour: "H:mm", time: "H:mm", compact: "H:mm" };
427
+ var H12 = { hour: "h a", time: "h:mm a", compact: "h:mm" };
428
+ function timeFormats(locale) {
429
+ return uses24HourClock(locale) ? H24 : H12;
430
+ }
431
+ var MAX_FORMATTERS = 50;
432
+ var formatters = /* @__PURE__ */ new Map();
433
+ function getDateTimeFormat(locale, timeZone, options) {
434
+ const key = `${locale}|${timeZone ?? ""}|${JSON.stringify(options)}`;
435
+ let formatter = formatters.get(key);
436
+ if (formatter) {
437
+ formatters.delete(key);
438
+ } else {
439
+ formatter = new Intl.DateTimeFormat(locale, { ...options, timeZone });
440
+ if (formatters.size >= MAX_FORMATTERS) {
441
+ formatters.delete(formatters.keys().next().value);
442
+ }
443
+ }
444
+ formatters.set(key, formatter);
445
+ return formatter;
446
+ }
447
+ function timeZoneAbbreviation(date, timeZone) {
448
+ try {
449
+ return getDateTimeFormat("en-US", timeZone, { timeZoneName: "short" }).formatToParts(date).find((part) => part.type === "timeZoneName")?.value ?? "";
450
+ } catch {
451
+ return "";
452
+ }
453
+ }
454
+ function resolveTranslations(language, overrides) {
455
+ return { ...language === "fr" ? fr : en, ...overrides };
456
+ }
457
+
458
+ // src/components/Sidebar.tsx
243
459
  var Sidebar = ({
244
460
  currentDate,
245
461
  onDateChange,
@@ -270,14 +486,7 @@ var Sidebar = ({
270
486
  { id: "3", label: "Tasks", color: "#6366f1", active: true }
271
487
  ];
272
488
  const displayCalendars = calendars || defaultCalendars;
273
- const getAcronym = (tz) => {
274
- if (!tz || !now) return "LOC";
275
- try {
276
- return new Intl.DateTimeFormat("en-US", { timeZone: tz, timeZoneName: "short" }).formatToParts(now).find((part) => part.type === "timeZoneName")?.value || "";
277
- } catch (e) {
278
- return "";
279
- }
280
- };
489
+ const getAcronym = (tz) => !tz || !now ? "LOC" : timeZoneAbbreviation(now, tz);
281
490
  const timezones = [
282
491
  { value: "", label: translations?.localTime || "Local Time", acronym: "LOC" },
283
492
  { value: "UTC", label: "UTC", acronym: "UTC" },
@@ -295,56 +504,53 @@ var Sidebar = ({
295
504
  ];
296
505
  const formatTzLabel = (tz, showTime = true) => {
297
506
  if (!hasMounted || !now || !showTime) {
298
- return /* @__PURE__ */ React15__default.createElement("span", null, tz.label);
507
+ return /* @__PURE__ */ React4.createElement("span", null, tz.label);
299
508
  }
300
509
  let time = "";
301
510
  let acronym = tz.acronym;
302
511
  try {
303
512
  if (!tz.value) {
304
- time = format(now, "HH:mm");
305
- try {
306
- acronym = new Intl.DateTimeFormat("en-US", { timeZoneName: "short" }).formatToParts(now).find((part) => part.type === "timeZoneName")?.value || "LOC";
307
- } catch (e) {
308
- }
513
+ time = format4(now, "HH:mm");
514
+ acronym = timeZoneAbbreviation(now) || "LOC";
309
515
  } else {
310
516
  const zDate = toZonedTime(now, tz.value);
311
- time = format(zDate, "HH:mm");
517
+ time = format4(zDate, "HH:mm");
312
518
  const dynAcronym = getAcronym(tz.value);
313
519
  if (dynAcronym && !dynAcronym.includes("GMT") && !dynAcronym.includes("Time")) {
314
520
  acronym = dynAcronym;
315
521
  }
316
522
  }
317
- } catch (e) {
318
- return /* @__PURE__ */ React15__default.createElement("span", null, tz.label);
523
+ } catch {
524
+ return /* @__PURE__ */ React4.createElement("span", null, tz.label);
319
525
  }
320
- return /* @__PURE__ */ React15__default.createElement("div", { className: "flex justify-between w-full" }, /* @__PURE__ */ React15__default.createElement("span", null, tz.label), /* @__PURE__ */ React15__default.createElement("span", { className: "text-muted-foreground ml-2 tabular-nums" }, time, " ", /* @__PURE__ */ React15__default.createElement("span", { className: "text-xs opacity-75" }, "(", acronym, ")")));
526
+ return /* @__PURE__ */ React4.createElement("div", { className: "flex justify-between w-full" }, /* @__PURE__ */ React4.createElement("span", null, tz.label), /* @__PURE__ */ React4.createElement("span", { className: "text-muted-foreground ml-2 tabular-nums" }, time, " ", /* @__PURE__ */ React4.createElement("span", { className: "text-xs opacity-75" }, "(", acronym, ")")));
321
527
  };
322
528
  const selectedTzObj = timezones.find((t) => t.value === (timezone || ""));
323
529
  const selectedTimezoneLabel = selectedTzObj ? formatTzLabel(selectedTzObj) : translations?.localTime || "Local Time";
324
- return /* @__PURE__ */ React15__default.createElement("div", { className: cn("flex flex-col w-[260px] overflow-x-hidden h-full bg-gradient-to-b scrollbar-hide from-background via-background to-muted/10 pt-4 pb-4 overflow-y-auto hidden lg:flex", className) }, !readOnly && /* @__PURE__ */ React15__default.createElement("div", { className: "px-4 mb-6" }, /* @__PURE__ */ React15__default.createElement(
530
+ return /* @__PURE__ */ React4.createElement("div", { className: cn("flex flex-col w-[260px] overflow-x-hidden h-full bg-gradient-to-b scrollbar-hide from-background via-background to-muted/10 pt-4 pb-4 overflow-y-auto hidden lg:flex", className) }, !readOnly && /* @__PURE__ */ React4.createElement("div", { className: "px-4 mb-6" }, /* @__PURE__ */ React4.createElement(
325
531
  Button,
326
532
  {
327
533
  className: "w-full rounded-2xl shadow-lg bg-primary text-primary-foreground hover:bg-primary/90 h-12 gap-3 justify-center transition-all duration-300 hover:shadow-xl hover:shadow-primary/20 hover:scale-[1.02] active:scale-[0.98] font-semibold",
328
534
  onClick: onEventCreate
329
535
  },
330
- /* @__PURE__ */ React15__default.createElement(Plus, { className: "w-5 h-5" }),
331
- /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm" }, translations?.create || "Create")
332
- )), /* @__PURE__ */ React15__default.createElement(MiniCalendar, { currentDate, onDateChange, onViewChange, locale }), /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 px-4 space-y-5 mt-5" }, /* @__PURE__ */ React15__default.createElement("div", { className: "bg-muted/20 rounded-2xl p-3 border-[0px] border-border/30" }, /* @__PURE__ */ React15__default.createElement(
536
+ /* @__PURE__ */ React4.createElement(Plus, { className: "w-5 h-5" }),
537
+ /* @__PURE__ */ React4.createElement("span", { className: "text-sm" }, translations?.create || "Create")
538
+ )), /* @__PURE__ */ React4.createElement(MiniCalendar, { currentDate, onDateChange, onViewChange, locale }), /* @__PURE__ */ React4.createElement("div", { className: "flex-1 px-4 space-y-5 mt-5" }, /* @__PURE__ */ React4.createElement("div", { className: "bg-muted/20 rounded-2xl p-3 border-[0px] border-border/30" }, /* @__PURE__ */ React4.createElement(
333
539
  "div",
334
540
  {
335
541
  className: "flex items-center justify-between cursor-pointer hover:bg-accent/50 p-2 -m-1 rounded-xl mb-2 transition-all duration-200",
336
542
  onClick: () => setCalendarsOpen(!calendarsOpen)
337
543
  },
338
- /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm font-semibold text-foreground" }, translations?.calendars || "Calendars"),
339
- /* @__PURE__ */ React15__default.createElement(ChevronDown, { className: cn("w-4 h-4 text-muted-foreground transition-transform duration-200", calendarsOpen && "rotate-180") })
340
- ), calendarsOpen && /* @__PURE__ */ React15__default.createElement("div", { className: "space-y-1" }, displayCalendars.map((cal) => /* @__PURE__ */ React15__default.createElement(
544
+ /* @__PURE__ */ React4.createElement("span", { className: "text-sm font-semibold text-foreground" }, translations?.calendars || "Calendars"),
545
+ /* @__PURE__ */ React4.createElement(ChevronDown, { className: cn("w-4 h-4 text-muted-foreground transition-transform duration-200", calendarsOpen && "rotate-180") })
546
+ ), calendarsOpen && /* @__PURE__ */ React4.createElement("div", { className: "space-y-1" }, displayCalendars.map((cal) => /* @__PURE__ */ React4.createElement(
341
547
  "div",
342
548
  {
343
549
  key: cal.id,
344
550
  className: "flex items-center gap-3 py-2 px-2 hover:bg-accent/60 rounded-xl cursor-pointer group transition-all duration-200",
345
551
  onClick: () => onCalendarToggle?.(cal.id, !(cal.active ?? true))
346
552
  },
347
- /* @__PURE__ */ React15__default.createElement("div", { className: "relative flex items-center justify-center" }, /* @__PURE__ */ React15__default.createElement(
553
+ /* @__PURE__ */ React4.createElement("div", { className: "relative flex items-center justify-center" }, /* @__PURE__ */ React4.createElement(
348
554
  "input",
349
555
  {
350
556
  type: "checkbox",
@@ -357,7 +563,7 @@ var Sidebar = ({
357
563
  style: { "--primary-color": cal.color },
358
564
  "data-cal-id": cal.id
359
565
  }
360
- ), /* @__PURE__ */ React15__default.createElement("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none opacity-0 peer-checked:opacity-100 transition-opacity" }, /* @__PURE__ */ React15__default.createElement("svg", { className: "w-3.5 h-3.5 text-white", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3 }, /* @__PURE__ */ React15__default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }))), /* @__PURE__ */ React15__default.createElement("style", null, `
566
+ ), /* @__PURE__ */ React4.createElement("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none opacity-0 peer-checked:opacity-100 transition-opacity" }, /* @__PURE__ */ React4.createElement("svg", { className: "w-3.5 h-3.5 text-white", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3 }, /* @__PURE__ */ React4.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }))), /* @__PURE__ */ React4.createElement("style", null, `
361
567
  input[type="checkbox"][data-cal-id="${cal.id}"]:checked {
362
568
  background-color: ${cal.color} !important;
363
569
  border-color: ${cal.color} !important;
@@ -366,23 +572,23 @@ var Sidebar = ({
366
572
  --tw-ring-color: ${cal.color}40 !important;
367
573
  }
368
574
  `)),
369
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2 flex-1 min-w-0" }, /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm text-foreground/90 truncate font-medium" }, cal.label)),
370
- /* @__PURE__ */ React15__default.createElement(
575
+ /* @__PURE__ */ React4.createElement("div", { className: "flex items-center gap-2 flex-1 min-w-0" }, /* @__PURE__ */ React4.createElement("span", { className: "text-sm text-foreground/90 truncate font-medium" }, cal.label)),
576
+ /* @__PURE__ */ React4.createElement(
371
577
  "div",
372
578
  {
373
579
  className: "w-2 h-2 rounded-full opacity-60 group-hover:opacity-100 transition-opacity",
374
580
  style: { backgroundColor: cal.color }
375
581
  }
376
582
  )
377
- ))))), /* @__PURE__ */ React15__default.createElement("div", { className: "mt-auto px-4 pt-5" }, /* @__PURE__ */ React15__default.createElement("div", { className: "bg-muted/20 rounded-2xl p-3" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2 mb-3" }, /* @__PURE__ */ React15__default.createElement("div", { className: "p-1.5 bg-primary/10 rounded-lg" }, /* @__PURE__ */ React15__default.createElement(Globe, { className: "w-4 h-4 text-primary" })), /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm font-semibold text-foreground" }, translations?.timezone || "Timezone")), /* @__PURE__ */ React15__default.createElement("div", { className: "relative" }, /* @__PURE__ */ React15__default.createElement(
583
+ ))))), /* @__PURE__ */ React4.createElement("div", { className: "mt-auto px-4 pt-5" }, /* @__PURE__ */ React4.createElement("div", { className: "bg-muted/20 rounded-2xl p-3" }, /* @__PURE__ */ React4.createElement("div", { className: "flex items-center gap-2 mb-3" }, /* @__PURE__ */ React4.createElement("div", { className: "p-1.5 bg-primary/10 rounded-lg" }, /* @__PURE__ */ React4.createElement(Globe, { className: "w-4 h-4 text-primary" })), /* @__PURE__ */ React4.createElement("span", { className: "text-sm font-semibold text-foreground" }, translations?.timezone || "Timezone")), /* @__PURE__ */ React4.createElement("div", { className: "relative" }, /* @__PURE__ */ React4.createElement(
378
584
  "button",
379
585
  {
380
586
  onClick: () => setTimezoneOpen(!timezoneOpen),
381
587
  className: "w-full flex items-center justify-between bg-blue-200/40 hover:bg-blue-200/80 rounded-xl py-2.5 pl-4 pr-3 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary/50 transition-all duration-200 text-left"
382
588
  },
383
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 truncate mr-2 font-medium" }, selectedTimezoneLabel),
384
- /* @__PURE__ */ React15__default.createElement(ChevronDown, { className: cn("w-4 h-4 text-muted-foreground transition-transform duration-200", timezoneOpen && "rotate-180") })
385
- ), timezoneOpen && /* @__PURE__ */ React15__default.createElement(React15__default.Fragment, null, /* @__PURE__ */ React15__default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setTimezoneOpen(false) }), /* @__PURE__ */ React15__default.createElement("div", { className: "absolute bottom-full left-0 w-full mb-2 bg-background rounded-xl shadow-2xl z-50 max-h-[260px] overflow-y-auto p-1.5 animate-in fade-in zoom-in-95 duration-200 backdrop-blur-none" }, timezones.map((tz) => /* @__PURE__ */ React15__default.createElement(
589
+ /* @__PURE__ */ React4.createElement("div", { className: "flex-1 truncate mr-2 font-medium" }, selectedTimezoneLabel),
590
+ /* @__PURE__ */ React4.createElement(ChevronDown, { className: cn("w-4 h-4 text-muted-foreground transition-transform duration-200", timezoneOpen && "rotate-180") })
591
+ ), timezoneOpen && /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setTimezoneOpen(false) }), /* @__PURE__ */ React4.createElement("div", { className: "absolute bottom-full left-0 w-full mb-2 bg-background rounded-xl shadow-2xl z-50 max-h-[260px] overflow-y-auto p-1.5 animate-in fade-in zoom-in-95 duration-200 backdrop-blur-none" }, timezones.map((tz) => /* @__PURE__ */ React4.createElement(
386
592
  "div",
387
593
  {
388
594
  key: tz.value,
@@ -398,26 +604,202 @@ var Sidebar = ({
398
604
  formatTzLabel(tz)
399
605
  ))))))));
400
606
  };
401
- var DraggableEvent = ({ event, children, className, style: propStyle, ...props }) => {
607
+
608
+ // src/views/MonthView.tsx
609
+ import React7, { useMemo } from "react";
610
+ import { format as format7, isSameDay as isSameDay3, isSameMonth as isSameMonth2 } from "date-fns";
611
+
612
+ // src/core/events.ts
613
+ import { addDays, format as format6, startOfDay as startOfDay2 } from "date-fns";
614
+
615
+ // src/core/timezone.ts
616
+ import { format as format5, isSameDay as isSameDay2, startOfDay } from "date-fns";
617
+ import { fromZonedTime, toZonedTime as toZonedTime2 } from "date-fns-tz";
618
+
619
+ // src/core/warn.ts
620
+ var warned = /* @__PURE__ */ new Set();
621
+ function isProductionBuild() {
622
+ try {
623
+ return process.env.NODE_ENV === "production";
624
+ } catch {
625
+ return false;
626
+ }
627
+ }
628
+ function warnOnce(key, message) {
629
+ if (isProductionBuild() || warned.has(key)) return;
630
+ warned.add(key);
631
+ console.warn(`[calendarkit-pro] ${message}`);
632
+ }
633
+
634
+ // src/core/timezone.ts
635
+ var validity = /* @__PURE__ */ new Map();
636
+ function resolveTimeZone(tz) {
637
+ if (!tz) return void 0;
638
+ let valid = validity.get(tz);
639
+ if (valid === void 0) {
640
+ try {
641
+ new Intl.DateTimeFormat("en-US", { timeZone: tz });
642
+ valid = true;
643
+ } catch {
644
+ valid = false;
645
+ }
646
+ validity.set(tz, valid);
647
+ }
648
+ if (!valid) {
649
+ warnOnce(`invalid-timezone:${tz}`, `Unknown timezone "${tz}", falling back to local time.`);
650
+ return void 0;
651
+ }
652
+ return tz;
653
+ }
654
+ function toDisplay(date, tz) {
655
+ const zone = resolveTimeZone(tz);
656
+ return zone ? toZonedTime2(date, zone) : date;
657
+ }
658
+ function fromDisplay(wall, tz) {
659
+ const zone = resolveTimeZone(tz);
660
+ return zone ? fromZonedTime(wall, zone) : new Date(wall);
661
+ }
662
+ function minutesSinceDisplayMidnight(date, tz) {
663
+ const wall = toDisplay(date, tz);
664
+ return wall.getHours() * 60 + wall.getMinutes();
665
+ }
666
+ function isSameDisplayDay(date, day, tz) {
667
+ return isSameDay2(toDisplay(date, tz), day);
668
+ }
669
+ function displayToday(tz, now = /* @__PURE__ */ new Date()) {
670
+ return startOfDay(toDisplay(now, tz));
671
+ }
672
+
673
+ // src/core/events.ts
674
+ var toDate = (value) => value === void 0 || value === null ? void 0 : value instanceof Date ? value : new Date(value);
675
+ var isValidDate = (date) => !!date && !Number.isNaN(date.getTime());
676
+ var normalizedEvent = /* @__PURE__ */ new WeakMap();
677
+ var normalizedList = /* @__PURE__ */ new WeakMap();
678
+ function normalizeEvent(event) {
679
+ const cached = normalizedEvent.get(event);
680
+ if (cached !== void 0) return cached;
681
+ const start = toDate(event.start);
682
+ const end = toDate(event.end);
683
+ let result = null;
684
+ if (!isValidDate(start) || !isValidDate(end)) {
685
+ warnOnce(`invalid-date:${event.id}`, `Event "${event.id}" has an invalid start or end date and was skipped.`);
686
+ } else if (end.getTime() < start.getTime()) {
687
+ warnOnce(`end-before-start:${event.id}`, `Event "${event.id}" ends before it starts and was skipped.`);
688
+ } else {
689
+ const needsCopy = start !== event.start || end !== event.end || needsRecurrenceCopy(event);
690
+ result = needsCopy ? {
691
+ ...event,
692
+ start,
693
+ end,
694
+ recurrence: event.recurrence && {
695
+ ...event.recurrence,
696
+ until: toDate(event.recurrence.until),
697
+ exdates: event.recurrence.exdates?.map((d) => toDate(d))
698
+ }
699
+ } : event;
700
+ }
701
+ normalizedEvent.set(event, result);
702
+ return result;
703
+ }
704
+ function needsRecurrenceCopy(event) {
705
+ const r = event.recurrence;
706
+ if (!r) return false;
707
+ return r.until !== void 0 && !(r.until instanceof Date) || !!r.exdates?.some((d) => !(d instanceof Date));
708
+ }
709
+ function normalizeEvents(events) {
710
+ const cached = normalizedList.get(events);
711
+ if (cached) return cached;
712
+ const seen = /* @__PURE__ */ new Set();
713
+ const result = [];
714
+ for (const event of events) {
715
+ const normalized = normalizeEvent(event);
716
+ if (!normalized) continue;
717
+ if (seen.has(normalized.id)) {
718
+ warnOnce(`duplicate-id:${normalized.id}`, `Duplicate event id "${normalized.id}": ids must be unique.`);
719
+ }
720
+ seen.add(normalized.id);
721
+ result.push(normalized);
722
+ }
723
+ normalizedList.set(events, result);
724
+ return result;
725
+ }
726
+ var dayKey = (wall) => format6(wall, "yyyy-MM-dd");
727
+ function memoByZone(cache, events, tz, compute) {
728
+ let byZone = cache.get(events);
729
+ if (!byZone) {
730
+ byZone = /* @__PURE__ */ new Map();
731
+ cache.set(events, byZone);
732
+ }
733
+ const key = tz ?? "";
734
+ let value = byZone.get(key);
735
+ if (value === void 0) {
736
+ value = compute();
737
+ byZone.set(key, value);
738
+ }
739
+ return value;
740
+ }
741
+ var startDayCache = /* @__PURE__ */ new WeakMap();
742
+ function eventsByStartDay(events, tz) {
743
+ return memoByZone(startDayCache, events, tz, () => {
744
+ const map = /* @__PURE__ */ new Map();
745
+ for (const event of events) {
746
+ const key = dayKey(toDisplay(event.start, tz));
747
+ const bucket = map.get(key);
748
+ if (bucket) bucket.push(event);
749
+ else map.set(key, [event]);
750
+ }
751
+ return map;
752
+ });
753
+ }
754
+ var segmentCache = /* @__PURE__ */ new WeakMap();
755
+ function segmentsByDisplayDay(events, tz, range) {
756
+ const cacheKey = range ? `${tz ?? ""}|${range.start.getTime()}|${range.end.getTime()}` : tz;
757
+ return memoByZone(segmentCache, events, cacheKey, () => {
758
+ const map = /* @__PURE__ */ new Map();
759
+ for (const event of events) {
760
+ const wallStart = toDisplay(event.start, tz);
761
+ const rawEnd = toDisplay(event.end, tz);
762
+ const wallEnd = rawEnd < wallStart ? wallStart : rawEnd;
763
+ if (range && (wallEnd < range.start || wallStart >= range.end)) continue;
764
+ let day = startOfDay2(range && wallStart < range.start ? range.start : wallStart);
765
+ const stop = range && wallEnd > range.end ? range.end : wallEnd;
766
+ do {
767
+ const next = addDays(day, 1);
768
+ const start = wallStart > day ? wallStart : day;
769
+ const end = wallEnd < next ? wallEnd : next;
770
+ if (end > start || wallStart.getTime() === wallEnd.getTime()) {
771
+ const key = dayKey(day);
772
+ const bucket = map.get(key);
773
+ const segment = { event, start, end };
774
+ if (bucket) bucket.push(segment);
775
+ else map.set(key, [segment]);
776
+ }
777
+ day = next;
778
+ } while (day < stop);
779
+ }
780
+ return map;
781
+ });
782
+ }
783
+
784
+ // src/components/dnd/DraggableEvent.tsx
785
+ import React5 from "react";
786
+ import { useDraggable } from "@dnd-kit/core";
787
+ import { CSS } from "@dnd-kit/utilities";
788
+ var DraggableEventImpl = ({ event, dragId, grabOffsetMs, children, className, style: propStyle, ...props }) => {
402
789
  const dragDisabled = isEventDragDisabled(event);
403
790
  const { attributes, listeners, setNodeRef, transform, isDragging } = useDraggable({
404
- id: event.id,
405
- data: { event },
791
+ id: dragId ?? event.id,
792
+ data: { event, grabOffsetMs },
406
793
  disabled: dragDisabled
407
794
  });
408
795
  const style = {
409
796
  ...propStyle,
410
797
  transform: CSS.Translate.toString(transform),
411
798
  zIndex: isDragging ? 100 : propStyle?.zIndex,
412
- // When dragging, we want the ORIGINAL element to be almost invisible (or fully invisible)
413
- // so that the DragOverlay (the "ghost") is the only thing the user focuses on.
414
- // If we set opacity: 0, it disappears. If 0.1, it's a faint placeholder.
415
- // The user asked for "Make the entire dragged item transparent".
416
- // Usually this means the original item should be faded out while the drag overlay is moving.
799
+ // Hide the original while dragging: the DragOverlay ghost is what the user follows.
417
800
  opacity: isDragging ? 0 : propStyle?.opacity
418
- // Hiding original element completely
419
801
  };
420
- return /* @__PURE__ */ React15__default.createElement(
802
+ return /* @__PURE__ */ React5.createElement(
421
803
  "div",
422
804
  {
423
805
  ref: setNodeRef,
@@ -430,32 +812,59 @@ var DraggableEvent = ({ event, children, className, style: propStyle, ...props }
430
812
  children
431
813
  );
432
814
  };
433
- var DroppableCell = ({ id, date, resourceId, children, className, style, onClick }) => {
815
+ var DraggableEvent = React5.memo(DraggableEventImpl);
816
+
817
+ // src/components/dnd/DroppableCell.tsx
818
+ import React6 from "react";
819
+ import { useDroppable } from "@dnd-kit/core";
820
+ var QUARTER_HOVER = [
821
+ "hover:bg-blue-50/50 dark:hover:bg-blue-900/10",
822
+ "hover:bg-blue-50/80 dark:hover:bg-blue-900/20",
823
+ "hover:bg-blue-100/50 dark:hover:bg-blue-900/30",
824
+ "hover:bg-blue-100/80 dark:hover:bg-blue-900/40"
825
+ ];
826
+ var QUARTER_ACTIVE = [
827
+ "bg-blue-50/50 dark:bg-blue-900/10 ring-2 ring-primary ring-inset",
828
+ "bg-blue-50/80 dark:bg-blue-900/20 ring-2 ring-primary ring-inset",
829
+ "bg-blue-100/50 dark:bg-blue-900/30 ring-2 ring-primary ring-inset",
830
+ "bg-blue-100/80 dark:bg-blue-900/40 ring-2 ring-primary ring-inset"
831
+ ];
832
+ var quarterOf = (date) => Math.min(3, Math.floor(date.getMinutes() / 15));
833
+ var DroppableCellImpl = ({ id, date, resourceId, children, className, style, onClick, onSlotClick }) => {
434
834
  const { isOver, setNodeRef } = useDroppable({
435
835
  id,
436
836
  data: { date, resourceId }
437
837
  });
438
- const minutes = date.getMinutes();
439
- const quarterClass = minutes === 0 ? "hover:bg-blue-50/50 dark:hover:bg-blue-900/10" : minutes === 15 ? "hover:bg-blue-50/80 dark:hover:bg-blue-900/20" : minutes === 30 ? "hover:bg-blue-100/50 dark:hover:bg-blue-900/30" : "hover:bg-blue-100/80 dark:hover:bg-blue-900/40";
440
- const activeQuarterClass = minutes === 0 ? "bg-blue-50/50 dark:bg-blue-900/10 ring-2 ring-primary ring-inset" : minutes === 15 ? "bg-blue-50/80 dark:bg-blue-900/20 ring-2 ring-primary ring-inset" : minutes === 30 ? "bg-blue-100/50 dark:bg-blue-900/30 ring-2 ring-primary ring-inset" : "bg-blue-100/80 dark:bg-blue-900/40 ring-2 ring-primary ring-inset";
441
- return /* @__PURE__ */ React15__default.createElement(
838
+ const quarter = quarterOf(date);
839
+ return /* @__PURE__ */ React6.createElement(
442
840
  "div",
443
841
  {
444
842
  ref: setNodeRef,
445
843
  className: cn(
446
844
  className,
447
- quarterClass,
448
- isOver && activeQuarterClass
845
+ QUARTER_HOVER[quarter],
846
+ isOver && QUARTER_ACTIVE[quarter],
847
+ onSlotClick && "cursor-pointer"
449
848
  ),
450
849
  style,
451
- onClick
850
+ onClick: onSlotClick ? () => onSlotClick(date, resourceId) : onClick
452
851
  },
453
852
  children
454
853
  );
455
854
  };
855
+ var shallowEqualStyle = (a, b) => {
856
+ if (a === b) return true;
857
+ if (!a || !b) return false;
858
+ const keys = Object.keys(a);
859
+ return keys.length === Object.keys(b).length && keys.every((key) => a[key] === b[key]);
860
+ };
861
+ var DroppableCell = React6.memo(
862
+ DroppableCellImpl,
863
+ (prev, next) => prev.id === next.id && prev.date.getTime() === next.date.getTime() && prev.resourceId === next.resourceId && prev.children === next.children && prev.className === next.className && prev.onClick === next.onClick && prev.onSlotClick === next.onSlotClick && shallowEqualStyle(prev.style, next.style)
864
+ );
456
865
 
457
866
  // src/views/MonthView.tsx
458
- var EventItem = React15__default.memo(({ event, onEventClick }) => /* @__PURE__ */ React15__default.createElement(DraggableEvent, { event }, /* @__PURE__ */ React15__default.createElement(
867
+ var EventItem = React7.memo(({ event, onEventClick }) => /* @__PURE__ */ React7.createElement(DraggableEvent, { event }, /* @__PURE__ */ React7.createElement(
459
868
  "div",
460
869
  {
461
870
  className: cn(
@@ -473,7 +882,7 @@ var EventItem = React15__default.memo(({ event, onEventClick }) => /* @__PURE__
473
882
  onEventClick?.(event);
474
883
  }
475
884
  },
476
- /* @__PURE__ */ React15__default.createElement("span", { className: "font-medium" }, event.title)
885
+ /* @__PURE__ */ React7.createElement("span", { className: "font-medium" }, event.title)
477
886
  )));
478
887
  EventItem.displayName = "EventItem";
479
888
  var MonthView = ({
@@ -484,44 +893,24 @@ var MonthView = ({
484
893
  timezone,
485
894
  locale
486
895
  }) => {
487
- const weekStartsOn = locale?.options?.weekStartsOn ?? 1;
488
- const days = useMemo(
489
- () => getMonthGrid(currentDate, weekStartsOn),
490
- [currentDate, weekStartsOn]
491
- );
492
- const weekDays = useMemo(() => {
493
- const start = startOfWeek(currentDate, { weekStartsOn });
494
- const end = endOfWeek(currentDate, { weekStartsOn });
495
- return eachDayOfInterval({ start, end });
496
- }, [currentDate, weekStartsOn]);
497
- const getZonedDate = useCallback((date) => {
498
- return timezone ? toZonedTime(date, timezone) : date;
499
- }, [timezone]);
500
- const eventsByDay = useMemo(() => {
501
- const map = /* @__PURE__ */ new Map();
502
- events.forEach((event) => {
503
- const zonedStart = getZonedDate(event.start);
504
- const key = format(zonedStart, "yyyy-MM-dd");
505
- if (!map.has(key)) {
506
- map.set(key, []);
507
- }
508
- map.get(key).push(event);
509
- });
510
- return map;
511
- }, [events, getZonedDate]);
512
- return /* @__PURE__ */ React15__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__ */ React15__default.createElement("div", { className: "overflow-y-auto flex-1 relative" }, /* @__PURE__ */ React15__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__ */ React15__default.createElement(
896
+ const weekStartsOn = resolveWeekStartsOn(locale, 1);
897
+ const days = useMemo(() => getMonthGrid(currentDate, weekStartsOn), [currentDate, weekStartsOn]);
898
+ const weekDays = useMemo(() => getWeekDays(currentDate, weekStartsOn), [currentDate, weekStartsOn]);
899
+ const eventsByDay = eventsByStartDay(events, timezone);
900
+ const today = displayToday(timezone);
901
+ return /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] scrollbar-hide border-border/50 rounded-2xl overflow-hidden min-w-[800px] md:min-w-0 shadow-sm" }, /* @__PURE__ */ React7.createElement("div", { className: "overflow-y-auto flex-1 relative" }, /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 border-b-[0.5px] border-border/50 bg-gradient-to-r from-muted/30 via-muted/40 to-muted/30 sticky top-0 z-20 backdrop-blur-sm" }, weekDays.map((day) => /* @__PURE__ */ React7.createElement(
513
902
  "div",
514
903
  {
515
904
  key: day.toISOString(),
516
905
  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"
517
906
  },
518
- format(day, "EEE", { locale })
519
- ))), /* @__PURE__ */ React15__default.createElement("div", { className: "grid grid-cols-7", style: { gridAutoRows: "130px" } }, days.map((day) => {
520
- const dayKey = format(day, "yyyy-MM-dd");
521
- const dayEvents = eventsByDay.get(dayKey) || [];
522
- const isCurrentMonth = isSameMonth(day, currentDate);
907
+ format7(day, "EEE", { locale })
908
+ ))), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7", style: { gridAutoRows: "130px" } }, days.map((day) => {
909
+ const dayKey2 = format7(day, "yyyy-MM-dd");
910
+ const dayEvents = eventsByDay.get(dayKey2) || [];
911
+ const isCurrentMonth = isSameMonth2(day, currentDate);
523
912
  const cellId = day.toISOString();
524
- return /* @__PURE__ */ React15__default.createElement(
913
+ return /* @__PURE__ */ React7.createElement(
525
914
  DroppableCell,
526
915
  {
527
916
  key: cellId,
@@ -530,18 +919,87 @@ var MonthView = ({
530
919
  className: cn(
531
920
  "h-[130px] p-2 border-b-[0.5px] border-r-[0.5px] border-border/30 last:border-r-0 relative transition-all duration-200 hover:bg-accent/5 flex flex-col gap-1.5 overflow-hidden group",
532
921
  !isCurrentMonth && "bg-muted/5 text-muted-foreground/60",
533
- isToday(day) && "bg-primary/5 ring-1 ring-inset ring-primary/20"
922
+ isSameDay3(day, today) && "bg-primary/5 ring-1 ring-inset ring-primary/20"
534
923
  ),
535
924
  onClick: () => onDateClick?.(day)
536
925
  },
537
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React15__default.createElement("div", { className: cn(
926
+ /* @__PURE__ */ React7.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React7.createElement("div", { className: cn(
538
927
  "text-sm font-semibold w-7 h-7 flex items-center justify-center rounded-full transition-all duration-200",
539
- isToday(day) ? "bg-primary text-primary-foreground shadow-md shadow-primary/30" : "group-hover:bg-accent"
540
- ) }, format(day, "d", { locale })), dayEvents.length > 0 && /* @__PURE__ */ React15__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)),
541
- /* @__PURE__ */ React15__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__ */ React15__default.createElement(EventItem, { key: `${event.id}-${dayKey}`, event, onEventClick })), dayEvents.length > 4 && /* @__PURE__ */ React15__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"))
928
+ isSameDay3(day, today) ? "bg-primary text-primary-foreground shadow-md shadow-primary/30" : "group-hover:bg-accent"
929
+ ) }, format7(day, "d", { locale })), dayEvents.length > 0 && /* @__PURE__ */ React7.createElement("div", { className: "text-[10px] font-medium text-muted-foreground/60 bg-muted/50 px-1.5 py-0.5 rounded-full" }, dayEvents.length)),
930
+ /* @__PURE__ */ React7.createElement("div", { className: "flex-1 flex flex-col gap-1 scrollbar-hide overflow-y-auto overflow-x-hidden" }, dayEvents.slice(0, 4).map((event) => /* @__PURE__ */ React7.createElement(EventItem, { key: `${event.id}-${dayKey2}`, event, onEventClick })), dayEvents.length > 4 && /* @__PURE__ */ React7.createElement("div", { className: "text-[10px] text-primary font-semibold text-center py-1 px-2 rounded-md bg-primary/5 hover:bg-primary/10 cursor-pointer transition-colors" }, "+", dayEvents.length - 4, " more"))
542
931
  );
543
932
  }))));
544
933
  };
934
+
935
+ // src/views/WeekView.tsx
936
+ import React9 from "react";
937
+ import { addDays as addDays2, format as format8, differenceInMinutes, isSameDay as isSameDay4 } from "date-fns";
938
+
939
+ // src/core/layout.ts
940
+ var layoutCache = /* @__PURE__ */ new WeakMap();
941
+ function layoutDayEvents(segments) {
942
+ const cached = layoutCache.get(segments);
943
+ if (cached) return cached;
944
+ const sorted = [...segments].sort(
945
+ (a, b) => a.start.getTime() - b.start.getTime() || b.end.getTime() - a.end.getTime() || (a.event.id < b.event.id ? -1 : a.event.id > b.event.id ? 1 : 0)
946
+ );
947
+ const result = [];
948
+ let cluster = [];
949
+ let columnEnds = [];
950
+ let clusterEnd = -Infinity;
951
+ const closeCluster = () => {
952
+ for (const placed of cluster) placed.columns = columnEnds.length;
953
+ cluster = [];
954
+ columnEnds = [];
955
+ };
956
+ for (const segment of sorted) {
957
+ const start = segment.start.getTime();
958
+ const end = Math.max(segment.end.getTime(), start + 1);
959
+ if (start >= clusterEnd) closeCluster();
960
+ let column = columnEnds.findIndex((columnEnd) => columnEnd <= start);
961
+ if (column === -1) {
962
+ column = columnEnds.length;
963
+ columnEnds.push(end);
964
+ } else {
965
+ columnEnds[column] = end;
966
+ }
967
+ const placed = { ...segment, column, columns: 1 };
968
+ cluster.push(placed);
969
+ result.push(placed);
970
+ clusterEnd = Math.max(clusterEnd, end);
971
+ }
972
+ closeCluster();
973
+ layoutCache.set(segments, result);
974
+ return result;
975
+ }
976
+
977
+ // src/components/dnd/ResizableEvent.tsx
978
+ import React8, { useState as useState2, useRef, useCallback } from "react";
979
+
980
+ // src/core/dnd.ts
981
+ function computeDrop({ event, overDate, overResourceId, grabOffsetMs = 0, view, tz }) {
982
+ let wallStart;
983
+ if (view === "month") {
984
+ const original = toDisplay(event.start, tz);
985
+ wallStart = new Date(overDate);
986
+ wallStart.setHours(original.getHours(), original.getMinutes(), original.getSeconds(), original.getMilliseconds());
987
+ } else {
988
+ wallStart = new Date(overDate.getTime() - grabOffsetMs);
989
+ wallStart.setSeconds(0, 0);
990
+ }
991
+ const start = fromDisplay(wallStart, tz);
992
+ const end = new Date(start.getTime() + (event.end.getTime() - event.start.getTime()));
993
+ const resourceId = overResourceId ?? event.resourceId;
994
+ if (start.getTime() === event.start.getTime() && resourceId === event.resourceId) return null;
995
+ return { start, end, resourceId };
996
+ }
997
+ function computeResizeEnd(event, deltaMinutes, minDuration = 15) {
998
+ const minEnd = event.start.getTime() + minDuration * 6e4;
999
+ return new Date(Math.max(event.end.getTime() + deltaMinutes * 6e4, minEnd));
1000
+ }
1001
+
1002
+ // src/components/dnd/ResizableEvent.tsx
545
1003
  var ResizableEvent = ({
546
1004
  event,
547
1005
  hourHeight,
@@ -553,8 +1011,8 @@ var ResizableEvent = ({
553
1011
  readonly
554
1012
  }) => {
555
1013
  const resizeLocked = readonly || isEventResizeDisabled(event);
556
- const [isResizing, setIsResizing] = useState(false);
557
- const [resizeHeight, setResizeHeight] = useState(null);
1014
+ const [isResizing, setIsResizing] = useState2(false);
1015
+ const [resizeHeight, setResizeHeight] = useState2(null);
558
1016
  const containerRef = useRef(null);
559
1017
  const startYRef = useRef(0);
560
1018
  const startHeightRef = useRef(0);
@@ -583,14 +1041,8 @@ var ResizableEvent = ({
583
1041
  setIsResizing(false);
584
1042
  const finalHeight = resizeHeightRef.current;
585
1043
  if (finalHeight !== null && containerRef.current && onResize) {
586
- const originalHeight = startHeightRef.current;
587
- const heightDiff = finalHeight - originalHeight;
588
- const minutesDiff = heightDiff / hourHeight * 60;
589
- const newEnd = new Date(event.end);
590
- newEnd.setMinutes(newEnd.getMinutes() + minutesDiff);
591
- if (newEnd > event.start) {
592
- onResize(event, newEnd);
593
- }
1044
+ const minutesDiff = (finalHeight - startHeightRef.current) / hourHeight * 60;
1045
+ onResize(event, computeResizeEnd(event, minutesDiff, minDuration));
594
1046
  }
595
1047
  resizeHeightRef.current = null;
596
1048
  setResizeHeight(null);
@@ -607,7 +1059,7 @@ var ResizableEvent = ({
607
1059
  const handlePointerDown = useCallback((e) => {
608
1060
  e.stopPropagation();
609
1061
  }, []);
610
- return /* @__PURE__ */ React15__default.createElement(
1062
+ return /* @__PURE__ */ React8.createElement(
611
1063
  "div",
612
1064
  {
613
1065
  ref: containerRef,
@@ -618,7 +1070,7 @@ var ResizableEvent = ({
618
1070
  }
619
1071
  },
620
1072
  children,
621
- /* @__PURE__ */ React15__default.createElement(
1073
+ /* @__PURE__ */ React8.createElement(
622
1074
  "div",
623
1075
  {
624
1076
  className: cn(
@@ -631,17 +1083,26 @@ var ResizableEvent = ({
631
1083
  onMouseDown: resizeLocked ? void 0 : handleResizeStart,
632
1084
  onTouchStart: resizeLocked ? void 0 : handleResizeStart
633
1085
  },
634
- /* @__PURE__ */ React15__default.createElement("div", { className: cn(
1086
+ /* @__PURE__ */ React8.createElement("div", { className: cn(
635
1087
  "w-8 h-1 rounded-full transition-all",
636
1088
  isResizing ? "bg-primary" : "bg-muted-foreground/30 group-hover:bg-primary/50"
637
1089
  ) })
638
1090
  ),
639
- isResizing && /* @__PURE__ */ React15__default.createElement("div", { className: "absolute inset-0 border-2 border-primary border-dashed rounded-md pointer-events-none bg-primary/5" })
1091
+ isResizing && /* @__PURE__ */ React8.createElement("div", { className: "absolute inset-0 border-2 border-primary border-dashed rounded-md pointer-events-none bg-primary/5" })
640
1092
  );
641
1093
  };
642
1094
 
643
1095
  // src/views/WeekView.tsx
644
- var WeekView = ({
1096
+ var HOUR_HEIGHT = 60;
1097
+ var HOURS = Array.from({ length: 24 }, (_, i) => i);
1098
+ var QUARTERS = [0, 15, 30, 45];
1099
+ var NO_SEGMENTS = [];
1100
+ var slotDate = (day, hour, minute) => {
1101
+ const date = new Date(day);
1102
+ date.setHours(hour, minute, 0, 0);
1103
+ return date;
1104
+ };
1105
+ var WeekViewImpl = ({
645
1106
  currentDate,
646
1107
  events,
647
1108
  onEventClick,
@@ -651,151 +1112,110 @@ var WeekView = ({
651
1112
  locale,
652
1113
  readonly
653
1114
  }) => {
654
- const weekStartsOn = locale?.options?.weekStartsOn ?? 1;
655
- const start = startOfWeek(currentDate, { weekStartsOn });
656
- const end = endOfWeek(currentDate, { weekStartsOn });
657
- const weekDays = eachDayOfInterval({ start, end });
658
- const hours = Array.from({ length: 24 }, (_, i) => i);
659
- const hourHeight = 60;
660
- const scrollContainerRef = React15__default.useRef(null);
661
- const [now, setNow] = React15__default.useState(/* @__PURE__ */ new Date());
662
- React15__default.useEffect(() => {
1115
+ const weekDays = React9.useMemo(
1116
+ () => getWeekDays(currentDate, resolveWeekStartsOn(locale, 1)),
1117
+ [currentDate, locale]
1118
+ );
1119
+ const visibleRange = React9.useMemo(
1120
+ () => ({ start: weekDays[0], end: addDays2(weekDays[weekDays.length - 1], 1) }),
1121
+ [weekDays]
1122
+ );
1123
+ const scrollContainerRef = React9.useRef(null);
1124
+ const [now, setNow] = React9.useState(() => /* @__PURE__ */ new Date());
1125
+ React9.useEffect(() => {
663
1126
  const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
664
1127
  return () => clearInterval(interval);
665
1128
  }, []);
666
- React15__default.useEffect(() => {
1129
+ React9.useEffect(() => {
667
1130
  if (scrollContainerRef.current) {
668
- const scrollToActualTime = () => {
669
- const currentHour = now.getHours();
670
- const offsetHour = 4;
671
- return (currentHour - offsetHour) * hourHeight;
672
- };
673
- scrollContainerRef.current.scrollTop = scrollToActualTime();
674
- }
675
- }, []);
676
- const getZonedDate = (date) => {
677
- return timezone ? toZonedTime(date, timezone) : date;
678
- };
679
- const zonedNow = getZonedDate(/* @__PURE__ */ new Date());
680
- const getTimezoneDisplay = (tz) => {
681
- const date = now;
682
- let displayTime = "";
683
- let acronym = "";
684
- if (!tz) {
685
- displayTime = format(date, "HH:mm");
686
- try {
687
- acronym = new Intl.DateTimeFormat("en-US", { timeZoneName: "short" }).formatToParts(date).find((part) => part.type === "timeZoneName")?.value || "";
688
- } catch (e) {
689
- acronym = "LOC";
690
- }
691
- } else {
692
- try {
693
- const zDate = toZonedTime(date, tz);
694
- displayTime = format(zDate, "HH:mm");
695
- acronym = new Intl.DateTimeFormat("en-US", { timeZone: tz, timeZoneName: "short" }).formatToParts(date).find((part) => part.type === "timeZoneName")?.value || "";
696
- } catch (e) {
697
- displayTime = format(date, "HH:mm");
698
- acronym = tz;
699
- }
1131
+ const offsetHour = 4;
1132
+ scrollContainerRef.current.scrollTop = (toDisplay(/* @__PURE__ */ new Date(), timezone).getHours() - offsetHour) * HOUR_HEIGHT;
700
1133
  }
701
- return /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col items-center justify-center leading-tight" }, /* @__PURE__ */ React15__default.createElement("span", null, displayTime), /* @__PURE__ */ React15__default.createElement("span", { className: "text-[10px] opacity-75" }, "(", acronym, ")"));
702
- };
703
- const is24h = uses24HourClock(locale);
704
- const timeFormat = is24h ? "H:mm" : "h a";
705
- const eventTimeFormat = is24h ? "H:mm" : "h:mm a";
706
- const nowFormat = is24h ? "H:mm" : "h:mm";
707
- return /* @__PURE__ */ React15__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__ */ React15__default.createElement(
1134
+ }, [timezone]);
1135
+ const segmentsByDay = segmentsByDisplayDay(events, timezone, visibleRange);
1136
+ const today = displayToday(timezone, now);
1137
+ const zonedNow = toDisplay(now, timezone);
1138
+ const nowTop = minutesSinceDisplayMidnight(now, timezone) / 60 * HOUR_HEIGHT;
1139
+ const showsToday = weekDays.some((day) => isSameDay4(day, today));
1140
+ const zone = resolveTimeZone(timezone);
1141
+ const zoneLabel = timeZoneAbbreviation(now, zone) || zone || "LOC";
1142
+ const formats = timeFormats(locale);
1143
+ return /* @__PURE__ */ React9.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden min-w-[800px] md:min-w-0 shadow-sm" }, /* @__PURE__ */ React9.createElement(
708
1144
  "div",
709
1145
  {
710
1146
  ref: scrollContainerRef,
711
1147
  className: "flex-1 overflow-y-auto scrollbar-hide relative bg-background scroll-smooth"
712
1148
  },
713
- /* @__PURE__ */ React15__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__ */ React15__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" }, getTimezoneDisplay(timezone)), /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 grid grid-cols-7" }, weekDays.map((day, index) => /* @__PURE__ */ React15__default.createElement("div", { key: day.toISOString(), className: cn("py-3 px-2 text-center", index > 0 && "border-l-[0.5px] border-border/30") }, /* @__PURE__ */ React15__default.createElement("div", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1.5" }, format(day, "EEE", { locale })), /* @__PURE__ */ React15__default.createElement("div", { className: cn(
1149
+ /* @__PURE__ */ React9.createElement("div", { className: "flex border-b-[0.5px] border-border/50 bg-gradient-to-r from-muted/20 via-background to-muted/20 z-20 sticky top-0 backdrop-blur-sm" }, /* @__PURE__ */ React9.createElement("div", { className: "flex-none p-3 text-center text-xs font-semibold text-muted-foreground w-16 flex items-center justify-center border-r-[0.5px] border-border/30 bg-muted/10" }, /* @__PURE__ */ React9.createElement("div", { className: "flex flex-col items-center justify-center leading-tight" }, /* @__PURE__ */ React9.createElement("span", null, format8(zonedNow, "HH:mm")), /* @__PURE__ */ React9.createElement("span", { className: "text-[10px] opacity-75" }, "(", zoneLabel, ")"))), /* @__PURE__ */ React9.createElement("div", { className: "flex-1 grid grid-cols-7" }, weekDays.map((day, index) => /* @__PURE__ */ React9.createElement("div", { key: day.toISOString(), className: cn("py-3 px-2 text-center", index > 0 && "border-l-[0.5px] border-border/30") }, /* @__PURE__ */ React9.createElement("div", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1.5" }, format8(day, "EEE", { locale })), /* @__PURE__ */ React9.createElement("div", { className: cn(
714
1150
  "w-9 h-9 flex items-center justify-center rounded-xl mx-auto text-sm font-semibold transition-all duration-200",
715
- isToday(day) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30 scale-110" : "text-foreground hover:bg-accent/80"
716
- ) }, format(day, "d", { locale })))))),
717
- /* @__PURE__ */ React15__default.createElement(
1151
+ isSameDay4(day, today) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30 scale-110" : "text-foreground hover:bg-accent/80"
1152
+ ) }, format8(day, "d", { locale })))))),
1153
+ /* @__PURE__ */ React9.createElement(
718
1154
  "div",
719
1155
  {
720
1156
  className: "flex min-w-full relative",
721
- style: { height: hours.length * hourHeight }
1157
+ style: { height: HOURS.length * HOUR_HEIGHT }
722
1158
  },
723
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex-none w-16 border-r-[0.5px] border-border/30 relative bg-muted/5" }, hours.map((hour) => /* @__PURE__ */ React15__default.createElement(
1159
+ /* @__PURE__ */ React9.createElement("div", { className: "flex-none w-16 border-r-[0.5px] border-border/30 relative bg-muted/5" }, HOURS.map((hour) => /* @__PURE__ */ React9.createElement(
724
1160
  "div",
725
1161
  {
726
1162
  key: hour,
727
1163
  className: "relative w-full text-[11px] text-muted-foreground/80 text-right pr-3 font-medium tabular-nums box-border",
728
- style: { height: hourHeight }
1164
+ style: { height: HOUR_HEIGHT }
729
1165
  },
730
- /* @__PURE__ */ React15__default.createElement("span", { className: "block -translate-y-1/2" }, hour !== 0 && format((/* @__PURE__ */ new Date()).setHours(hour, 0, 0, 0), timeFormat, { locale }))
731
- ))),
732
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, weekDays.map((day, dayIndex) => {
733
- const dayEvents = events.filter((e) => {
734
- const zonedStart = getZonedDate(e.start);
735
- return isSameDay(zonedStart, day);
736
- });
737
- return /* @__PURE__ */ React15__default.createElement("div", { key: day.toISOString(), className: cn("relative h-full", dayIndex > 0 && "border-l-[0.5px] border-border/30") }, hours.map((hour) => {
738
- return /* @__PURE__ */ React15__default.createElement(
739
- "div",
740
- {
741
- key: hour,
742
- className: "w-full border-b-[0.5px] border-dashed border-border/20 box-border relative hover:bg-accent/5 transition-colors",
743
- style: { height: hourHeight }
744
- },
745
- [0, 15, 30, 45].map((minute) => {
746
- const cellDate = new Date(day);
747
- cellDate.setHours(hour, minute, 0, 0);
748
- const cellId = cellDate.toISOString();
749
- return /* @__PURE__ */ React15__default.createElement(
750
- DroppableCell,
751
- {
752
- key: minute,
753
- id: cellId,
754
- date: cellDate,
755
- className: "w-full absolute left-0 right-0 z-0 transition-colors",
756
- style: {
757
- height: "25%",
758
- top: `${minute / 60 * 100}%`
759
- }
1166
+ /* @__PURE__ */ React9.createElement("span", { className: "block -translate-y-1/2" }, hour !== 0 && format8(slotDate(currentDate, hour, 0), formats.hour, { locale }))
1167
+ )), showsToday && /* @__PURE__ */ React9.createElement(
1168
+ "div",
1169
+ {
1170
+ className: "absolute left-0 w-full pointer-events-none z-30 flex justify-end pr-2",
1171
+ style: { top: `${nowTop}px` }
1172
+ },
1173
+ /* @__PURE__ */ React9.createElement("span", { className: "text-[10px] font-bold text-primary-foreground bg-primary px-1.5 py-0.5 rounded-md shadow-md -translate-y-1/2 backdrop-blur-none" }, format8(zonedNow, formats.compact, { locale }))
1174
+ )),
1175
+ /* @__PURE__ */ React9.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, weekDays.map((day, dayIndex) => {
1176
+ const dayKey2 = format8(day, "yyyy-MM-dd");
1177
+ const positioned = layoutDayEvents(segmentsByDay.get(dayKey2) ?? NO_SEGMENTS);
1178
+ return /* @__PURE__ */ React9.createElement("div", { key: dayKey2, className: cn("relative h-full", dayIndex > 0 && "border-l-[0.5px] border-border/30") }, HOURS.map((hour) => /* @__PURE__ */ React9.createElement(
1179
+ "div",
1180
+ {
1181
+ key: hour,
1182
+ className: "w-full border-b-[0.5px] border-dashed border-border/20 box-border relative hover:bg-accent/5 transition-colors",
1183
+ style: { height: HOUR_HEIGHT }
1184
+ },
1185
+ QUARTERS.map((minute) => {
1186
+ const cellDate = slotDate(day, hour, minute);
1187
+ return /* @__PURE__ */ React9.createElement(
1188
+ DroppableCell,
1189
+ {
1190
+ key: minute,
1191
+ id: cellDate.toISOString(),
1192
+ date: cellDate,
1193
+ className: "w-full absolute left-0 right-0 z-0 transition-colors",
1194
+ style: {
1195
+ height: "25%",
1196
+ top: `${minute / 60 * 100}%`
760
1197
  },
761
- /* @__PURE__ */ React15__default.createElement(
762
- "div",
763
- {
764
- className: "w-full h-full bg-transparent cursor-pointer",
765
- onClick: () => onTimeSlotClick?.(cellDate)
766
- }
767
- )
768
- );
769
- })
770
- );
771
- }), dayEvents.map((event) => {
772
- const overlappingEvents = dayEvents.filter((e) => {
773
- if (e.id === event.id) return false;
774
- const s1 = getZonedDate(event.start).getTime();
775
- const e1 = getZonedDate(event.end).getTime();
776
- const s2 = getZonedDate(e.start).getTime();
777
- const e2 = getZonedDate(e.end).getTime();
778
- return s1 < e2 && e1 > s2;
779
- });
780
- const group = [event, ...overlappingEvents].sort(
781
- (a, b) => getZonedDate(a.start).getTime() - getZonedDate(b.start).getTime() || (a.id > b.id ? 1 : -1)
782
- // stable sort
783
- );
784
- const index = group.findIndex((e) => e.id === event.id);
785
- const count = group.length;
786
- const widthPercent = 100 / count;
787
- const leftPercent = index * widthPercent;
788
- const zonedEventStart = getZonedDate(event.start);
789
- const zonedEventEnd = getZonedDate(event.end);
790
- const startMinutes = zonedEventStart.getHours() * 60 + zonedEventStart.getMinutes();
791
- const durationMinutes = differenceInMinutes(zonedEventEnd, zonedEventStart);
792
- const top = startMinutes / 60 * hourHeight;
793
- const height = durationMinutes / 60 * hourHeight;
1198
+ onSlotClick: onTimeSlotClick
1199
+ }
1200
+ );
1201
+ })
1202
+ )), positioned.map(({ event, start, end, column, columns }) => {
1203
+ const widthPercent = 100 / columns;
1204
+ const leftPercent = column * widthPercent;
1205
+ const zonedEventStart = toDisplay(event.start, timezone);
1206
+ const zonedEventEnd = toDisplay(event.end, timezone);
1207
+ const startMinutes = start.getHours() * 60 + start.getMinutes();
1208
+ const durationMinutes = differenceInMinutes(end, start);
1209
+ const top = startMinutes / 60 * HOUR_HEIGHT;
1210
+ const height = durationMinutes / 60 * HOUR_HEIGHT;
794
1211
  const isShortEvent = durationMinutes < 60;
795
- return /* @__PURE__ */ React15__default.createElement(
1212
+ const isLastSegment = end.getTime() === zonedEventEnd.getTime();
1213
+ return /* @__PURE__ */ React9.createElement(
796
1214
  DraggableEvent,
797
1215
  {
798
- key: `${event.id}-${day.toISOString()}`,
1216
+ key: `${event.id}-${dayKey2}`,
1217
+ dragId: `${event.id}@${dayKey2}`,
1218
+ grabOffsetMs: start.getTime() - zonedEventStart.getTime(),
799
1219
  event,
800
1220
  className: `absolute z-10 transition-all ${readonly ? "cursor-default" : ""}`,
801
1221
  style: {
@@ -804,20 +1224,20 @@ var WeekView = ({
804
1224
  left: `${leftPercent}%`,
805
1225
  width: `${widthPercent}%`,
806
1226
  // Add minimal spacing between overlapping events
807
- paddingRight: count > 1 ? "2px" : "0"
1227
+ paddingRight: columns > 1 ? "2px" : "0"
808
1228
  }
809
1229
  },
810
- /* @__PURE__ */ React15__default.createElement(
1230
+ /* @__PURE__ */ React9.createElement(
811
1231
  ResizableEvent,
812
1232
  {
813
- readonly,
1233
+ readonly: readonly || !isLastSegment,
814
1234
  event,
815
- hourHeight,
1235
+ hourHeight: HOUR_HEIGHT,
816
1236
  onResize: onEventResize,
817
1237
  className: "h-full",
818
1238
  style: { height: "100%" }
819
1239
  },
820
- /* @__PURE__ */ React15__default.createElement(
1240
+ /* @__PURE__ */ React9.createElement(
821
1241
  "div",
822
1242
  {
823
1243
  className: cn(
@@ -827,7 +1247,7 @@ var WeekView = ({
827
1247
  !event.color && "border-primary/20 bg-primary/10",
828
1248
  isShortEvent ? "px-1 flex items-center justify-center" : "p-2",
829
1249
  // Add active border for overlapped events to distinguish them
830
- count > 1 && "border-l-4 border-l-primary/50"
1250
+ columns > 1 && "border-l-4 border-l-primary/50"
831
1251
  ),
832
1252
  style: {
833
1253
  height: "100%",
@@ -840,41 +1260,43 @@ var WeekView = ({
840
1260
  e.stopPropagation();
841
1261
  onEventClick?.(event);
842
1262
  },
843
- title: count > 1 ? `${event.title} (${index + 1}/${count})` : void 0
1263
+ title: columns > 1 ? `${event.title} (${column + 1}/${columns})` : void 0
844
1264
  },
845
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ React15__default.createElement("div", { className: cn(
1265
+ /* @__PURE__ */ React9.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ React9.createElement("div", { className: cn(
846
1266
  "font-semibold truncate text-foreground/90 leading-tight",
847
1267
  isShortEvent ? "text-xs text-center" : "text-xs"
848
- ) }, event.title), !isShortEvent && /* @__PURE__ */ React15__default.createElement(React15__default.Fragment, null, /* @__PURE__ */ React15__default.createElement("div", { className: "text-[10px] text-muted-foreground truncate mt-0.5 font-medium leading-tight" }, format(zonedEventStart, eventTimeFormat, { locale }), " - ", format(zonedEventEnd, eventTimeFormat, { locale })), event.description && height > 50 && /* @__PURE__ */ React15__default.createElement("div", { className: "text-[10px] text-muted-foreground/80 truncate mt-1 leading-tight opacity-80" }, event.description)), count > 1 && !isShortEvent && /* @__PURE__ */ React15__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" }, count))
1268
+ ) }, event.title), !isShortEvent && /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement("div", { className: "text-[10px] text-muted-foreground truncate mt-0.5 font-medium leading-tight" }, format8(zonedEventStart, formats.time, { locale }), " - ", format8(zonedEventEnd, formats.time, { locale })), event.description && height > 50 && /* @__PURE__ */ React9.createElement("div", { className: "text-[10px] text-muted-foreground/80 truncate mt-1 leading-tight opacity-80" }, event.description)), columns > 1 && !isShortEvent && /* @__PURE__ */ React9.createElement("div", { className: "absolute top-1 right-1 bg-background/80 backdrop-blur-sm rounded-full w-4 h-4 flex items-center justify-center text-[9px] font-bold text-muted-foreground border border-border shadow-sm" }, columns))
849
1269
  )
850
1270
  )
851
1271
  );
852
- }), isToday(day) && /* @__PURE__ */ React15__default.createElement(
1272
+ }), isSameDay4(day, today) && /* @__PURE__ */ React9.createElement(
853
1273
  "div",
854
1274
  {
855
1275
  className: "absolute left-0 right-0 z-20 pointer-events-none flex items-center",
856
- style: {
857
- top: `${(zonedNow.getHours() * 60 + zonedNow.getMinutes()) / 60 * hourHeight}px`
858
- }
1276
+ style: { top: `${nowTop}px` }
859
1277
  },
860
- /* @__PURE__ */ React15__default.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
861
- /* @__PURE__ */ React15__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" })
1278
+ /* @__PURE__ */ React9.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
1279
+ /* @__PURE__ */ React9.createElement("div", { className: "absolute -left-1.5 w-3 h-3 bg-primary rounded-full shadow-lg shadow-primary/40 ring-2 ring-background animate-pulse" })
862
1280
  ));
863
1281
  }))
864
- ),
865
- /* @__PURE__ */ React15__default.createElement(
866
- "div",
867
- {
868
- className: "absolute left-0 w-16 pointer-events-none z-30 flex justify-end pr-2",
869
- style: {
870
- top: `${(zonedNow.getHours() * 60 + zonedNow.getMinutes()) / 60 * hourHeight + 80}px`
871
- }
872
- },
873
- /* @__PURE__ */ React15__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" }, format(zonedNow, nowFormat, { locale }))
874
1282
  )
875
1283
  ));
876
1284
  };
877
- var DayView = ({
1285
+ var WeekView = React9.memo(WeekViewImpl);
1286
+
1287
+ // src/views/DayView.tsx
1288
+ import React10 from "react";
1289
+ import { addDays as addDays3, format as format9, differenceInMinutes as differenceInMinutes2, isSameDay as isSameDay5, startOfDay as startOfDay3 } from "date-fns";
1290
+ var HOUR_HEIGHT2 = 80;
1291
+ var HOURS2 = Array.from({ length: 24 }, (_, i) => i);
1292
+ var QUARTERS2 = [0, 15, 30, 45];
1293
+ var NO_SEGMENTS2 = [];
1294
+ var slotDate2 = (day, hour, minute) => {
1295
+ const date = new Date(day);
1296
+ date.setHours(hour, minute, 0, 0);
1297
+ return date;
1298
+ };
1299
+ var DayViewImpl = ({
878
1300
  currentDate,
879
1301
  events,
880
1302
  onEventClick,
@@ -884,114 +1306,84 @@ var DayView = ({
884
1306
  locale,
885
1307
  readonly
886
1308
  }) => {
887
- const hours = Array.from({ length: 24 }, (_, i) => i);
888
- const hourHeight = 80;
889
- const scrollContainerRef = React15__default.useRef(null);
890
- const [now, setNow] = React15__default.useState(/* @__PURE__ */ new Date());
891
- React15__default.useEffect(() => {
1309
+ const visibleRange = React10.useMemo(() => {
1310
+ const start = startOfDay3(currentDate);
1311
+ return { start, end: addDays3(start, 1) };
1312
+ }, [currentDate]);
1313
+ const scrollContainerRef = React10.useRef(null);
1314
+ const [now, setNow] = React10.useState(() => /* @__PURE__ */ new Date());
1315
+ React10.useEffect(() => {
892
1316
  const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
893
1317
  return () => clearInterval(interval);
894
1318
  }, []);
895
- React15__default.useEffect(() => {
1319
+ React10.useEffect(() => {
896
1320
  if (scrollContainerRef.current) {
897
- const scrollToActualTime = () => {
898
- const currentHour = now.getHours();
899
- const offsetHour = 3;
900
- return (currentHour - offsetHour) * hourHeight;
901
- };
902
- scrollContainerRef.current.scrollTop = scrollToActualTime();
1321
+ const offsetHour = 3;
1322
+ scrollContainerRef.current.scrollTop = (toDisplay(/* @__PURE__ */ new Date(), timezone).getHours() - offsetHour) * HOUR_HEIGHT2;
903
1323
  }
904
- }, []);
905
- const getZonedDate = (date) => {
906
- return timezone ? toZonedTime(date, timezone) : date;
907
- };
908
- const zonedNow = getZonedDate(now);
909
- const dayEvents = events.filter((e) => {
910
- const zonedStart = getZonedDate(e.start);
911
- return isSameDay(zonedStart, currentDate);
912
- });
913
- const is24h = uses24HourClock(locale);
914
- const timeFormat = is24h ? "H:mm" : "h a";
915
- const eventTimeFormat = is24h ? "H:mm" : "h:mm a";
916
- const nowFormat = is24h ? "H:mm" : "h:mm a";
917
- return /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden shadow-sm" }, /* @__PURE__ */ React15__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__ */ React15__default.createElement("div", { className: "flex items-center justify-center gap-3" }, /* @__PURE__ */ React15__default.createElement("h2", { className: "text-xl font-semibold capitalize text-foreground" }, format(currentDate, "EEEE, MMMM d, yyyy", { locale })), isToday(currentDate) && /* @__PURE__ */ React15__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__ */ React15__default.createElement("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto relative" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex relative", style: { height: hours.length * hourHeight } }, /* @__PURE__ */ React15__default.createElement("div", { className: "w-20 bg-muted/5 border-r-[0.5px] border-border/30 relative" }, hours.map((hour) => /* @__PURE__ */ React15__default.createElement(
1324
+ }, [timezone]);
1325
+ const dayKey2 = format9(currentDate, "yyyy-MM-dd");
1326
+ const positioned = layoutDayEvents(segmentsByDisplayDay(events, timezone, visibleRange).get(dayKey2) ?? NO_SEGMENTS2);
1327
+ const isToday2 = isSameDay5(currentDate, displayToday(timezone, now));
1328
+ const zonedNow = toDisplay(now, timezone);
1329
+ const nowTop = minutesSinceDisplayMidnight(now, timezone) / 60 * HOUR_HEIGHT2;
1330
+ const formats = timeFormats(locale);
1331
+ return /* @__PURE__ */ React10.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden shadow-sm" }, /* @__PURE__ */ React10.createElement("div", { className: "px-6 py-4 border-b-[0.5px] border-border/50 bg-gradient-to-r from-muted/20 via-background to-muted/20 text-center shrink-0" }, /* @__PURE__ */ React10.createElement("div", { className: "flex items-center justify-center gap-3" }, /* @__PURE__ */ React10.createElement("h2", { className: "text-xl font-semibold capitalize text-foreground" }, format9(currentDate, "EEEE, MMMM d, yyyy", { locale })), isToday2 && /* @__PURE__ */ React10.createElement("span", { className: "text-xs font-semibold bg-primary text-primary-foreground px-3 py-1 rounded-full shadow-md shadow-primary/20" }, "Today"))), /* @__PURE__ */ React10.createElement("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto relative" }, /* @__PURE__ */ React10.createElement("div", { className: "flex relative", style: { height: HOURS2.length * HOUR_HEIGHT2 } }, /* @__PURE__ */ React10.createElement("div", { className: "w-20 bg-muted/5 border-r-[0.5px] border-border/30 relative" }, HOURS2.map((hour) => /* @__PURE__ */ React10.createElement(
918
1332
  "div",
919
1333
  {
920
1334
  key: hour,
921
1335
  className: "relative w-full",
922
- style: { height: hourHeight }
1336
+ style: { height: HOUR_HEIGHT2 }
923
1337
  },
924
- hour !== 0 && /* @__PURE__ */ React15__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" }, format((/* @__PURE__ */ new Date()).setHours(hour, 0, 0, 0), timeFormat, { locale }))
925
- )), isToday(currentDate) && /* @__PURE__ */ React15__default.createElement(
1338
+ hour !== 0 && /* @__PURE__ */ React10.createElement("span", { className: "absolute w-full text-center -top-3 left-1/2 -translate-x-1/2 text-[11px] text-muted-foreground/80 font-medium tabular-nums bg-background px-1.5 py-0.5 rounded-md" }, format9(slotDate2(currentDate, hour, 0), formats.hour, { locale }))
1339
+ )), isToday2 && /* @__PURE__ */ React10.createElement(
926
1340
  "div",
927
1341
  {
928
1342
  className: "absolute left-0 w-full pointer-events-none z-30 flex justify-end pr-2",
929
- style: {
930
- top: `${(zonedNow.getHours() * 60 + zonedNow.getMinutes()) / 60 * hourHeight}px`
931
- }
1343
+ style: { top: `${nowTop}px` }
932
1344
  },
933
- /* @__PURE__ */ React15__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" }, format(zonedNow, nowFormat, { locale }))
934
- )), /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 relative" }, hours.map((hour) => {
935
- return /* @__PURE__ */ React15__default.createElement(
936
- "div",
937
- {
938
- key: hour,
939
- className: "border-b-[0.5px] border-dashed border-border/20 box-border relative hover:bg-accent/5 transition-colors",
940
- style: { height: hourHeight }
941
- },
942
- [0, 15, 30, 45].map((minute) => {
943
- const cellDate = new Date(currentDate);
944
- cellDate.setHours(hour, minute, 0, 0);
945
- const cellId = cellDate.toISOString();
946
- return /* @__PURE__ */ React15__default.createElement(
947
- DroppableCell,
948
- {
949
- key: minute,
950
- id: cellId,
951
- date: cellDate,
952
- className: "w-full absolute left-0 right-0 z-0 transition-colors",
953
- style: {
954
- height: "25%",
955
- top: `${minute / 60 * 100}%`
956
- }
1345
+ /* @__PURE__ */ React10.createElement("span", { className: "text-[10px] font-bold text-white bg-primary px-2 py-1 rounded-lg shadow-md shadow-primary/30 -translate-y-1/2" }, format9(zonedNow, formats.time, { locale }))
1346
+ )), /* @__PURE__ */ React10.createElement("div", { className: "flex-1 relative" }, HOURS2.map((hour) => /* @__PURE__ */ React10.createElement(
1347
+ "div",
1348
+ {
1349
+ key: hour,
1350
+ className: "border-b-[0.5px] border-dashed border-border/20 box-border relative hover:bg-accent/5 transition-colors",
1351
+ style: { height: HOUR_HEIGHT2 }
1352
+ },
1353
+ QUARTERS2.map((minute) => {
1354
+ const cellDate = slotDate2(currentDate, hour, minute);
1355
+ return /* @__PURE__ */ React10.createElement(
1356
+ DroppableCell,
1357
+ {
1358
+ key: minute,
1359
+ id: cellDate.toISOString(),
1360
+ date: cellDate,
1361
+ className: "w-full absolute left-0 right-0 z-0 transition-colors",
1362
+ style: {
1363
+ height: "25%",
1364
+ top: `${minute / 60 * 100}%`
957
1365
  },
958
- /* @__PURE__ */ React15__default.createElement(
959
- "div",
960
- {
961
- className: "h-full w-full bg-transparent cursor-pointer",
962
- onClick: () => onTimeSlotClick?.(cellDate)
963
- }
964
- )
965
- );
966
- })
967
- );
968
- }), dayEvents.map((event) => {
969
- const overlappingEvents = dayEvents.filter((e) => {
970
- if (e.id === event.id) return false;
971
- const s1 = getZonedDate(event.start).getTime();
972
- const e1 = getZonedDate(event.end).getTime();
973
- const s2 = getZonedDate(e.start).getTime();
974
- const e2 = getZonedDate(e.end).getTime();
975
- return s1 < e2 && e1 > s2;
976
- });
977
- const group = [event, ...overlappingEvents].sort(
978
- (a, b) => getZonedDate(a.start).getTime() - getZonedDate(b.start).getTime() || (a.id > b.id ? 1 : -1)
979
- );
980
- const index = group.findIndex((e) => e.id === event.id);
981
- const count = group.length;
982
- const widthPercent = 100 / count;
983
- const leftPercent = index * widthPercent;
984
- const zonedStart = getZonedDate(event.start);
985
- const zonedEnd = getZonedDate(event.end);
986
- const startMinutes = zonedStart.getHours() * 60 + zonedStart.getMinutes();
987
- const durationMinutes = differenceInMinutes(zonedEnd, zonedStart);
988
- const top = startMinutes / 60 * hourHeight;
989
- const height = durationMinutes / 60 * hourHeight;
1366
+ onSlotClick: onTimeSlotClick
1367
+ }
1368
+ );
1369
+ })
1370
+ )), positioned.map(({ event, start, end, column, columns }) => {
1371
+ const widthPercent = 100 / columns;
1372
+ const leftPercent = column * widthPercent;
1373
+ const zonedStart = toDisplay(event.start, timezone);
1374
+ const zonedEnd = toDisplay(event.end, timezone);
1375
+ const startMinutes = start.getHours() * 60 + start.getMinutes();
1376
+ const durationMinutes = differenceInMinutes2(end, start);
1377
+ const top = startMinutes / 60 * HOUR_HEIGHT2;
1378
+ const height = durationMinutes / 60 * HOUR_HEIGHT2;
990
1379
  const isShortEvent = durationMinutes < 45;
991
- return /* @__PURE__ */ React15__default.createElement(
1380
+ const isLastSegment = end.getTime() === zonedEnd.getTime();
1381
+ return /* @__PURE__ */ React10.createElement(
992
1382
  DraggableEvent,
993
1383
  {
994
- key: `${event.id}-${currentDate.toISOString()}`,
1384
+ key: `${event.id}-${dayKey2}`,
1385
+ dragId: `${event.id}@${dayKey2}`,
1386
+ grabOffsetMs: start.getTime() - zonedStart.getTime(),
995
1387
  event,
996
1388
  className: `absolute z-10 transition-all ${readonly ? "cursor-default" : ""}`,
997
1389
  style: {
@@ -999,20 +1391,20 @@ var DayView = ({
999
1391
  height: `${Math.max(height, 28)}px`,
1000
1392
  left: `calc(${leftPercent}% + 4px)`,
1001
1393
  width: `calc(${widthPercent}% - 8px)`,
1002
- paddingRight: count > 1 ? "2px" : "0"
1394
+ paddingRight: columns > 1 ? "2px" : "0"
1003
1395
  }
1004
1396
  },
1005
- /* @__PURE__ */ React15__default.createElement(
1397
+ /* @__PURE__ */ React10.createElement(
1006
1398
  ResizableEvent,
1007
1399
  {
1008
- readonly,
1400
+ readonly: readonly || !isLastSegment,
1009
1401
  event,
1010
- hourHeight,
1402
+ hourHeight: HOUR_HEIGHT2,
1011
1403
  onResize: onEventResize,
1012
1404
  className: "h-full",
1013
1405
  style: { height: "100%" }
1014
1406
  },
1015
- /* @__PURE__ */ React15__default.createElement(
1407
+ /* @__PURE__ */ React10.createElement(
1016
1408
  "div",
1017
1409
  {
1018
1410
  className: cn(
@@ -1021,61 +1413,72 @@ var DayView = ({
1021
1413
  readonly || isEventDragDisabled(event) ? "cursor-default" : "cursor-grab active:cursor-grabbing",
1022
1414
  !event.color && "bg-primary/10 border-primary/20",
1023
1415
  isShortEvent ? "px-2 flex items-center" : "px-3 py-2",
1024
- count > 1 && "border-l-4"
1416
+ columns > 1 && "border-l-4"
1025
1417
  ),
1026
1418
  style: {
1027
1419
  backgroundColor: event.color ? `${event.color}15` : void 0,
1028
1420
  borderColor: event.color ? `${event.color}30` : void 0,
1029
1421
  borderLeftColor: event.color || "var(--primary)",
1030
- borderLeftWidth: count > 1 ? "4px" : "3px"
1422
+ borderLeftWidth: columns > 1 ? "4px" : "3px"
1031
1423
  },
1032
1424
  onClick: (e) => {
1033
1425
  e.stopPropagation();
1034
1426
  onEventClick?.(event);
1035
1427
  },
1036
- title: count > 1 ? `${event.title} (${index + 1}/${count})` : void 0
1428
+ title: columns > 1 ? `${event.title} (${column + 1}/${columns})` : void 0
1037
1429
  },
1038
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ React15__default.createElement("div", { className: cn(
1430
+ /* @__PURE__ */ React10.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ React10.createElement("div", { className: cn(
1039
1431
  "font-semibold truncate leading-tight",
1040
1432
  isShortEvent ? "text-xs" : "text-sm",
1041
1433
  event.color ? "text-foreground" : "text-foreground/90"
1042
- ) }, event.title), !isShortEvent && /* @__PURE__ */ React15__default.createElement(React15__default.Fragment, null, /* @__PURE__ */ React15__default.createElement("div", { className: "text-xs text-muted-foreground mt-0.5 font-medium" }, format(zonedStart, eventTimeFormat, { locale }), " - ", format(zonedEnd, eventTimeFormat, { locale })), event.description && height > 60 && /* @__PURE__ */ React15__default.createElement("div", { className: "text-xs text-muted-foreground/80 mt-1 line-clamp-2" }, event.description)), count > 1 && !isShortEvent && /* @__PURE__ */ React15__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" }, count))
1434
+ ) }, event.title), !isShortEvent && /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement("div", { className: "text-xs text-muted-foreground mt-0.5 font-medium" }, format9(zonedStart, formats.time, { locale }), " - ", format9(zonedEnd, formats.time, { locale })), event.description && height > 60 && /* @__PURE__ */ React10.createElement("div", { className: "text-xs text-muted-foreground/80 mt-1 line-clamp-2" }, event.description)), columns > 1 && !isShortEvent && /* @__PURE__ */ React10.createElement("div", { className: "absolute top-1.5 right-1.5 bg-background/90 backdrop-blur-sm rounded-full w-5 h-5 flex items-center justify-center text-[10px] font-bold text-muted-foreground border border-border shadow-sm" }, columns))
1043
1435
  )
1044
1436
  )
1045
1437
  );
1046
- }), isToday(currentDate) && /* @__PURE__ */ React15__default.createElement(
1438
+ }), isToday2 && /* @__PURE__ */ React10.createElement(
1047
1439
  "div",
1048
1440
  {
1049
1441
  className: "absolute left-0 right-0 z-20 pointer-events-none flex items-center",
1050
- style: {
1051
- top: `${(zonedNow.getHours() * 60 + zonedNow.getMinutes()) / 60 * hourHeight}px`
1052
- }
1442
+ style: { top: `${nowTop}px` }
1053
1443
  },
1054
- /* @__PURE__ */ React15__default.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
1055
- /* @__PURE__ */ React15__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" })
1444
+ /* @__PURE__ */ React10.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
1445
+ /* @__PURE__ */ React10.createElement("div", { className: "absolute -left-1.5 w-3 h-3 bg-primary rounded-full shadow-lg shadow-primary/40 ring-2 ring-background animate-pulse" })
1056
1446
  )))));
1057
1447
  };
1058
- var AgendaEmptyState = ({ onCreateEvent, translations }) => /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col items-center justify-center h-full min-h-[400px] py-12" }, /* @__PURE__ */ React15__default.createElement("div", { className: "relative mb-8" }, /* @__PURE__ */ React15__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__ */ React15__default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React15__default.createElement("div", { className: "w-12 h-12 rounded-2xl bg-green-100 dark:bg-green-900/30 flex items-center justify-center" }, /* @__PURE__ */ React15__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__ */ React15__default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }))), /* @__PURE__ */ React15__default.createElement("div", { className: "text-left" }, /* @__PURE__ */ React15__default.createElement("div", { className: "font-medium text-foreground" }, translations?.allCaughtUp || "All caught up!"), /* @__PURE__ */ React15__default.createElement("div", { className: "text-sm text-muted-foreground" }, translations?.noEventsScheduled || "No events scheduled"))))), /* @__PURE__ */ React15__default.createElement("div", { className: "text-center max-w-sm" }, /* @__PURE__ */ React15__default.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, translations?.noUpcoming || "Your schedule is clear"), /* @__PURE__ */ React15__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__ */ React15__default.createElement(
1448
+ var DayView = React10.memo(DayViewImpl);
1449
+
1450
+ // src/views/AgendaView.tsx
1451
+ import React12, { useMemo as useMemo2 } from "react";
1452
+ import { format as format10, isSameDay as isSameDay6, addDays as addDays4, startOfDay as startOfDay4, differenceInMinutes as differenceInMinutes3 } from "date-fns";
1453
+
1454
+ // src/components/EmptyState.tsx
1455
+ import React11 from "react";
1456
+ import { Plus as Plus2 } from "lucide-react";
1457
+ var AgendaEmptyState = ({ onCreateEvent, translations }) => /* @__PURE__ */ React11.createElement("div", { className: "flex flex-col items-center justify-center h-full min-h-[400px] py-12" }, /* @__PURE__ */ React11.createElement("div", { className: "relative mb-8" }, /* @__PURE__ */ React11.createElement("div", { className: "p-8 bg-gradient-to-br from-green-50 to-blue-50 dark:from-green-900/10 dark:to-blue-900/10 rounded-3xl border border-border/30" }, /* @__PURE__ */ React11.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React11.createElement("div", { className: "w-12 h-12 rounded-2xl bg-green-100 dark:bg-green-900/30 flex items-center justify-center" }, /* @__PURE__ */ React11.createElement("svg", { className: "w-6 h-6 text-green-600 dark:text-green-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2 }, /* @__PURE__ */ React11.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }))), /* @__PURE__ */ React11.createElement("div", { className: "text-left" }, /* @__PURE__ */ React11.createElement("div", { className: "font-medium text-foreground" }, translations?.allCaughtUp || "All caught up!"), /* @__PURE__ */ React11.createElement("div", { className: "text-sm text-muted-foreground" }, translations?.noEventsScheduled || "No events scheduled"))))), /* @__PURE__ */ React11.createElement("div", { className: "text-center max-w-sm" }, /* @__PURE__ */ React11.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, translations?.noUpcoming || "Your schedule is clear"), /* @__PURE__ */ React11.createElement("p", { className: "text-sm text-muted-foreground mb-6" }, translations?.noUpcomingHint || "No upcoming events to show. Create a new event to start planning."), onCreateEvent && /* @__PURE__ */ React11.createElement(
1059
1458
  "button",
1060
1459
  {
1061
1460
  onClick: onCreateEvent,
1062
1461
  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"
1063
1462
  },
1064
- /* @__PURE__ */ React15__default.createElement(Plus, { className: "w-4 h-4" }),
1463
+ /* @__PURE__ */ React11.createElement(Plus2, { className: "w-4 h-4" }),
1065
1464
  translations?.createEvent || "Create Event"
1066
1465
  )));
1466
+
1467
+ // src/views/AgendaView.tsx
1468
+ import { motion } from "framer-motion";
1469
+ import { Clock, Users, Paperclip, Bell } from "lucide-react";
1067
1470
  var formatDuration = (start, end) => {
1068
- const minutes = differenceInMinutes(end, start);
1471
+ const minutes = differenceInMinutes3(end, start);
1069
1472
  if (minutes < 60) return `${minutes}m`;
1070
1473
  const hours = Math.floor(minutes / 60);
1071
1474
  const remainingMinutes = minutes % 60;
1072
1475
  if (remainingMinutes === 0) return `${hours}h`;
1073
1476
  return `${hours}h ${remainingMinutes}m`;
1074
1477
  };
1075
- var getDateLabel = (date, locale, translations) => {
1076
- if (isToday(date)) return translations?.today || "Today";
1077
- if (isTomorrow(date)) return translations?.tomorrow || "Tomorrow";
1078
- return format(date, "EEEE", { locale });
1478
+ var getDateLabel = (date, today, locale, translations) => {
1479
+ if (isSameDay6(date, today)) return translations?.today || "Today";
1480
+ if (isSameDay6(date, addDays4(today, 1))) return translations?.tomorrow || "Tomorrow";
1481
+ return format10(date, "EEEE", { locale });
1079
1482
  };
1080
1483
  var AgendaView = ({
1081
1484
  currentDate,
@@ -1083,24 +1486,24 @@ var AgendaView = ({
1083
1486
  onEventClick,
1084
1487
  onCreateEvent,
1085
1488
  locale,
1086
- translations
1489
+ translations,
1490
+ timezone
1087
1491
  }) => {
1088
1492
  const is24h = uses24HourClock(locale);
1089
- const timePattern = is24h ? "H:mm" : "h:mm a";
1090
- const compactTimePattern = is24h ? "H:mm" : "h:mm";
1091
- const groupedEvents = useMemo(() => {
1092
- const startDate = startOfDay(currentDate);
1493
+ const { time: timePattern, compact: compactTimePattern } = timeFormats(locale);
1494
+ const today = displayToday(timezone);
1495
+ const groupedEvents = useMemo2(() => {
1496
+ const byDay = eventsByStartDay(events, timezone);
1093
1497
  const groups = [];
1094
- const sortedEvents = [...events].sort((a, b) => a.start.getTime() - b.start.getTime());
1095
1498
  for (let i = 0; i < 30; i++) {
1096
- const day = addDays(startDate, i);
1097
- const dayEvents = sortedEvents.filter((event) => isSameDay(event.start, day));
1098
- if (dayEvents.length > 0) {
1099
- groups.push({ date: day, events: dayEvents });
1499
+ const day = addDays4(startOfDay4(currentDate), i);
1500
+ const dayEvents = byDay.get(format10(day, "yyyy-MM-dd"));
1501
+ if (dayEvents?.length) {
1502
+ groups.push({ date: day, events: [...dayEvents].sort((a, b) => a.start.getTime() - b.start.getTime()) });
1100
1503
  }
1101
1504
  }
1102
1505
  return groups;
1103
- }, [currentDate, events]);
1506
+ }, [currentDate, events, timezone]);
1104
1507
  const container = {
1105
1508
  hidden: { opacity: 0 },
1106
1509
  show: {
@@ -1114,7 +1517,7 @@ var AgendaView = ({
1114
1517
  hidden: { opacity: 0, x: -20 },
1115
1518
  show: { opacity: 1, x: 0 }
1116
1519
  };
1117
- return /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col h-full bg-background overflow-y-auto" }, groupedEvents.length === 0 ? /* @__PURE__ */ React15__default.createElement(AgendaEmptyState, { onCreateEvent, translations }) : /* @__PURE__ */ React15__default.createElement(
1520
+ return /* @__PURE__ */ React12.createElement("div", { className: "flex flex-col h-full bg-background overflow-y-auto" }, groupedEvents.length === 0 ? /* @__PURE__ */ React12.createElement(AgendaEmptyState, { onCreateEvent, translations }) : /* @__PURE__ */ React12.createElement(
1118
1521
  motion.div,
1119
1522
  {
1120
1523
  className: "max-w-3xl mx-auto w-full pb-10 px-4 md:px-6",
@@ -1122,21 +1525,21 @@ var AgendaView = ({
1122
1525
  initial: "hidden",
1123
1526
  animate: "show"
1124
1527
  },
1125
- groupedEvents.map((group, groupIndex) => /* @__PURE__ */ React15__default.createElement(
1528
+ groupedEvents.map((group) => /* @__PURE__ */ React12.createElement(
1126
1529
  motion.div,
1127
1530
  {
1128
1531
  key: group.date.toISOString(),
1129
1532
  className: "relative",
1130
1533
  variants: item
1131
1534
  },
1132
- /* @__PURE__ */ React15__default.createElement("div", { className: "sticky top-0 bg-background/95 backdrop-blur-md py-4 z-10 border-b border-border/50" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React15__default.createElement("div", { className: cn(
1535
+ /* @__PURE__ */ React12.createElement("div", { className: "sticky top-0 bg-background/95 backdrop-blur-md py-4 z-10 border-b border-border/50" }, /* @__PURE__ */ React12.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React12.createElement("div", { className: cn(
1133
1536
  "flex flex-col items-center justify-center w-16 h-16 rounded-2xl transition-all",
1134
- isToday(group.date) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30" : "bg-muted/50 text-foreground"
1135
- ) }, /* @__PURE__ */ React15__default.createElement("span", { className: "text-2xl font-bold leading-none" }, format(group.date, "d")), /* @__PURE__ */ React15__default.createElement("span", { className: "text-xs font-medium uppercase tracking-wide opacity-80" }, format(group.date, "MMM", { locale }))), /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React15__default.createElement("span", { className: cn(
1537
+ isSameDay6(group.date, today) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30" : "bg-muted/50 text-foreground"
1538
+ ) }, /* @__PURE__ */ React12.createElement("span", { className: "text-2xl font-bold leading-none" }, format10(group.date, "d")), /* @__PURE__ */ React12.createElement("span", { className: "text-xs font-medium uppercase tracking-wide opacity-80" }, format10(group.date, "MMM", { locale }))), /* @__PURE__ */ React12.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React12.createElement("span", { className: cn(
1136
1539
  "text-lg font-semibold",
1137
- isToday(group.date) && "text-primary"
1138
- ) }, getDateLabel(group.date, locale, translations)), /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm text-muted-foreground" }, group.events.length, " ", group.events.length !== 1 ? translations?.eventPlural || "events" : translations?.eventSingular || "event")))),
1139
- /* @__PURE__ */ React15__default.createElement("div", { className: "py-4 space-y-3" }, group.events.map((event, eventIndex) => /* @__PURE__ */ React15__default.createElement(
1540
+ isSameDay6(group.date, today) && "text-primary"
1541
+ ) }, getDateLabel(group.date, today, locale, translations)), /* @__PURE__ */ React12.createElement("span", { className: "text-sm text-muted-foreground" }, group.events.length, " ", group.events.length !== 1 ? translations?.eventPlural || "events" : translations?.eventSingular || "event")))),
1542
+ /* @__PURE__ */ React12.createElement("div", { className: "py-4 space-y-3" }, group.events.map((event) => /* @__PURE__ */ React12.createElement(
1140
1543
  motion.div,
1141
1544
  {
1142
1545
  key: event.id,
@@ -1150,44 +1553,49 @@ var AgendaView = ({
1150
1553
  whileHover: { scale: 1.01, y: -2 },
1151
1554
  transition: { duration: 0.2 }
1152
1555
  },
1153
- /* @__PURE__ */ React15__default.createElement(
1556
+ /* @__PURE__ */ React12.createElement(
1154
1557
  "div",
1155
1558
  {
1156
1559
  className: "absolute left-0 top-3 bottom-3 w-1 rounded-full",
1157
1560
  style: { backgroundColor: event.color || "var(--primary)" }
1158
1561
  }
1159
1562
  ),
1160
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col items-center min-w-[70px] pl-2" }, event.allDay ? /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ React15__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__ */ React15__default.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ React15__default.createElement("span", { className: "text-base font-semibold text-foreground" }, format(event.start, compactTimePattern, { locale })), !is24h && /* @__PURE__ */ React15__default.createElement("span", { className: "text-xs text-muted-foreground uppercase" }, format(event.start, "a")), /* @__PURE__ */ React15__default.createElement("div", { className: "w-px h-3 bg-border my-1" }), /* @__PURE__ */ React15__default.createElement("span", { className: "text-xs text-muted-foreground/70 font-medium" }, formatDuration(event.start, event.end)))),
1161
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 min-w-0 space-y-2" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-start justify-between gap-2" }, /* @__PURE__ */ React15__default.createElement("h4", { className: "text-base font-semibold text-foreground group-hover:text-primary transition-colors line-clamp-1" }, event.title), /* @__PURE__ */ React15__default.createElement(
1563
+ /* @__PURE__ */ React12.createElement("div", { className: "flex flex-col items-center min-w-[70px] pl-2" }, event.allDay ? /* @__PURE__ */ React12.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ React12.createElement("span", { className: "text-xs font-semibold text-muted-foreground bg-muted/80 px-2.5 py-1 rounded-full" }, translations?.allDay || "All Day")) : /* @__PURE__ */ React12.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ React12.createElement("span", { className: "text-base font-semibold text-foreground" }, format10(toDisplay(event.start, timezone), compactTimePattern, { locale })), !is24h && /* @__PURE__ */ React12.createElement("span", { className: "text-xs text-muted-foreground uppercase" }, format10(toDisplay(event.start, timezone), "a")), /* @__PURE__ */ React12.createElement("div", { className: "w-px h-3 bg-border my-1" }), /* @__PURE__ */ React12.createElement("span", { className: "text-xs text-muted-foreground/70 font-medium" }, formatDuration(event.start, event.end)))),
1564
+ /* @__PURE__ */ React12.createElement("div", { className: "flex-1 min-w-0 space-y-2" }, /* @__PURE__ */ React12.createElement("div", { className: "flex items-start justify-between gap-2" }, /* @__PURE__ */ React12.createElement("h4", { className: "text-base font-semibold text-foreground group-hover:text-primary transition-colors line-clamp-1" }, event.title), /* @__PURE__ */ React12.createElement(
1162
1565
  "div",
1163
1566
  {
1164
1567
  className: "w-3 h-3 rounded-full shrink-0 mt-1.5",
1165
1568
  style: { backgroundColor: event.color || "var(--primary)" }
1166
1569
  }
1167
- )), event.description && /* @__PURE__ */ React15__default.createElement("p", { className: "text-sm text-muted-foreground line-clamp-2 leading-relaxed" }, event.description), /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-wrap items-center gap-3 pt-1" }, !event.allDay && /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React15__default.createElement(Clock, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React15__default.createElement("span", null, format(event.start, timePattern, { locale }), " - ", format(event.end, timePattern, { locale }))), event.guests && event.guests.length > 0 && /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React15__default.createElement(Users, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React15__default.createElement("span", null, event.guests.length, " ", event.guests.length !== 1 ? translations?.guestsCount || "guests" : translations?.guestCount || "guest")), event.attachments && event.attachments.length > 0 && /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React15__default.createElement(Paperclip, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React15__default.createElement("span", null, event.attachments.length)), event.reminders && event.reminders.length > 0 && /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React15__default.createElement(Bell, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React15__default.createElement("span", null, event.reminders.length)))),
1168
- /* @__PURE__ */ React15__default.createElement("div", { className: "absolute right-4 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity" }, /* @__PURE__ */ React15__default.createElement("svg", { className: "w-5 h-5 text-muted-foreground", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ React15__default.createElement("path", { d: "M9 18l6-6-6-6" })))
1570
+ )), event.description && /* @__PURE__ */ React12.createElement("p", { className: "text-sm text-muted-foreground line-clamp-2 leading-relaxed" }, event.description), /* @__PURE__ */ React12.createElement("div", { className: "flex flex-wrap items-center gap-3 pt-1" }, !event.allDay && /* @__PURE__ */ React12.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React12.createElement(Clock, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React12.createElement("span", null, format10(toDisplay(event.start, timezone), timePattern, { locale }), " - ", format10(toDisplay(event.end, timezone), timePattern, { locale }))), event.guests && event.guests.length > 0 && /* @__PURE__ */ React12.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React12.createElement(Users, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React12.createElement("span", null, event.guests.length, " ", event.guests.length !== 1 ? translations?.guestsCount || "guests" : translations?.guestCount || "guest")), event.attachments && event.attachments.length > 0 && /* @__PURE__ */ React12.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React12.createElement(Paperclip, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React12.createElement("span", null, event.attachments.length)), event.reminders && event.reminders.length > 0 && /* @__PURE__ */ React12.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ React12.createElement(Bell, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ React12.createElement("span", null, event.reminders.length)))),
1571
+ /* @__PURE__ */ React12.createElement("div", { className: "absolute right-4 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity" }, /* @__PURE__ */ React12.createElement("svg", { className: "w-5 h-5 text-muted-foreground", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ React12.createElement("path", { d: "M9 18l6-6-6-6" })))
1169
1572
  )))
1170
1573
  ))
1171
1574
  ));
1172
1575
  };
1576
+
1577
+ // src/views/ResourceView.tsx
1578
+ import React13, { useRef as useRef2 } from "react";
1579
+ import { format as format11, startOfDay as startOfDay5, differenceInMinutes as differenceInMinutes4 } from "date-fns";
1173
1580
  var ResourceView = ({
1174
1581
  currentDate,
1175
1582
  events,
1176
1583
  resources,
1177
1584
  onEventClick,
1178
1585
  onTimeSlotClick,
1179
- locale
1586
+ locale,
1587
+ timezone
1180
1588
  }) => {
1181
- const containerRef = useRef(null);
1589
+ const containerRef = useRef2(null);
1182
1590
  const hours = Array.from({ length: 24 }, (_, i) => i);
1183
1591
  const hourWidth = 100;
1184
- const timeFormat = uses24HourClock(locale) ? "H:mm" : "h a";
1592
+ const timeFormat = timeFormats(locale).hour;
1185
1593
  const getEventStyle = (event) => {
1186
- const start = new Date(event.start);
1187
- const end = new Date(event.end);
1188
- const dayStart = startOfDay(currentDate);
1189
- const startMinutes = differenceInMinutes(start, dayStart);
1190
- const durationMinutes = differenceInMinutes(end, start);
1594
+ const start = toDisplay(event.start, timezone);
1595
+ const end = toDisplay(event.end, timezone);
1596
+ const dayStart = startOfDay5(currentDate);
1597
+ const startMinutes = differenceInMinutes4(start, dayStart);
1598
+ const durationMinutes = differenceInMinutes4(end, start);
1191
1599
  const left = startMinutes / 60 * hourWidth;
1192
1600
  const width = durationMinutes / 60 * hourWidth;
1193
1601
  return {
@@ -1196,19 +1604,19 @@ var ResourceView = ({
1196
1604
  // Min width for visibility
1197
1605
  };
1198
1606
  };
1199
- return /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col h-full bg-background overflow-hidden" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex border-b border-border bg-muted/20" }, /* @__PURE__ */ React15__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__ */ React15__default.createElement("div", { className: "flex overflow-hidden" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex relative", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ React15__default.createElement(
1607
+ return /* @__PURE__ */ React13.createElement("div", { className: "flex flex-col h-full bg-background overflow-hidden" }, /* @__PURE__ */ React13.createElement("div", { className: "flex border-b border-border bg-muted/20" }, /* @__PURE__ */ React13.createElement("div", { className: "w-48 shrink-0 border-r border-border p-4 font-semibold text-sm bg-background sticky left-0 z-20" }, "Resources"), /* @__PURE__ */ React13.createElement("div", { className: "flex overflow-hidden" }, /* @__PURE__ */ React13.createElement("div", { className: "flex relative", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ React13.createElement(
1200
1608
  "div",
1201
1609
  {
1202
1610
  key: hour,
1203
1611
  className: "border-r border-border/50 text-xs text-muted-foreground p-2 font-medium shrink-0",
1204
1612
  style: { width: hourWidth }
1205
1613
  },
1206
- format((/* @__PURE__ */ new Date()).setHours(hour, 0, 0, 0), timeFormat, { locale })
1207
- ))))), /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 overflow-auto relative", ref: containerRef }, /* @__PURE__ */ React15__default.createElement("div", { className: "min-w-fit" }, resources.map((resource) => {
1614
+ format11((/* @__PURE__ */ new Date()).setHours(hour, 0, 0, 0), timeFormat, { locale })
1615
+ ))))), /* @__PURE__ */ React13.createElement("div", { className: "flex-1 overflow-auto relative", ref: containerRef }, /* @__PURE__ */ React13.createElement("div", { className: "min-w-fit" }, resources.map((resource) => {
1208
1616
  const resourceEvents = events.filter(
1209
- (e) => e.resourceId === resource.id && isSameDay(new Date(e.start), currentDate)
1617
+ (e) => e.resourceId === resource.id && isSameDisplayDay(e.start, currentDate, timezone)
1210
1618
  );
1211
- return /* @__PURE__ */ React15__default.createElement("div", { key: resource.id, className: "flex border-b border-border min-h-[100px]" }, /* @__PURE__ */ React15__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__ */ React15__default.createElement("img", { src: resource.avatar, alt: resource.label, className: "w-8 h-8 rounded-full object-cover" }) : /* @__PURE__ */ React15__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__ */ React15__default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm font-medium" }, resource.label), /* @__PURE__ */ React15__default.createElement("span", { className: "text-xs text-muted-foreground" }, "ID: ", resource.id))), /* @__PURE__ */ React15__default.createElement("div", { className: "relative flex", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ React15__default.createElement(
1619
+ return /* @__PURE__ */ React13.createElement("div", { key: resource.id, className: "flex border-b border-border min-h-[100px]" }, /* @__PURE__ */ React13.createElement("div", { className: "w-48 shrink-0 border-r border-border p-4 bg-background sticky left-0 z-10 flex items-center gap-3" }, resource.avatar ? /* @__PURE__ */ React13.createElement("img", { src: resource.avatar, alt: resource.label, className: "w-8 h-8 rounded-full object-cover" }) : /* @__PURE__ */ React13.createElement("div", { className: "w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center text-xs font-bold text-primary" }, resource.label.substring(0, 2).toUpperCase()), /* @__PURE__ */ React13.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React13.createElement("span", { className: "text-sm font-medium" }, resource.label), /* @__PURE__ */ React13.createElement("span", { className: "text-xs text-muted-foreground" }, "ID: ", resource.id))), /* @__PURE__ */ React13.createElement("div", { className: "relative flex", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ React13.createElement(
1212
1620
  "div",
1213
1621
  {
1214
1622
  key: hour,
@@ -1216,24 +1624,22 @@ var ResourceView = ({
1216
1624
  style: { width: hourWidth }
1217
1625
  },
1218
1626
  [0, 15, 30, 45].map((minute) => {
1219
- const slotDate = new Date(currentDate);
1220
- slotDate.setHours(hour, minute, 0, 0);
1221
- const slotId = `${resource.id}-${slotDate.toISOString()}`;
1222
- return /* @__PURE__ */ React15__default.createElement(
1627
+ const slotDate3 = new Date(currentDate);
1628
+ slotDate3.setHours(hour, minute, 0, 0);
1629
+ const slotId = `${resource.id}-${slotDate3.toISOString()}`;
1630
+ return /* @__PURE__ */ React13.createElement(
1223
1631
  DroppableCell,
1224
1632
  {
1225
1633
  key: minute,
1226
1634
  id: slotId,
1227
- date: slotDate,
1635
+ date: slotDate3,
1228
1636
  resourceId: resource.id,
1229
1637
  className: "h-full flex-1 border-r border-border/10 last:border-border/30 hover:bg-accent/10 transition-colors",
1230
- onClick: () => {
1231
- onTimeSlotClick?.(slotDate, resource.id);
1232
- }
1638
+ onSlotClick: onTimeSlotClick
1233
1639
  }
1234
1640
  );
1235
1641
  })
1236
- )), resourceEvents.map((event) => /* @__PURE__ */ React15__default.createElement(
1642
+ )), resourceEvents.map((event) => /* @__PURE__ */ React13.createElement(
1237
1643
  DraggableEvent,
1238
1644
  {
1239
1645
  key: event.id,
@@ -1250,10 +1656,17 @@ var ResourceView = ({
1250
1656
  color: "#fff"
1251
1657
  }
1252
1658
  },
1253
- /* @__PURE__ */ React15__default.createElement("div", { className: "truncate" }, event.title)
1659
+ /* @__PURE__ */ React13.createElement("div", { className: "truncate" }, event.title)
1254
1660
  ))));
1255
1661
  }))));
1256
1662
  };
1663
+
1664
+ // src/components/EventModal.tsx
1665
+ import React15, { useState as useState3, useEffect as useEffect3 } from "react";
1666
+
1667
+ // src/components/ui/Modal.tsx
1668
+ import React14, { useEffect as useEffect2, useRef as useRef3 } from "react";
1669
+ import { X } from "lucide-react";
1257
1670
  var Modal = ({
1258
1671
  isOpen,
1259
1672
  onClose,
@@ -1262,8 +1675,8 @@ var Modal = ({
1262
1675
  className,
1263
1676
  hideHeader = false
1264
1677
  }) => {
1265
- const overlayRef = useRef(null);
1266
- useEffect(() => {
1678
+ const overlayRef = useRef3(null);
1679
+ useEffect2(() => {
1267
1680
  const handleEscape = (e) => {
1268
1681
  if (e.key === "Escape") {
1269
1682
  onClose();
@@ -1277,14 +1690,14 @@ var Modal = ({
1277
1690
  };
1278
1691
  }, [isOpen, onClose]);
1279
1692
  if (!isOpen) return null;
1280
- return /* @__PURE__ */ 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__ */ React15__default.createElement(
1693
+ return /* @__PURE__ */ React14.createElement("div", { className: "absolute inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-md animate-in fade-in duration-300" }, /* @__PURE__ */ React14.createElement(
1281
1694
  "div",
1282
1695
  {
1283
1696
  ref: overlayRef,
1284
1697
  className: "absolute inset-0",
1285
1698
  onClick: onClose
1286
1699
  }
1287
- ), /* @__PURE__ */ React15__default.createElement(
1700
+ ), /* @__PURE__ */ React14.createElement(
1288
1701
  "div",
1289
1702
  {
1290
1703
  className: cn(
@@ -1292,7 +1705,7 @@ var Modal = ({
1292
1705
  className
1293
1706
  )
1294
1707
  },
1295
- !hideHeader && /* @__PURE__ */ 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__ */ React15__default.createElement("h3", { className: "text-lg font-semibold text-foreground" }, title), /* @__PURE__ */ React15__default.createElement(
1708
+ !hideHeader && /* @__PURE__ */ React14.createElement("div", { className: "flex items-center justify-between px-6 py-4 border-b border-border/50 shrink-0 bg-gradient-to-r from-muted/20 to-background" }, /* @__PURE__ */ React14.createElement("h3", { className: "text-lg font-semibold text-foreground" }, title), /* @__PURE__ */ React14.createElement(
1296
1709
  Button,
1297
1710
  {
1298
1711
  variant: "ghost",
@@ -1300,12 +1713,37 @@ var Modal = ({
1300
1713
  onClick: onClose,
1301
1714
  className: "h-9 w-9 p-0 rounded-xl hover:bg-accent/80 transition-all duration-200"
1302
1715
  },
1303
- /* @__PURE__ */ React15__default.createElement(X, { className: "h-4 w-4" }),
1304
- /* @__PURE__ */ React15__default.createElement("span", { className: "sr-only" }, "Close")
1716
+ /* @__PURE__ */ React14.createElement(X, { className: "h-4 w-4" }),
1717
+ /* @__PURE__ */ React14.createElement("span", { className: "sr-only" }, "Close")
1305
1718
  )),
1306
- /* @__PURE__ */ React15__default.createElement("div", { className: cn("overflow-y-auto flex-1", !hideHeader && "p-6") }, children)
1719
+ /* @__PURE__ */ React14.createElement("div", { className: cn("overflow-y-auto flex-1", !hideHeader && "p-6") }, children)
1307
1720
  ));
1308
1721
  };
1722
+
1723
+ // src/components/EventModal.tsx
1724
+ import { format as format12, differenceInMinutes as differenceInMinutes5 } from "date-fns";
1725
+ import { motion as motion2, AnimatePresence } from "framer-motion";
1726
+ import {
1727
+ Clock as Clock2,
1728
+ MapPin,
1729
+ AlignLeft,
1730
+ Trash2,
1731
+ X as X2,
1732
+ Edit2,
1733
+ Users as Users2,
1734
+ Paperclip as Paperclip2,
1735
+ File,
1736
+ Calendar as Calendar2,
1737
+ ChevronDown as ChevronDown2,
1738
+ Check,
1739
+ Download,
1740
+ Bell as Bell2,
1741
+ BellRing,
1742
+ Plus as Plus3,
1743
+ Repeat,
1744
+ Tag,
1745
+ ExternalLink
1746
+ } from "lucide-react";
1309
1747
  var REMINDER_OPTIONS = [
1310
1748
  { value: 0, label: "At time of event" },
1311
1749
  { value: 5, label: "5 minutes before" },
@@ -1347,13 +1785,10 @@ var EventModal = ({
1347
1785
  initialDate,
1348
1786
  onSave,
1349
1787
  onDelete,
1350
- calendars,
1351
- eventTypes,
1352
- translations
1788
+ calendars
1353
1789
  }) => {
1354
- const [mode, setMode] = useState("create");
1355
- const [activeTab, setActiveTab] = useState("details");
1356
- const [formData, setFormData] = useState({
1790
+ const [mode, setMode] = useState3("create");
1791
+ const [formData, setFormData] = useState3({
1357
1792
  title: "",
1358
1793
  description: "",
1359
1794
  location: "",
@@ -1367,10 +1802,10 @@ var EventModal = ({
1367
1802
  attachments: [],
1368
1803
  reminders: [{ id: "1", type: "notification", time: 30, label: "30 minutes before" }]
1369
1804
  });
1370
- const [isCalendarDropdownOpen, setIsCalendarDropdownOpen] = useState(false);
1371
- const [isColorPickerOpen, setIsColorPickerOpen] = useState(false);
1372
- const [isReminderDropdownOpen, setIsReminderDropdownOpen] = useState(false);
1373
- const [isGuestsDropdownOpen, setIsGuestsDropdownOpen] = useState(false);
1805
+ const [isCalendarDropdownOpen, setIsCalendarDropdownOpen] = useState3(false);
1806
+ const [isColorPickerOpen, setIsColorPickerOpen] = useState3(false);
1807
+ const [isReminderDropdownOpen, setIsReminderDropdownOpen] = useState3(false);
1808
+ const [isGuestsDropdownOpen, setIsGuestsDropdownOpen] = useState3(false);
1374
1809
  const fakeGuests = [
1375
1810
  "alice@example.com",
1376
1811
  "bob@example.com",
@@ -1378,9 +1813,8 @@ var EventModal = ({
1378
1813
  "diana@example.com",
1379
1814
  "evan@example.com"
1380
1815
  ];
1381
- useRef(null);
1382
- const [selectedGuests, setSelectedGuests] = useState([]);
1383
- useEffect(() => {
1816
+ const [selectedGuests, setSelectedGuests] = useState3([]);
1817
+ useEffect3(() => {
1384
1818
  if (isOpen) {
1385
1819
  if (event) {
1386
1820
  setMode("view");
@@ -1410,7 +1844,6 @@ var EventModal = ({
1410
1844
  reminders: [{ id: "1", type: "notification", time: 30, label: "30 minutes before" }]
1411
1845
  });
1412
1846
  setSelectedGuests([]);
1413
- setActiveTab("details");
1414
1847
  }
1415
1848
  }
1416
1849
  }, [isOpen, event, initialDate, calendars]);
@@ -1445,7 +1878,7 @@ var EventModal = ({
1445
1878
  };
1446
1879
  const formatDateForInput = (date) => {
1447
1880
  if (!date) return "";
1448
- return format(date, "yyyy-MM-dd'T'HH:mm");
1881
+ return format12(date, "yyyy-MM-dd'T'HH:mm");
1449
1882
  };
1450
1883
  const handleDateChange = (field, value) => {
1451
1884
  const date = new Date(value);
@@ -1495,14 +1928,14 @@ var EventModal = ({
1495
1928
  };
1496
1929
  const getDurationText = () => {
1497
1930
  if (!formData.start || !formData.end) return "";
1498
- const mins = differenceInMinutes(formData.end, formData.start);
1931
+ const mins = differenceInMinutes5(formData.end, formData.start);
1499
1932
  if (mins < 60) return `${mins} min`;
1500
1933
  const hours = Math.floor(mins / 60);
1501
1934
  const remainingMins = mins % 60;
1502
1935
  if (remainingMins === 0) return `${hours} hr`;
1503
1936
  return `${hours} hr ${remainingMins} min`;
1504
1937
  };
1505
- const renderViewMode = () => /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-col bg-background overflow-hidden w-full max-h-[90vh]" }, /* @__PURE__ */ React15__default.createElement(
1938
+ const renderViewMode = () => /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col bg-background overflow-hidden w-full max-h-[90vh]" }, /* @__PURE__ */ React15.createElement(
1506
1939
  "div",
1507
1940
  {
1508
1941
  className: "relative px-6 pt-6 pb-8",
@@ -1510,65 +1943,65 @@ var EventModal = ({
1510
1943
  background: `linear-gradient(135deg, ${event?.color || "#3b82f6"}15 0%, transparent 100%)`
1511
1944
  }
1512
1945
  },
1513
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center justify-between mb-6" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15__default.createElement(
1946
+ /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between mb-6" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(
1514
1947
  "div",
1515
1948
  {
1516
1949
  className: "w-3 h-3 rounded-full",
1517
1950
  style: { backgroundColor: event?.color || "#3b82f6" }
1518
1951
  }
1519
- ), /* @__PURE__ */ React15__default.createElement("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider" }, calendars?.find((c) => c.id === event?.calendarId)?.label || "Event")), /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React15__default.createElement(
1952
+ ), /* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider" }, calendars?.find((c) => c.id === event?.calendarId)?.label || "Event")), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React15.createElement(
1520
1953
  "button",
1521
1954
  {
1522
1955
  onClick: () => setMode("edit"),
1523
1956
  className: "p-2 hover:bg-background/80 rounded-lg transition-all text-muted-foreground hover:text-foreground",
1524
1957
  title: "Edit"
1525
1958
  },
1526
- /* @__PURE__ */ React15__default.createElement(Edit2, { className: "w-4 h-4" })
1527
- ), /* @__PURE__ */ React15__default.createElement(
1959
+ /* @__PURE__ */ React15.createElement(Edit2, { className: "w-4 h-4" })
1960
+ ), /* @__PURE__ */ React15.createElement(
1528
1961
  "button",
1529
1962
  {
1530
1963
  onClick: handleDelete,
1531
1964
  className: "p-2 hover:bg-destructive/10 rounded-lg transition-all text-muted-foreground hover:text-destructive",
1532
1965
  title: "Delete"
1533
1966
  },
1534
- /* @__PURE__ */ React15__default.createElement(Trash2, { className: "w-4 h-4" })
1535
- ), /* @__PURE__ */ React15__default.createElement(
1967
+ /* @__PURE__ */ React15.createElement(Trash2, { className: "w-4 h-4" })
1968
+ ), /* @__PURE__ */ React15.createElement(
1536
1969
  "button",
1537
1970
  {
1538
1971
  onClick: onClose,
1539
1972
  className: "p-2 hover:bg-background/80 rounded-lg transition-all text-muted-foreground hover:text-foreground",
1540
1973
  title: "Close"
1541
1974
  },
1542
- /* @__PURE__ */ React15__default.createElement(X, { className: "w-4 h-4" })
1975
+ /* @__PURE__ */ React15.createElement(X2, { className: "w-4 h-4" })
1543
1976
  ))),
1544
- /* @__PURE__ */ React15__default.createElement("h1", { className: "text-2xl font-bold text-foreground mb-3 leading-tight" }, event?.title || "(No title)"),
1545
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-3 text-sm" }, /* @__PURE__ */ React15__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__ */ React15__default.createElement(Calendar, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15__default.createElement("span", { className: "font-medium" }, event?.start && format(new Date(event.start), "EEE, MMM d"))), /* @__PURE__ */ React15__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__ */ React15__default.createElement(Clock, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15__default.createElement("span", { className: "font-medium" }, event?.start && format(new Date(event.start), "h:mm a"), " \u2013 ", event?.end && format(new Date(event.end), "h:mm a"))))
1546
- ), /* @__PURE__ */ React15__default.createElement("div", { className: "px-6 pb-6 space-y-4 overflow-y-auto flex-1" }, event?.location && /* @__PURE__ */ React15__default.createElement(
1547
- motion.div,
1977
+ /* @__PURE__ */ React15.createElement("h1", { className: "text-2xl font-bold text-foreground mb-3 leading-tight" }, event?.title || "(No title)"),
1978
+ /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-3 text-sm" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-background/60 backdrop-blur-sm rounded-lg border border-border/30" }, /* @__PURE__ */ React15.createElement(Calendar2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "font-medium" }, event?.start && format12(new Date(event.start), "EEE, MMM d"))), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-background/60 backdrop-blur-sm rounded-lg border border-border/30" }, /* @__PURE__ */ React15.createElement(Clock2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "font-medium" }, event?.start && format12(new Date(event.start), "h:mm a"), " \u2013 ", event?.end && format12(new Date(event.end), "h:mm a"))))
1979
+ ), /* @__PURE__ */ React15.createElement("div", { className: "px-6 pb-6 space-y-4 overflow-y-auto flex-1" }, event?.location && /* @__PURE__ */ React15.createElement(
1980
+ motion2.div,
1548
1981
  {
1549
1982
  initial: { opacity: 0, y: 10 },
1550
1983
  animate: { opacity: 1, y: 0 },
1551
1984
  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"
1552
1985
  },
1553
- /* @__PURE__ */ React15__default.createElement("div", { className: "p-2 bg-primary/10 rounded-xl" }, /* @__PURE__ */ React15__default.createElement(MapPin, { className: "w-5 h-5 text-primary" })),
1554
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React15__default.createElement("p", { className: "text-sm font-medium text-foreground" }, event.location), /* @__PURE__ */ React15__default.createElement("p", { className: "text-xs text-muted-foreground mt-0.5" }, "Click to open in maps")),
1555
- /* @__PURE__ */ React15__default.createElement(ExternalLink, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
1556
- ), event?.guests && event.guests.length > 0 && /* @__PURE__ */ React15__default.createElement(
1557
- motion.div,
1986
+ /* @__PURE__ */ React15.createElement("div", { className: "p-2 bg-primary/10 rounded-xl" }, /* @__PURE__ */ React15.createElement(MapPin, { className: "w-5 h-5 text-primary" })),
1987
+ /* @__PURE__ */ React15.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React15.createElement("p", { className: "text-sm font-medium text-foreground" }, event.location), /* @__PURE__ */ React15.createElement("p", { className: "text-xs text-muted-foreground mt-0.5" }, "Click to open in maps")),
1988
+ /* @__PURE__ */ React15.createElement(ExternalLink, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
1989
+ ), event?.guests && event.guests.length > 0 && /* @__PURE__ */ React15.createElement(
1990
+ motion2.div,
1558
1991
  {
1559
1992
  initial: { opacity: 0, y: 10 },
1560
1993
  animate: { opacity: 1, y: 0 },
1561
1994
  transition: { delay: 0.05 },
1562
1995
  className: "space-y-3"
1563
1996
  },
1564
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15__default.createElement(Users, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm font-medium text-foreground" }, event.guests.length, " ", event.guests.length > 1 ? "Guests" : "Guest"))),
1565
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-wrap gap-2" }, event.guests.map((email, index) => /* @__PURE__ */ React15__default.createElement(
1997
+ /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Users2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, event.guests.length, " ", event.guests.length > 1 ? "Guests" : "Guest"))),
1998
+ /* @__PURE__ */ React15.createElement("div", { className: "flex flex-wrap gap-2" }, event.guests.map((email, index) => /* @__PURE__ */ React15.createElement(
1566
1999
  "div",
1567
2000
  {
1568
2001
  key: index,
1569
2002
  className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-muted/30 border border-border/30 hover:bg-muted/50 transition-all cursor-pointer group"
1570
2003
  },
1571
- /* @__PURE__ */ React15__default.createElement(
2004
+ /* @__PURE__ */ React15.createElement(
1572
2005
  "div",
1573
2006
  {
1574
2007
  className: "w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold text-white",
@@ -1576,18 +2009,18 @@ var EventModal = ({
1576
2009
  },
1577
2010
  email[0].toUpperCase()
1578
2011
  ),
1579
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React15__default.createElement("p", { className: "text-sm font-medium text-foreground" }, email.split("@")[0]), /* @__PURE__ */ React15__default.createElement("p", { className: "text-xs text-muted-foreground truncate" }, email))
2012
+ /* @__PURE__ */ React15.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React15.createElement("p", { className: "text-sm font-medium text-foreground" }, email.split("@")[0]), /* @__PURE__ */ React15.createElement("p", { className: "text-xs text-muted-foreground truncate" }, email))
1580
2013
  )))
1581
- ), event?.reminders && event.reminders.length > 0 && /* @__PURE__ */ React15__default.createElement(
1582
- motion.div,
2014
+ ), event?.reminders && event.reminders.length > 0 && /* @__PURE__ */ React15.createElement(
2015
+ motion2.div,
1583
2016
  {
1584
2017
  initial: { opacity: 0, y: 10 },
1585
2018
  animate: { opacity: 1, y: 0 },
1586
2019
  transition: { delay: 0.1 },
1587
2020
  className: "flex items-center gap-3"
1588
2021
  },
1589
- /* @__PURE__ */ React15__default.createElement("div", { className: "p-2 bg-amber-500/10 rounded-xl" }, /* @__PURE__ */ React15__default.createElement(Bell, { className: "w-4 h-4 text-amber-500" })),
1590
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-wrap gap-2" }, event.reminders.map((reminder) => /* @__PURE__ */ React15__default.createElement(
2022
+ /* @__PURE__ */ React15.createElement("div", { className: "p-2 bg-amber-500/10 rounded-xl" }, /* @__PURE__ */ React15.createElement(Bell2, { className: "w-4 h-4 text-amber-500" })),
2023
+ /* @__PURE__ */ React15.createElement("div", { className: "flex flex-wrap gap-2" }, event.reminders.map((reminder) => /* @__PURE__ */ React15.createElement(
1591
2024
  "span",
1592
2025
  {
1593
2026
  key: reminder.id,
@@ -1595,45 +2028,45 @@ var EventModal = ({
1595
2028
  },
1596
2029
  reminder.label || `${reminder.time} min before`
1597
2030
  )))
1598
- ), event?.description && /* @__PURE__ */ React15__default.createElement(
1599
- motion.div,
2031
+ ), event?.description && /* @__PURE__ */ React15.createElement(
2032
+ motion2.div,
1600
2033
  {
1601
2034
  initial: { opacity: 0, y: 10 },
1602
2035
  animate: { opacity: 1, y: 0 },
1603
2036
  transition: { delay: 0.15 },
1604
2037
  className: "space-y-2"
1605
2038
  },
1606
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15__default.createElement(AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Notes")),
1607
- /* @__PURE__ */ React15__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)
1608
- ), event?.attachments && event.attachments.length > 0 && /* @__PURE__ */ React15__default.createElement(
1609
- motion.div,
2039
+ /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, "Notes")),
2040
+ /* @__PURE__ */ React15.createElement("div", { className: "text-sm text-foreground/80 whitespace-pre-wrap leading-relaxed pl-6 p-3 rounded-xl bg-muted/20 border border-border/30" }, event.description)
2041
+ ), event?.attachments && event.attachments.length > 0 && /* @__PURE__ */ React15.createElement(
2042
+ motion2.div,
1610
2043
  {
1611
2044
  initial: { opacity: 0, y: 10 },
1612
2045
  animate: { opacity: 1, y: 0 },
1613
2046
  transition: { delay: 0.2 },
1614
2047
  className: "space-y-2"
1615
2048
  },
1616
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15__default.createElement(Paperclip, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Attachments")),
1617
- /* @__PURE__ */ React15__default.createElement("div", { className: "grid gap-2" }, event.attachments.map((att) => /* @__PURE__ */ React15__default.createElement(
2049
+ /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Paperclip2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, "Attachments")),
2050
+ /* @__PURE__ */ React15.createElement("div", { className: "grid gap-2" }, event.attachments.map((att) => /* @__PURE__ */ React15.createElement(
1618
2051
  "div",
1619
2052
  {
1620
2053
  key: att.id,
1621
2054
  onClick: () => handleDownload(att),
1622
2055
  className: "flex items-center gap-3 p-3 rounded-xl border border-border/30 bg-muted/20 hover:bg-muted/40 transition-all cursor-pointer group"
1623
2056
  },
1624
- /* @__PURE__ */ React15__default.createElement("div", { className: "p-2 bg-primary/10 rounded-lg" }, /* @__PURE__ */ React15__default.createElement(File, { className: "w-4 h-4 text-primary" })),
1625
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React15__default.createElement("p", { className: "text-sm font-medium text-foreground truncate" }, att.name), /* @__PURE__ */ React15__default.createElement("p", { className: "text-xs text-muted-foreground" }, att.size)),
1626
- /* @__PURE__ */ React15__default.createElement(Download, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
2057
+ /* @__PURE__ */ React15.createElement("div", { className: "p-2 bg-primary/10 rounded-lg" }, /* @__PURE__ */ React15.createElement(File, { className: "w-4 h-4 text-primary" })),
2058
+ /* @__PURE__ */ React15.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React15.createElement("p", { className: "text-sm font-medium text-foreground truncate" }, att.name), /* @__PURE__ */ React15.createElement("p", { className: "text-xs text-muted-foreground" }, att.size)),
2059
+ /* @__PURE__ */ React15.createElement(Download, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
1627
2060
  )))
1628
2061
  )));
1629
- const renderEditMode = () => /* @__PURE__ */ React15__default.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col bg-background overflow-hidden w-full max-h-[85vh]" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center justify-between px-5 py-4 border-b border-border/50 shrink-0" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React15__default.createElement(
2062
+ const renderEditMode = () => /* @__PURE__ */ React15.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col bg-background overflow-hidden w-full max-h-[85vh]" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between px-5 py-4 border-b border-border/50 shrink-0" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React15.createElement(
1630
2063
  "button",
1631
2064
  {
1632
2065
  type: "button",
1633
2066
  onClick: () => setIsColorPickerOpen(!isColorPickerOpen),
1634
2067
  className: "relative p-1"
1635
2068
  },
1636
- /* @__PURE__ */ React15__default.createElement(
2069
+ /* @__PURE__ */ React15.createElement(
1637
2070
  "div",
1638
2071
  {
1639
2072
  className: "w-5 h-5 rounded-full cursor-pointer hover:scale-110 transition-transform",
@@ -1643,7 +2076,7 @@ var EventModal = ({
1643
2076
  }
1644
2077
  }
1645
2078
  ),
1646
- isColorPickerOpen && /* @__PURE__ */ React15__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__ */ React15__default.createElement(
2079
+ isColorPickerOpen && /* @__PURE__ */ React15.createElement("div", { className: "absolute top-full left-0 mt-2 p-2 bg-background border border-border rounded-xl shadow-xl z-50 flex flex-wrap gap-1.5 w-[180px]" }, COLOR_PALETTE.map((color) => /* @__PURE__ */ React15.createElement(
1647
2080
  "button",
1648
2081
  {
1649
2082
  key: color,
@@ -1659,15 +2092,15 @@ var EventModal = ({
1659
2092
  style: { backgroundColor: color, color }
1660
2093
  }
1661
2094
  )))
1662
- ), /* @__PURE__ */ React15__default.createElement("h2", { className: "text-lg font-semibold text-foreground" }, mode === "edit" ? "Edit Event" : "New Event")), /* @__PURE__ */ React15__default.createElement(
2095
+ ), /* @__PURE__ */ React15.createElement("h2", { className: "text-lg font-semibold text-foreground" }, mode === "edit" ? "Edit Event" : "New Event")), /* @__PURE__ */ React15.createElement(
1663
2096
  "button",
1664
2097
  {
1665
2098
  type: "button",
1666
2099
  onClick: onClose,
1667
2100
  className: "p-2 hover:bg-accent rounded-xl transition-all text-muted-foreground hover:text-foreground"
1668
2101
  },
1669
- /* @__PURE__ */ React15__default.createElement(X, { className: "w-4 h-4" })
1670
- )), /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 overflow-y-auto" }, /* @__PURE__ */ React15__default.createElement("div", { className: "px-5 py-4 space-y-5" }, /* @__PURE__ */ React15__default.createElement("div", null, /* @__PURE__ */ React15__default.createElement(
2102
+ /* @__PURE__ */ React15.createElement(X2, { className: "w-4 h-4" })
2103
+ )), /* @__PURE__ */ React15.createElement("div", { className: "flex-1 overflow-y-auto" }, /* @__PURE__ */ React15.createElement("div", { className: "px-5 py-4 space-y-5" }, /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement(
1671
2104
  "input",
1672
2105
  {
1673
2106
  type: "text",
@@ -1678,7 +2111,7 @@ var EventModal = ({
1678
2111
  onChange: (e) => setFormData({ ...formData, title: e.target.value }),
1679
2112
  placeholder: "Add title"
1680
2113
  }
1681
- )), /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-3 p-4 rounded-2xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15__default.createElement("div", { className: "p-2 bg-primary/10 rounded-xl shrink-0" }, /* @__PURE__ */ React15__default.createElement(Clock, { className: "w-5 h-5 text-primary" })), /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 grid grid-cols-2 gap-3" }, /* @__PURE__ */ React15__default.createElement("div", null, /* @__PURE__ */ React15__default.createElement("label", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, "Start"), /* @__PURE__ */ React15__default.createElement(
2114
+ )), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-3 p-4 rounded-2xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15.createElement("div", { className: "p-2 bg-primary/10 rounded-xl shrink-0" }, /* @__PURE__ */ React15.createElement(Clock2, { className: "w-5 h-5 text-primary" })), /* @__PURE__ */ React15.createElement("div", { className: "flex-1 grid grid-cols-2 gap-3" }, /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("label", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, "Start"), /* @__PURE__ */ React15.createElement(
1682
2115
  "input",
1683
2116
  {
1684
2117
  type: "datetime-local",
@@ -1686,7 +2119,7 @@ var EventModal = ({
1686
2119
  value: formatDateForInput(formData.start),
1687
2120
  onChange: (e) => handleDateChange("start", e.target.value)
1688
2121
  }
1689
- )), /* @__PURE__ */ React15__default.createElement("div", null, /* @__PURE__ */ React15__default.createElement("label", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, "End"), /* @__PURE__ */ React15__default.createElement(
2122
+ )), /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("label", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, "End"), /* @__PURE__ */ React15.createElement(
1690
2123
  "input",
1691
2124
  {
1692
2125
  type: "datetime-local",
@@ -1694,16 +2127,16 @@ var EventModal = ({
1694
2127
  value: formatDateForInput(formData.end),
1695
2128
  onChange: (e) => handleDateChange("end", e.target.value)
1696
2129
  }
1697
- )))), getDurationText() && /* @__PURE__ */ React15__default.createElement("div", { className: "flex justify-center" }, /* @__PURE__ */ React15__default.createElement("span", { className: "text-xs font-medium px-3 py-1 rounded-full bg-primary/10 text-primary" }, getDurationText())), /* @__PURE__ */ React15__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15__default.createElement(Bell, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Reminders")), /* @__PURE__ */ React15__default.createElement("div", { className: "relative" }, /* @__PURE__ */ React15__default.createElement(
2130
+ )))), getDurationText() && /* @__PURE__ */ React15.createElement("div", { className: "flex justify-center" }, /* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium px-3 py-1 rounded-full bg-primary/10 text-primary" }, getDurationText())), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Bell2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, "Reminders")), /* @__PURE__ */ React15.createElement("div", { className: "relative" }, /* @__PURE__ */ React15.createElement(
1698
2131
  "button",
1699
2132
  {
1700
2133
  type: "button",
1701
2134
  onClick: () => setIsReminderDropdownOpen(!isReminderDropdownOpen),
1702
2135
  className: "flex items-center gap-1 text-xs font-medium text-primary hover:text-primary/80 transition-colors"
1703
2136
  },
1704
- /* @__PURE__ */ React15__default.createElement(Plus, { className: "w-3.5 h-3.5" }),
2137
+ /* @__PURE__ */ React15.createElement(Plus3, { className: "w-3.5 h-3.5" }),
1705
2138
  "Add"
1706
- ), isReminderDropdownOpen && /* @__PURE__ */ React15__default.createElement(React15__default.Fragment, null, /* @__PURE__ */ React15__default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsReminderDropdownOpen(false) }), /* @__PURE__ */ React15__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__ */ React15__default.createElement(
2139
+ ), isReminderDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsReminderDropdownOpen(false) }), /* @__PURE__ */ React15.createElement("div", { className: "absolute right-0 top-full mt-1 w-48 bg-background border border-border rounded-xl shadow-xl z-50 py-1 max-h-60 overflow-y-auto" }, REMINDER_OPTIONS.map((option) => /* @__PURE__ */ React15.createElement(
1707
2140
  "button",
1708
2141
  {
1709
2142
  key: option.value,
@@ -1712,58 +2145,58 @@ var EventModal = ({
1712
2145
  className: "w-full px-3 py-2 text-left text-sm hover:bg-accent transition-colors"
1713
2146
  },
1714
2147
  option.label
1715
- )))))), formData.reminders && formData.reminders.length > 0 && /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-wrap gap-2" }, formData.reminders.map((reminder) => /* @__PURE__ */ React15__default.createElement(
2148
+ )))))), formData.reminders && formData.reminders.length > 0 && /* @__PURE__ */ React15.createElement("div", { className: "flex flex-wrap gap-2" }, formData.reminders.map((reminder) => /* @__PURE__ */ React15.createElement(
1716
2149
  "div",
1717
2150
  {
1718
2151
  key: reminder.id,
1719
2152
  className: "flex items-center gap-2 px-3 py-1.5 rounded-full bg-amber-500/10 border border-amber-500/20"
1720
2153
  },
1721
- /* @__PURE__ */ React15__default.createElement(BellRing, { className: "w-3.5 h-3.5 text-amber-500" }),
1722
- /* @__PURE__ */ React15__default.createElement("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400" }, reminder.label),
1723
- /* @__PURE__ */ React15__default.createElement(
2154
+ /* @__PURE__ */ React15.createElement(BellRing, { className: "w-3.5 h-3.5 text-amber-500" }),
2155
+ /* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400" }, reminder.label),
2156
+ /* @__PURE__ */ React15.createElement(
1724
2157
  "button",
1725
2158
  {
1726
2159
  type: "button",
1727
2160
  onClick: () => removeReminder(reminder.id),
1728
2161
  className: "p-0.5 hover:bg-amber-500/20 rounded-full transition-colors"
1729
2162
  },
1730
- /* @__PURE__ */ React15__default.createElement(X, { className: "w-3 h-3 text-amber-500" })
2163
+ /* @__PURE__ */ React15.createElement(X2, { className: "w-3 h-3 text-amber-500" })
1731
2164
  )
1732
- )))), /* @__PURE__ */ React15__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15__default.createElement(Users, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Guests")), /* @__PURE__ */ React15__default.createElement("div", { className: "relative" }, /* @__PURE__ */ React15__default.createElement(
2165
+ )))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Users2, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, "Guests")), /* @__PURE__ */ React15.createElement("div", { className: "relative" }, /* @__PURE__ */ React15.createElement(
1733
2166
  "button",
1734
2167
  {
1735
2168
  type: "button",
1736
2169
  onClick: () => setIsGuestsDropdownOpen(!isGuestsDropdownOpen),
1737
2170
  className: "w-full flex items-center justify-between px-4 py-3 bg-muted/20 border border-border/30 rounded-xl text-sm text-left hover:bg-muted/30 transition-all"
1738
2171
  },
1739
- /* @__PURE__ */ React15__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"),
1740
- /* @__PURE__ */ React15__default.createElement(ChevronDown, { className: cn("w-4 h-4 text-muted-foreground transition-transform", isGuestsDropdownOpen && "rotate-180") })
1741
- ), isGuestsDropdownOpen && /* @__PURE__ */ React15__default.createElement(React15__default.Fragment, null, /* @__PURE__ */ React15__default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsGuestsDropdownOpen(false) }), /* @__PURE__ */ React15__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__ */ React15__default.createElement(
2172
+ /* @__PURE__ */ React15.createElement("span", { className: selectedGuests.length > 0 ? "text-foreground font-medium" : "text-muted-foreground" }, selectedGuests.length > 0 ? `${selectedGuests.length} guest${selectedGuests.length > 1 ? "s" : ""} added` : "Add guests"),
2173
+ /* @__PURE__ */ React15.createElement(ChevronDown2, { className: cn("w-4 h-4 text-muted-foreground transition-transform", isGuestsDropdownOpen && "rotate-180") })
2174
+ ), isGuestsDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsGuestsDropdownOpen(false) }), /* @__PURE__ */ React15.createElement("div", { className: "absolute z-50 w-full mt-2 bg-background border border-border rounded-xl shadow-xl max-h-48 overflow-y-auto" }, fakeGuests.map((email) => /* @__PURE__ */ React15.createElement(
1742
2175
  "div",
1743
2176
  {
1744
2177
  key: email,
1745
2178
  className: "px-4 py-3 hover:bg-accent cursor-pointer flex items-center gap-3 transition-colors",
1746
2179
  onClick: () => toggleGuest(email)
1747
2180
  },
1748
- /* @__PURE__ */ React15__default.createElement("div", { className: cn(
2181
+ /* @__PURE__ */ React15.createElement("div", { className: cn(
1749
2182
  "w-5 h-5 rounded-md border-2 flex items-center justify-center transition-all",
1750
2183
  selectedGuests.includes(email) ? "bg-primary border-primary" : "border-border"
1751
- ) }, selectedGuests.includes(email) && /* @__PURE__ */ React15__default.createElement(Check, { className: "w-3 h-3 text-primary-foreground" })),
1752
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15__default.createElement(
2184
+ ) }, selectedGuests.includes(email) && /* @__PURE__ */ React15.createElement(Check, { className: "w-3 h-3 text-primary-foreground" })),
2185
+ /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(
1753
2186
  "div",
1754
2187
  {
1755
2188
  className: "w-7 h-7 rounded-full flex items-center justify-center text-xs font-semibold text-white",
1756
2189
  style: { backgroundColor: `hsl(${fakeGuests.indexOf(email) * 60}, 70%, 50%)` }
1757
2190
  },
1758
2191
  email[0].toUpperCase()
1759
- ), /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm" }, email))
1760
- ))))), selectedGuests.length > 0 && /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, selectedGuests.map((email) => /* @__PURE__ */ React15__default.createElement(
2192
+ ), /* @__PURE__ */ React15.createElement("span", { className: "text-sm" }, email))
2193
+ ))))), selectedGuests.length > 0 && /* @__PURE__ */ React15.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, selectedGuests.map((email) => /* @__PURE__ */ React15.createElement(
1761
2194
  "div",
1762
2195
  {
1763
2196
  key: email,
1764
2197
  className: "flex items-center gap-2 pl-1 pr-2 py-1 bg-muted/30 border border-border/30 rounded-full"
1765
2198
  },
1766
- /* @__PURE__ */ React15__default.createElement(
2199
+ /* @__PURE__ */ React15.createElement(
1767
2200
  "div",
1768
2201
  {
1769
2202
  className: "w-6 h-6 rounded-full flex items-center justify-center text-xs font-semibold text-white",
@@ -1771,17 +2204,17 @@ var EventModal = ({
1771
2204
  },
1772
2205
  email[0].toUpperCase()
1773
2206
  ),
1774
- /* @__PURE__ */ React15__default.createElement("span", { className: "text-xs font-medium text-foreground" }, email.split("@")[0]),
1775
- /* @__PURE__ */ React15__default.createElement(
2207
+ /* @__PURE__ */ React15.createElement("span", { className: "text-xs font-medium text-foreground" }, email.split("@")[0]),
2208
+ /* @__PURE__ */ React15.createElement(
1776
2209
  "button",
1777
2210
  {
1778
2211
  type: "button",
1779
2212
  onClick: () => toggleGuest(email),
1780
2213
  className: "p-0.5 hover:bg-destructive/10 rounded-full transition-colors"
1781
2214
  },
1782
- /* @__PURE__ */ React15__default.createElement(X, { className: "w-3 h-3 text-muted-foreground" })
2215
+ /* @__PURE__ */ React15.createElement(X2, { className: "w-3 h-3 text-muted-foreground" })
1783
2216
  )
1784
- )))), /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15__default.createElement(MapPin, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ React15__default.createElement(
2217
+ )))), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15.createElement(MapPin, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ React15.createElement(
1785
2218
  "input",
1786
2219
  {
1787
2220
  type: "text",
@@ -1790,7 +2223,7 @@ var EventModal = ({
1790
2223
  value: formData.location || "",
1791
2224
  onChange: (e) => setFormData({ ...formData, location: e.target.value })
1792
2225
  }
1793
- )), /* @__PURE__ */ React15__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15__default.createElement(AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Notes")), /* @__PURE__ */ React15__default.createElement(
2226
+ )), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm font-medium text-foreground" }, "Notes")), /* @__PURE__ */ React15.createElement(
1794
2227
  "textarea",
1795
2228
  {
1796
2229
  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",
@@ -1798,7 +2231,7 @@ var EventModal = ({
1798
2231
  value: formData.description || "",
1799
2232
  onChange: (e) => setFormData({ ...formData, description: e.target.value })
1800
2233
  }
1801
- )), /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15__default.createElement(Repeat, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ React15__default.createElement(
2234
+ )), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15.createElement(Repeat, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ React15.createElement(
1802
2235
  "select",
1803
2236
  {
1804
2237
  className: "flex-1 bg-transparent text-sm text-foreground focus:outline-none cursor-pointer",
@@ -1817,28 +2250,28 @@ var EventModal = ({
1817
2250
  }
1818
2251
  }
1819
2252
  },
1820
- /* @__PURE__ */ React15__default.createElement("option", { value: "" }, "Does not repeat"),
1821
- /* @__PURE__ */ React15__default.createElement("option", { value: "DAILY" }, "Daily"),
1822
- /* @__PURE__ */ React15__default.createElement("option", { value: "WEEKLY" }, "Weekly"),
1823
- /* @__PURE__ */ React15__default.createElement("option", { value: "MONTHLY" }, "Monthly"),
1824
- /* @__PURE__ */ React15__default.createElement("option", { value: "YEARLY" }, "Yearly")
1825
- )), /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center justify-between p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15__default.createElement(Tag, { className: "w-5 h-5 text-muted-foreground" }), /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm text-foreground" }, "Calendar")), /* @__PURE__ */ React15__default.createElement("div", { className: "relative" }, /* @__PURE__ */ React15__default.createElement(
2253
+ /* @__PURE__ */ React15.createElement("option", { value: "" }, "Does not repeat"),
2254
+ /* @__PURE__ */ React15.createElement("option", { value: "DAILY" }, "Daily"),
2255
+ /* @__PURE__ */ React15.createElement("option", { value: "WEEKLY" }, "Weekly"),
2256
+ /* @__PURE__ */ React15.createElement("option", { value: "MONTHLY" }, "Monthly"),
2257
+ /* @__PURE__ */ React15.createElement("option", { value: "YEARLY" }, "Yearly")
2258
+ )), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Tag, { className: "w-5 h-5 text-muted-foreground" }), /* @__PURE__ */ React15.createElement("span", { className: "text-sm text-foreground" }, "Calendar")), /* @__PURE__ */ React15.createElement("div", { className: "relative" }, /* @__PURE__ */ React15.createElement(
1826
2259
  "button",
1827
2260
  {
1828
2261
  type: "button",
1829
2262
  onClick: () => setIsCalendarDropdownOpen(!isCalendarDropdownOpen),
1830
2263
  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"
1831
2264
  },
1832
- /* @__PURE__ */ React15__default.createElement(
2265
+ /* @__PURE__ */ React15.createElement(
1833
2266
  "div",
1834
2267
  {
1835
2268
  className: "w-3 h-3 rounded-full",
1836
2269
  style: { backgroundColor: calendars?.find((c) => c.id === formData.calendarId)?.color || "#3b82f6" }
1837
2270
  }
1838
2271
  ),
1839
- /* @__PURE__ */ React15__default.createElement("span", { className: "font-medium" }, calendars?.find((c) => c.id === formData.calendarId)?.label || "Select"),
1840
- /* @__PURE__ */ React15__default.createElement(ChevronDown, { className: "w-3.5 h-3.5 text-muted-foreground" })
1841
- ), isCalendarDropdownOpen && /* @__PURE__ */ React15__default.createElement(React15__default.Fragment, null, /* @__PURE__ */ React15__default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsCalendarDropdownOpen(false) }), /* @__PURE__ */ React15__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__ */ React15__default.createElement(
2272
+ /* @__PURE__ */ React15.createElement("span", { className: "font-medium" }, calendars?.find((c) => c.id === formData.calendarId)?.label || "Select"),
2273
+ /* @__PURE__ */ React15.createElement(ChevronDown2, { className: "w-3.5 h-3.5 text-muted-foreground" })
2274
+ ), isCalendarDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsCalendarDropdownOpen(false) }), /* @__PURE__ */ React15.createElement("div", { className: "absolute right-0 bottom-full mb-2 w-48 bg-background border border-border rounded-xl shadow-xl z-50 py-1" }, calendars?.map((cal) => /* @__PURE__ */ React15.createElement(
1842
2275
  "button",
1843
2276
  {
1844
2277
  key: cal.id,
@@ -1853,19 +2286,19 @@ var EventModal = ({
1853
2286
  setIsCalendarDropdownOpen(false);
1854
2287
  }
1855
2288
  },
1856
- /* @__PURE__ */ React15__default.createElement("div", { className: "w-3 h-3 rounded-full", style: { backgroundColor: cal.color } }),
1857
- /* @__PURE__ */ React15__default.createElement("span", { className: "flex-1 text-sm" }, cal.label),
1858
- formData.calendarId === cal.id && /* @__PURE__ */ React15__default.createElement(Check, { className: "w-4 h-4 text-primary" })
1859
- )))))))), /* @__PURE__ */ React15__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__ */ React15__default.createElement(
2289
+ /* @__PURE__ */ React15.createElement("div", { className: "w-3 h-3 rounded-full", style: { backgroundColor: cal.color } }),
2290
+ /* @__PURE__ */ React15.createElement("span", { className: "flex-1 text-sm" }, cal.label),
2291
+ formData.calendarId === cal.id && /* @__PURE__ */ React15.createElement(Check, { className: "w-4 h-4 text-primary" })
2292
+ )))))))), /* @__PURE__ */ React15.createElement("div", { className: "px-5 py-4 border-t border-border/50 flex items-center justify-between bg-muted/10 shrink-0" }, mode === "edit" && /* @__PURE__ */ React15.createElement(
1860
2293
  "button",
1861
2294
  {
1862
2295
  type: "button",
1863
2296
  onClick: handleDelete,
1864
2297
  className: "flex items-center gap-2 px-4 py-2 text-destructive hover:bg-destructive/10 rounded-xl transition-all text-sm font-medium"
1865
2298
  },
1866
- /* @__PURE__ */ React15__default.createElement(Trash2, { className: "w-4 h-4" }),
2299
+ /* @__PURE__ */ React15.createElement(Trash2, { className: "w-4 h-4" }),
1867
2300
  "Delete"
1868
- ), mode === "create" && /* @__PURE__ */ React15__default.createElement("div", null), /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15__default.createElement(
2301
+ ), mode === "create" && /* @__PURE__ */ React15.createElement("div", null), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(
1869
2302
  "button",
1870
2303
  {
1871
2304
  type: "button",
@@ -1873,7 +2306,7 @@ var EventModal = ({
1873
2306
  className: "px-4 py-2.5 text-muted-foreground hover:text-foreground font-medium text-sm rounded-xl transition-all hover:bg-accent"
1874
2307
  },
1875
2308
  "Cancel"
1876
- ), /* @__PURE__ */ React15__default.createElement(
2309
+ ), /* @__PURE__ */ React15.createElement(
1877
2310
  "button",
1878
2311
  {
1879
2312
  type: "submit",
@@ -1881,8 +2314,8 @@ var EventModal = ({
1881
2314
  },
1882
2315
  mode === "edit" ? "Save Changes" : "Create Event"
1883
2316
  ))));
1884
- return /* @__PURE__ */ React15__default.createElement(Modal, { isOpen, onClose, hideHeader: true, className: "p-0 overflow-hidden max-w-lg rounded-2xl shadow-2xl" }, /* @__PURE__ */ React15__default.createElement(AnimatePresence, { mode: "wait" }, mode === "view" && event ? /* @__PURE__ */ React15__default.createElement(
1885
- motion.div,
2317
+ return /* @__PURE__ */ React15.createElement(Modal, { isOpen, onClose, hideHeader: true, className: "p-0 overflow-hidden max-w-lg rounded-2xl shadow-2xl" }, /* @__PURE__ */ React15.createElement(AnimatePresence, { mode: "wait" }, mode === "view" && event ? /* @__PURE__ */ React15.createElement(
2318
+ motion2.div,
1886
2319
  {
1887
2320
  key: "view",
1888
2321
  initial: { opacity: 0 },
@@ -1891,8 +2324,8 @@ var EventModal = ({
1891
2324
  transition: { duration: 0.15 }
1892
2325
  },
1893
2326
  renderViewMode()
1894
- ) : /* @__PURE__ */ React15__default.createElement(
1895
- motion.div,
2327
+ ) : /* @__PURE__ */ React15.createElement(
2328
+ motion2.div,
1896
2329
  {
1897
2330
  key: "edit",
1898
2331
  initial: { opacity: 0 },
@@ -1903,9 +2336,12 @@ var EventModal = ({
1903
2336
  renderEditMode()
1904
2337
  )));
1905
2338
  };
1906
- var Skeleton = ({ className, style }) => /* @__PURE__ */ React15__default.createElement("div", { className: cn("animate-pulse bg-muted/40 rounded", className), style });
1907
- var MonthViewSkeleton = () => /* @__PURE__ */ React15__default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React15__default.createElement("div", { className: "grid grid-cols-7 border-b border-border/50 bg-muted/10" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ React15__default.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-4 w-8 mx-auto" })))), /* @__PURE__ */ React15__default.createElement("div", { className: "grid grid-cols-7 flex-1" }, Array.from({ length: 35 }).map((_, i) => /* @__PURE__ */ React15__default.createElement("div", { key: i, className: "min-h-[120px] border-r border-b border-border/30 p-2" }, /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-4 w-6 mb-2" }), /* @__PURE__ */ React15__default.createElement("div", { className: "space-y-1" }, Math.random() > 0.5 && /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-5 w-full rounded-md" }), Math.random() > 0.7 && /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-5 w-3/4 rounded-md" }))))));
1908
- var WeekViewSkeleton = () => /* @__PURE__ */ React15__default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex border-b border-border/50 bg-muted/10" }, /* @__PURE__ */ React15__default.createElement("div", { className: "w-16 p-3 border-r border-border/30" }, /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-8 w-10 mx-auto" })), /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 grid grid-cols-7" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ React15__default.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-3 w-8 mx-auto mb-1" }), /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-8 w-8 mx-auto rounded-xl" }))))), /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ React15__default.createElement("div", { className: "w-16 border-r border-border/30" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ React15__default.createElement("div", { key: i, className: "h-[60px] relative" }, /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-4 w-10 absolute right-2 -translate-y-1/2" })))), /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, Array.from({ length: 7 }).map((_, colIdx) => /* @__PURE__ */ 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__ */ React15__default.createElement("div", { key: rowIdx, className: "h-[60px] border-b border-dashed border-border/20" })), Math.random() > 0.3 && /* @__PURE__ */ React15__default.createElement(
2339
+
2340
+ // src/components/Skeleton.tsx
2341
+ import React16 from "react";
2342
+ var Skeleton = ({ className, style }) => /* @__PURE__ */ React16.createElement("div", { className: cn("animate-pulse bg-muted/40 rounded", className), style });
2343
+ var MonthViewSkeleton = () => /* @__PURE__ */ React16.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React16.createElement("div", { className: "grid grid-cols-7 border-b border-border/50 bg-muted/10" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-4 w-8 mx-auto" })))), /* @__PURE__ */ React16.createElement("div", { className: "grid grid-cols-7 flex-1" }, Array.from({ length: 35 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "min-h-[120px] border-r border-b border-border/30 p-2" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-4 w-6 mb-2" }), /* @__PURE__ */ React16.createElement("div", { className: "space-y-1" }, Math.random() > 0.5 && /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-5 w-full rounded-md" }), Math.random() > 0.7 && /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-5 w-3/4 rounded-md" }))))));
2344
+ var WeekViewSkeleton = () => /* @__PURE__ */ React16.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React16.createElement("div", { className: "flex border-b border-border/50 bg-muted/10" }, /* @__PURE__ */ React16.createElement("div", { className: "w-16 p-3 border-r border-border/30" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-8 w-10 mx-auto" })), /* @__PURE__ */ React16.createElement("div", { className: "flex-1 grid grid-cols-7" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-3 w-8 mx-auto mb-1" }), /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-8 w-8 mx-auto rounded-xl" }))))), /* @__PURE__ */ React16.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ React16.createElement("div", { className: "w-16 border-r border-border/30" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "h-[60px] relative" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-4 w-10 absolute right-2 -translate-y-1/2" })))), /* @__PURE__ */ React16.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, Array.from({ length: 7 }).map((_, colIdx) => /* @__PURE__ */ React16.createElement("div", { key: colIdx, className: "relative border-r border-border/30 last:border-r-0" }, Array.from({ length: 10 }).map((_2, rowIdx) => /* @__PURE__ */ React16.createElement("div", { key: rowIdx, className: "h-[60px] border-b border-dashed border-border/20" })), Math.random() > 0.3 && /* @__PURE__ */ React16.createElement(
1909
2345
  Skeleton,
1910
2346
  {
1911
2347
  className: "absolute rounded-md",
@@ -1917,20 +2353,25 @@ var WeekViewSkeleton = () => /* @__PURE__ */ React15__default.createElement("div
1917
2353
  }
1918
2354
  }
1919
2355
  ))))));
1920
- var DayViewSkeleton = () => /* @__PURE__ */ React15__default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React15__default.createElement("div", { className: "px-6 py-4 border-b border-border/50 bg-muted/10 text-center" }, /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-7 w-64 mx-auto" })), /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ React15__default.createElement("div", { className: "w-20 border-r border-border/30 bg-muted/5" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ React15__default.createElement("div", { key: i, className: "h-[80px] relative" }, /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-4 w-12 absolute left-1/2 -translate-x-1/2 -translate-y-1/2" })))), /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 relative" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ React15__default.createElement("div", { key: i, className: "h-[80px] border-b border-dashed border-border/20" })), /* @__PURE__ */ React15__default.createElement(
2356
+ var DayViewSkeleton = () => /* @__PURE__ */ React16.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ React16.createElement("div", { className: "px-6 py-4 border-b border-border/50 bg-muted/10 text-center" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-7 w-64 mx-auto" })), /* @__PURE__ */ React16.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ React16.createElement("div", { className: "w-20 border-r border-border/30 bg-muted/5" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "h-[80px] relative" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-4 w-12 absolute left-1/2 -translate-x-1/2 -translate-y-1/2" })))), /* @__PURE__ */ React16.createElement("div", { className: "flex-1 relative" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ React16.createElement("div", { key: i, className: "h-[80px] border-b border-dashed border-border/20" })), /* @__PURE__ */ React16.createElement(
1921
2357
  Skeleton,
1922
2358
  {
1923
2359
  className: "absolute rounded-lg left-4 right-4",
1924
2360
  style: { top: "160px", height: "120px" }
1925
2361
  }
1926
- ), /* @__PURE__ */ React15__default.createElement(
2362
+ ), /* @__PURE__ */ React16.createElement(
1927
2363
  Skeleton,
1928
2364
  {
1929
2365
  className: "absolute rounded-lg left-4 right-4",
1930
2366
  style: { top: "400px", height: "80px" }
1931
2367
  }
1932
2368
  ))));
1933
- var AgendaViewSkeleton = () => /* @__PURE__ */ React15__default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden p-6" }, /* @__PURE__ */ React15__default.createElement("div", { className: "space-y-6" }, Array.from({ length: 4 }).map((_, dayIdx) => /* @__PURE__ */ React15__default.createElement("div", { key: dayIdx }, /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-5 w-40 mb-4" }), /* @__PURE__ */ React15__default.createElement("div", { className: "space-y-3" }, Array.from({ length: 2 + Math.floor(Math.random() * 3) }).map((_2, eventIdx) => /* @__PURE__ */ React15__default.createElement("div", { key: eventIdx, className: "flex items-center gap-4 p-3 rounded-xl bg-muted/10" }, /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-10 w-10 rounded-lg" }), /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 space-y-2" }, /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-4 w-3/4" }), /* @__PURE__ */ React15__default.createElement(Skeleton, { className: "h-3 w-1/2" })))))))));
2369
+ var AgendaViewSkeleton = () => /* @__PURE__ */ React16.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden p-6" }, /* @__PURE__ */ React16.createElement("div", { className: "space-y-6" }, Array.from({ length: 4 }).map((_, dayIdx) => /* @__PURE__ */ React16.createElement("div", { key: dayIdx }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-5 w-40 mb-4" }), /* @__PURE__ */ React16.createElement("div", { className: "space-y-3" }, Array.from({ length: 2 + Math.floor(Math.random() * 3) }).map((_2, eventIdx) => /* @__PURE__ */ React16.createElement("div", { key: eventIdx, className: "flex items-center gap-4 p-3 rounded-xl bg-muted/10" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-10 w-10 rounded-lg" }), /* @__PURE__ */ React16.createElement("div", { className: "flex-1 space-y-2" }, /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-4 w-3/4" }), /* @__PURE__ */ React16.createElement(Skeleton, { className: "h-3 w-1/2" })))))))));
2370
+
2371
+ // src/components/ContextMenu.tsx
2372
+ import React17, { useState as useState4, useCallback as useCallback2, useEffect as useEffect4, useRef as useRef4 } from "react";
2373
+ import { Edit3, Trash2 as Trash22, Copy } from "lucide-react";
2374
+ import { AnimatePresence as AnimatePresence2, motion as motion3 } from "framer-motion";
1934
2375
  var EventContextMenu = ({
1935
2376
  event,
1936
2377
  position,
@@ -1941,8 +2382,8 @@ var EventContextMenu = ({
1941
2382
  customActions = [],
1942
2383
  translations
1943
2384
  }) => {
1944
- const menuRef = useRef(null);
1945
- useEffect(() => {
2385
+ const menuRef = useRef4(null);
2386
+ useEffect4(() => {
1946
2387
  const handleKeyDown = (e) => {
1947
2388
  if (e.key === "Escape") {
1948
2389
  onClose();
@@ -1953,7 +2394,7 @@ var EventContextMenu = ({
1953
2394
  return () => document.removeEventListener("keydown", handleKeyDown);
1954
2395
  }
1955
2396
  }, [position, onClose]);
1956
- useEffect(() => {
2397
+ useEffect4(() => {
1957
2398
  const handleClickOutside = (e) => {
1958
2399
  if (menuRef.current && !menuRef.current.contains(e.target)) {
1959
2400
  onClose();
@@ -1971,7 +2412,7 @@ var EventContextMenu = ({
1971
2412
  ...onEdit ? [{
1972
2413
  id: "edit",
1973
2414
  label: translations?.edit || "Edit",
1974
- icon: /* @__PURE__ */ React15__default.createElement(Edit3, { className: "w-4 h-4" }),
2415
+ icon: /* @__PURE__ */ React17.createElement(Edit3, { className: "w-4 h-4" }),
1975
2416
  onClick: () => {
1976
2417
  onEdit(event);
1977
2418
  onClose();
@@ -1980,7 +2421,7 @@ var EventContextMenu = ({
1980
2421
  ...onDuplicate ? [{
1981
2422
  id: "duplicate",
1982
2423
  label: translations?.duplicate || "Duplicate",
1983
- icon: /* @__PURE__ */ React15__default.createElement(Copy, { className: "w-4 h-4" }),
2424
+ icon: /* @__PURE__ */ React17.createElement(Copy, { className: "w-4 h-4" }),
1984
2425
  onClick: () => {
1985
2426
  onDuplicate(event);
1986
2427
  onClose();
@@ -1990,7 +2431,7 @@ var EventContextMenu = ({
1990
2431
  ...onDelete ? [{
1991
2432
  id: "delete",
1992
2433
  label: translations?.delete || "Delete",
1993
- icon: /* @__PURE__ */ React15__default.createElement(Trash2, { className: "w-4 h-4" }),
2434
+ icon: /* @__PURE__ */ React17.createElement(Trash22, { className: "w-4 h-4" }),
1994
2435
  onClick: () => {
1995
2436
  onDelete(event.id);
1996
2437
  onClose();
@@ -2002,8 +2443,8 @@ var EventContextMenu = ({
2002
2443
  x: Math.min(position.x, window.innerWidth - 200),
2003
2444
  y: Math.min(position.y, window.innerHeight - (actions.length * 44 + 80))
2004
2445
  };
2005
- return /* @__PURE__ */ React15__default.createElement(AnimatePresence, null, /* @__PURE__ */ React15__default.createElement(
2006
- motion.div,
2446
+ return /* @__PURE__ */ React17.createElement(AnimatePresence2, null, /* @__PURE__ */ React17.createElement(
2447
+ motion3.div,
2007
2448
  {
2008
2449
  ref: menuRef,
2009
2450
  initial: { opacity: 0, scale: 0.95, y: -5 },
@@ -2016,14 +2457,14 @@ var EventContextMenu = ({
2016
2457
  top: adjustedPosition.y
2017
2458
  }
2018
2459
  },
2019
- /* @__PURE__ */ React15__default.createElement("div", { className: "px-3 py-2 border-b-[0.5px] border-border bg-muted/30" }, /* @__PURE__ */ React15__default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15__default.createElement(
2460
+ /* @__PURE__ */ React17.createElement("div", { className: "px-3 py-2 border-b-[0.5px] border-border bg-muted/30" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React17.createElement(
2020
2461
  "div",
2021
2462
  {
2022
2463
  className: "w-2.5 h-2.5 rounded-full shrink-0",
2023
2464
  style: { backgroundColor: event.color || "var(--primary)" }
2024
2465
  }
2025
- ), /* @__PURE__ */ React15__default.createElement("span", { className: "text-sm font-medium truncate text-foreground" }, event.title))),
2026
- /* @__PURE__ */ React15__default.createElement("div", { className: "py-1" }, actions.map((action, index) => /* @__PURE__ */ React15__default.createElement(React15__default.Fragment, { key: action.id }, index > 0 && action.variant === "danger" && /* @__PURE__ */ React15__default.createElement("div", { className: "h-px bg-border my-1" }), /* @__PURE__ */ React15__default.createElement(
2466
+ ), /* @__PURE__ */ React17.createElement("span", { className: "text-sm font-medium truncate text-foreground" }, event.title))),
2467
+ /* @__PURE__ */ React17.createElement("div", { className: "py-1" }, actions.map((action, index) => /* @__PURE__ */ React17.createElement(React17.Fragment, { key: action.id }, index > 0 && action.variant === "danger" && /* @__PURE__ */ React17.createElement("div", { className: "h-px bg-border my-1" }), /* @__PURE__ */ React17.createElement(
2027
2468
  "button",
2028
2469
  {
2029
2470
  onClick: action.onClick,
@@ -2035,13 +2476,13 @@ var EventContextMenu = ({
2035
2476
  )
2036
2477
  },
2037
2478
  action.icon,
2038
- /* @__PURE__ */ React15__default.createElement("span", null, action.label)
2479
+ /* @__PURE__ */ React17.createElement("span", null, action.label)
2039
2480
  ))))
2040
2481
  ));
2041
2482
  };
2042
2483
  var useEventContextMenu = () => {
2043
- const [contextMenu, setContextMenu] = useState({ event: null, position: null });
2044
- const openContextMenu = useCallback((event, e) => {
2484
+ const [contextMenu, setContextMenu] = useState4({ event: null, position: null });
2485
+ const openContextMenu = useCallback2((event, e) => {
2045
2486
  e.preventDefault();
2046
2487
  e.stopPropagation();
2047
2488
  setContextMenu({
@@ -2049,7 +2490,7 @@ var useEventContextMenu = () => {
2049
2490
  position: { x: e.clientX, y: e.clientY }
2050
2491
  });
2051
2492
  }, []);
2052
- const closeContextMenu = useCallback(() => {
2493
+ const closeContextMenu = useCallback2(() => {
2053
2494
  setContextMenu({ event: null, position: null });
2054
2495
  }, []);
2055
2496
  return {
@@ -2060,146 +2501,6 @@ var useEventContextMenu = () => {
2060
2501
  };
2061
2502
  };
2062
2503
 
2063
- // src/locales/index.ts
2064
- var en = {
2065
- today: "Today",
2066
- month: "Month",
2067
- week: "Week",
2068
- day: "Day",
2069
- agenda: "Agenda",
2070
- resource: "Resources",
2071
- createEvent: "Create Event",
2072
- editEvent: "Edit Event",
2073
- delete: "Delete",
2074
- save: "Save",
2075
- cancel: "Cancel",
2076
- title: "Add title",
2077
- start: "Start",
2078
- end: "End",
2079
- allDay: "All Day",
2080
- description: "Description",
2081
- repeat: "Repeat",
2082
- noRepeat: "Does not repeat",
2083
- selectCalendar: "Select Calendar",
2084
- selectType: "Select Type",
2085
- daily: "Daily",
2086
- weekly: "Weekly",
2087
- monthly: "Monthly",
2088
- yearly: "Yearly",
2089
- search: "Search events...",
2090
- allTypes: "All Types",
2091
- timezone: "Time zone",
2092
- localTime: "Local Time",
2093
- create: "Create",
2094
- calendars: "Calendars",
2095
- event: "Event",
2096
- task: "Task",
2097
- appointmentSchedule: "Appointment schedule",
2098
- new: "New",
2099
- dateAndTime: "Date & Time",
2100
- whosJoining: "Who's joining?",
2101
- suggestedTimes: "Suggested times for guests",
2102
- viewSuggestions: "View suggestions",
2103
- whereWillItBe: "Where will it be?",
2104
- location: "Enter address",
2105
- descriptionAndAttachments: "Description",
2106
- dragAndDrop: "Drag & drop files or",
2107
- guests: "Guests",
2108
- addGuests: "Add guests",
2109
- addAttachment: "Upload files",
2110
- moreOptions: "More options",
2111
- doesNotRepeat: "Does not repeat",
2112
- locationHelpText: 'Enter a physical address (e.g. "123 Main St") to generate the map.',
2113
- notes: "Notes...",
2114
- guestCount: "guest",
2115
- guestsCount: "guests",
2116
- repeatFor: "Repeat for",
2117
- times: "times",
2118
- until: "Until",
2119
- endRepeat: "End repeat",
2120
- never: "Never",
2121
- afterOccurrences: "After occurrences",
2122
- onDate: "On date",
2123
- tomorrow: "Tomorrow",
2124
- edit: "Edit",
2125
- duplicate: "Duplicate",
2126
- eventSingular: "event",
2127
- eventPlural: "events",
2128
- allCaughtUp: "All caught up!",
2129
- noEventsScheduled: "No events scheduled",
2130
- noUpcoming: "Your schedule is clear",
2131
- noUpcomingHint: "No upcoming events to show. Create a new event to start planning."
2132
- };
2133
- var fr = {
2134
- today: "Aujourd'hui",
2135
- month: "Mois",
2136
- week: "Semaine",
2137
- day: "Jour",
2138
- agenda: "Agenda",
2139
- resource: "Ressources",
2140
- createEvent: "Cr\xE9er un \xE9v\xE9nement",
2141
- editEvent: "Modifier l'\xE9v\xE9nement",
2142
- delete: "Supprimer",
2143
- save: "Enregistrer",
2144
- cancel: "Annuler",
2145
- title: "Ajouter un titre",
2146
- start: "D\xE9but",
2147
- end: "Fin",
2148
- allDay: "Toute la journ\xE9e",
2149
- description: "Description",
2150
- repeat: "R\xE9p\xE9ter",
2151
- noRepeat: "Ne se r\xE9p\xE8te pas",
2152
- selectCalendar: "S\xE9lectionner un calendrier",
2153
- selectType: "S\xE9lectionner un type",
2154
- daily: "Quotidien",
2155
- weekly: "Hebdomadaire",
2156
- monthly: "Mensuel",
2157
- yearly: "Annuel",
2158
- search: "Rechercher...",
2159
- allTypes: "Tous les types",
2160
- timezone: "Fuseau horaire",
2161
- localTime: "Heure locale",
2162
- create: "Cr\xE9er",
2163
- calendars: "Calendriers",
2164
- event: "\xC9v\xE9nement",
2165
- task: "T\xE2che",
2166
- appointmentSchedule: "Planning de rendez-vous",
2167
- new: "Nouveau",
2168
- dateAndTime: "Date et heure",
2169
- whosJoining: "Qui participe ?",
2170
- suggestedTimes: "Horaires sugg\xE9r\xE9s",
2171
- viewSuggestions: "Voir les suggestions",
2172
- whereWillItBe: "O\xF9 aura lieu ?",
2173
- location: "Entrer une adresse",
2174
- descriptionAndAttachments: "Description",
2175
- dragAndDrop: "Glisser-d\xE9poser des fichiers ou",
2176
- guests: "Invit\xE9s",
2177
- addGuests: "Ajouter des invit\xE9s",
2178
- addAttachment: "T\xE9l\xE9charger des fichiers",
2179
- moreOptions: "Plus d'options",
2180
- doesNotRepeat: "Ne se r\xE9p\xE8te pas",
2181
- locationHelpText: 'Entrez une adresse physique (ex: "123 Rue Principale") pour g\xE9n\xE9rer la carte.',
2182
- notes: "Notes...",
2183
- guestCount: "invit\xE9",
2184
- guestsCount: "invit\xE9s",
2185
- repeatFor: "R\xE9p\xE9ter pendant",
2186
- times: "fois",
2187
- until: "Jusqu'au",
2188
- endRepeat: "Fin de r\xE9p\xE9tition",
2189
- never: "Jamais",
2190
- afterOccurrences: "Apr\xE8s occurrences",
2191
- onDate: "\xC0 la date",
2192
- tomorrow: "Demain",
2193
- edit: "Modifier",
2194
- duplicate: "Dupliquer",
2195
- eventSingular: "\xE9v\xE9nement",
2196
- eventPlural: "\xE9v\xE9nements",
2197
- allCaughtUp: "Tout est \xE0 jour !",
2198
- noEventsScheduled: "Aucun \xE9v\xE9nement pr\xE9vu",
2199
- noUpcoming: "Votre planning est libre",
2200
- noUpcomingHint: "Aucun \xE9v\xE9nement \xE0 venir. Cr\xE9ez un nouvel \xE9v\xE9nement pour commencer \xE0 planifier."
2201
- };
2202
-
2203
2504
  // src/lib/theme.ts
2204
2505
  function colorToHsl(color) {
2205
2506
  let r = 0, g = 0, b = 0;
@@ -2225,7 +2526,7 @@ function colorToHsl(color) {
2225
2526
  const min = Math.min(r, g, b);
2226
2527
  let h = 0;
2227
2528
  let s = 0;
2228
- let l = (max + min) / 2;
2529
+ const l = (max + min) / 2;
2229
2530
  if (max !== min) {
2230
2531
  const d = max - min;
2231
2532
  s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
@@ -2278,6 +2579,162 @@ function getThemeStyles(theme) {
2278
2579
  }
2279
2580
  return styles;
2280
2581
  }
2582
+
2583
+ // src/hooks/useCalendarLogic.ts
2584
+ import { useMemo as useMemo3, useState as useState5 } from "react";
2585
+ import {
2586
+ addDays as addDays5,
2587
+ addMonths as addMonths3,
2588
+ addWeeks,
2589
+ endOfMonth as endOfMonth2,
2590
+ format as format13,
2591
+ startOfMonth as startOfMonth3,
2592
+ startOfWeek as startOfWeek2,
2593
+ subDays,
2594
+ subMonths as subMonths2,
2595
+ subWeeks
2596
+ } from "date-fns";
2597
+
2598
+ // src/core/recurrence.ts
2599
+ import { addMonths as addMonths2, startOfMonth as startOfMonth2 } from "date-fns";
2600
+ import { RRule } from "rrule";
2601
+ var WEEKDAYS = [RRule.MO, RRule.TU, RRule.WE, RRule.TH, RRule.FR, RRule.SA, RRule.SU];
2602
+ var toFloating = (instant, tz) => {
2603
+ const w = toDisplay(instant, tz);
2604
+ return new Date(Date.UTC(w.getFullYear(), w.getMonth(), w.getDate(), w.getHours(), w.getMinutes(), w.getSeconds(), w.getMilliseconds()));
2605
+ };
2606
+ var fromFloating = (floating, tz) => fromDisplay(
2607
+ new Date(
2608
+ floating.getUTCFullYear(),
2609
+ floating.getUTCMonth(),
2610
+ floating.getUTCDate(),
2611
+ floating.getUTCHours(),
2612
+ floating.getUTCMinutes(),
2613
+ floating.getUTCSeconds(),
2614
+ floating.getUTCMilliseconds()
2615
+ ),
2616
+ tz
2617
+ );
2618
+ var minuteKey = (date) => Math.floor(date.getTime() / 6e4);
2619
+ var FREQUENCIES = { DAILY: RRule.DAILY, WEEKLY: RRule.WEEKLY, MONTHLY: RRule.MONTHLY, YEARLY: RRule.YEARLY };
2620
+ function buildRule(event, tz) {
2621
+ const r = event.recurrence;
2622
+ const freq = FREQUENCIES[r.freq];
2623
+ if (freq === void 0) throw new Error(`unsupported frequency "${r.freq}"`);
2624
+ return new RRule({
2625
+ freq,
2626
+ interval: r.interval || 1,
2627
+ dtstart: toFloating(event.start, tz),
2628
+ until: r.until ? toFloating(r.until, tz) : void 0,
2629
+ count: r.count,
2630
+ byweekday: r.byweekday?.length ? r.byweekday.map((d) => WEEKDAYS[d]) : void 0
2631
+ });
2632
+ }
2633
+ function occurrencesInMonth(event, monthStart, tz) {
2634
+ const rule = buildRule(event, tz);
2635
+ const excluded = new Set((event.recurrence.exdates ?? []).map(minuteKey));
2636
+ const duration = event.end.getTime() - event.start.getTime();
2637
+ const from = toFloating(monthStart, tz);
2638
+ const to = toFloating(addMonths2(monthStart, 1), tz);
2639
+ const result = [];
2640
+ for (const floating of rule.between(from, to, true)) {
2641
+ if (floating.getTime() === to.getTime()) continue;
2642
+ const start = fromFloating(floating, tz);
2643
+ if (excluded.has(minuteKey(start))) continue;
2644
+ result.push({
2645
+ ...event,
2646
+ id: `${event.id}-${start.getTime()}`,
2647
+ originalEventId: event.id,
2648
+ occurrenceStart: start,
2649
+ start,
2650
+ end: new Date(start.getTime() + duration)
2651
+ });
2652
+ }
2653
+ return result;
2654
+ }
2655
+ var MAX_MONTHS_PER_EVENT = 12;
2656
+ var occurrenceCache = /* @__PURE__ */ new WeakMap();
2657
+ function cachedMonth(event, monthStart, tz) {
2658
+ let months = occurrenceCache.get(event);
2659
+ if (!months) {
2660
+ months = /* @__PURE__ */ new Map();
2661
+ occurrenceCache.set(event, months);
2662
+ }
2663
+ const key = `${monthStart.getFullYear()}-${monthStart.getMonth()}|${tz ?? ""}`;
2664
+ let occurrences = months.get(key);
2665
+ if (occurrences) {
2666
+ months.delete(key);
2667
+ } else {
2668
+ occurrences = occurrencesInMonth(event, monthStart, tz);
2669
+ if (months.size >= MAX_MONTHS_PER_EVENT) months.delete(months.keys().next().value);
2670
+ }
2671
+ months.set(key, occurrences);
2672
+ return occurrences;
2673
+ }
2674
+ function expandRecurrences(events, range, anchorTz) {
2675
+ const result = [];
2676
+ const firstMonth = startOfMonth2(toDisplay(range.start, anchorTz));
2677
+ const lastMonth = startOfMonth2(toDisplay(range.end, anchorTz));
2678
+ for (const event of events) {
2679
+ if (!event.recurrence) {
2680
+ result.push(event);
2681
+ continue;
2682
+ }
2683
+ try {
2684
+ for (let month = firstMonth; month <= lastMonth; month = addMonths2(month, 1)) {
2685
+ for (const occurrence of cachedMonth(event, fromDisplay(month, anchorTz), anchorTz)) {
2686
+ if (occurrence.end >= range.start && occurrence.start <= range.end) result.push(occurrence);
2687
+ }
2688
+ }
2689
+ } catch (error) {
2690
+ warnOnce(`invalid-recurrence:${event.id}`, `Event "${event.id}" has an invalid recurrence rule: ${String(error)}`);
2691
+ result.push(event);
2692
+ }
2693
+ }
2694
+ return result;
2695
+ }
2696
+ function stripOccurrenceFields(event) {
2697
+ const { originalEventId: _originalEventId, occurrenceStart: _occurrenceStart, ...rest } = event;
2698
+ return rest;
2699
+ }
2700
+ var shiftFloating = (instant, deltaMs, tz) => fromFloating(new Date(toFloating(instant, tz).getTime() + deltaMs), tz);
2701
+ var DAY_MS = 24 * 60 * 60 * 1e3;
2702
+ var floatingDay = (floating) => Math.floor(floating.getTime() / DAY_MS);
2703
+ function shiftSeries(master, occurrence, newStart, newEnd, anchorTz) {
2704
+ const fromFloat = toFloating(occurrence.start, anchorTz);
2705
+ const toFloat = toFloating(newStart, anchorTz);
2706
+ const deltaMs = toFloat.getTime() - fromFloat.getTime();
2707
+ const dayDelta = floatingDay(toFloat) - floatingDay(fromFloat);
2708
+ const start = shiftFloating(master.start, deltaMs, anchorTz);
2709
+ const end = new Date(start.getTime() + (newEnd.getTime() - newStart.getTime()));
2710
+ const recurrence = master.recurrence && {
2711
+ ...master.recurrence,
2712
+ byweekday: master.recurrence.byweekday && dayDelta % 7 !== 0 ? master.recurrence.byweekday.map((d) => ((d + dayDelta) % 7 + 7) % 7) : master.recurrence.byweekday,
2713
+ exdates: master.recurrence.exdates?.map((d) => shiftFloating(d, deltaMs, anchorTz))
2714
+ };
2715
+ return stripOccurrenceFields({ ...master, start, end, recurrence });
2716
+ }
2717
+ function excludeOccurrence(master, occurrenceStart) {
2718
+ const recurrence = master.recurrence ?? { freq: "DAILY" };
2719
+ return { ...master, recurrence: { ...recurrence, exdates: [...recurrence.exdates ?? [], occurrenceStart] } };
2720
+ }
2721
+
2722
+ // src/hooks/useStableCallback.ts
2723
+ import { useCallback as useCallback3, useRef as useRef5 } from "react";
2724
+ function useStableCallback(fn) {
2725
+ const ref = useRef5(fn);
2726
+ ref.current = fn;
2727
+ return useCallback3((...args) => ref.current(...args), []);
2728
+ }
2729
+
2730
+ // src/hooks/useCalendarLogic.ts
2731
+ function expansionRange(monthStart) {
2732
+ return {
2733
+ start: startOfWeek2(startOfMonth3(subMonths2(monthStart, 1))),
2734
+ end: addDays5(endOfMonth2(addMonths3(monthStart, 1)), 37)
2735
+ };
2736
+ }
2737
+ var DAY_MS2 = 24 * 60 * 60 * 1e3;
2281
2738
  var useCalendarLogic = ({
2282
2739
  events,
2283
2740
  view: controlledView,
@@ -2288,72 +2745,47 @@ var useCalendarLogic = ({
2288
2745
  onEventUpdate,
2289
2746
  onEventCreate,
2290
2747
  onEventDelete,
2748
+ onEventDrop,
2749
+ onEventResize,
2750
+ onOccurrenceDelete,
2291
2751
  readOnly,
2292
2752
  timezone
2293
2753
  }) => {
2294
- const [internalView, setInternalView] = useState("week");
2295
- const [internalDate, setInternalDate] = useState(/* @__PURE__ */ new Date());
2296
- const [isSidebarOpen, setIsSidebarOpen] = useState(true);
2297
- const [isModalOpen, setIsModalOpen] = useState(false);
2298
- const [selectedEvent, setSelectedEvent] = useState(null);
2299
- const [modalInitialDate, setModalInitialDate] = useState(void 0);
2754
+ const [internalView, setInternalView] = useState5("week");
2755
+ const [internalDate, setInternalDate] = useState5(() => /* @__PURE__ */ new Date());
2756
+ const [isSidebarOpen, setIsSidebarOpen] = useState5(true);
2757
+ const [isModalOpen, setIsModalOpen] = useState5(false);
2758
+ const [selectedEvent, setSelectedEvent] = useState5(null);
2759
+ const [modalInitialDate, setModalInitialDate] = useState5(void 0);
2760
+ const [modalInitialResourceId, setModalInitialResourceId] = useState5(void 0);
2300
2761
  const view = controlledView ?? internalView;
2301
2762
  const currentDate = controlledDate ?? internalDate;
2302
- const expandedEvents = useMemo(() => {
2303
- const allEvents = [];
2304
- const rangeStart = subDays(currentDate, 365);
2305
- const rangeEnd = addDays(currentDate, 365);
2306
- events.forEach((event) => {
2307
- if (event.recurrence) {
2308
- try {
2309
- const rule = new RRule({
2310
- freq: RRule[event.recurrence.freq],
2311
- interval: event.recurrence.interval || 1,
2312
- dtstart: new Date(event.start),
2313
- until: event.recurrence.until ? new Date(event.recurrence.until) : void 0,
2314
- count: event.recurrence.count
2315
- });
2316
- const dates = rule.between(rangeStart, rangeEnd);
2317
- dates.forEach((date) => {
2318
- const duration = differenceInMilliseconds(new Date(event.end), new Date(event.start));
2319
- allEvents.push({
2320
- ...event,
2321
- id: `${event.id}-${date.getTime()}`,
2322
- // Unique ID for each instance
2323
- originalEventId: event.id,
2324
- // Reference to original
2325
- start: date,
2326
- end: new Date(date.getTime() + duration)
2327
- });
2328
- });
2329
- } catch (e) {
2330
- console.error("Error parsing recurrence rule", e);
2331
- allEvents.push(event);
2332
- }
2333
- } else {
2334
- allEvents.push(event);
2335
- }
2336
- });
2337
- return allEvents;
2338
- }, [events, currentDate]);
2339
- const handleViewChange = (newView) => {
2763
+ const normalizedEvents = useMemo3(() => normalizeEvents(events), [events]);
2764
+ const monthKey = format13(currentDate, "yyyy-MM");
2765
+ const range = useMemo3(() => expansionRange(/* @__PURE__ */ new Date(`${monthKey}-01T00:00:00`)), [monthKey]);
2766
+ const expandedEvents = useMemo3(
2767
+ () => expandRecurrences(normalizedEvents, range, timezone),
2768
+ [normalizedEvents, range, timezone]
2769
+ );
2770
+ const masterOf = (occurrence) => normalizedEvents.find((e) => e.id === occurrence.originalEventId);
2771
+ const handleViewChange = useStableCallback((newView) => {
2340
2772
  if (controlledOnViewChange) {
2341
2773
  controlledOnViewChange(newView);
2342
2774
  } else {
2343
2775
  setInternalView(newView);
2344
2776
  }
2345
- };
2346
- const handleDateChange = (newDate) => {
2777
+ });
2778
+ const handleDateChange = useStableCallback((newDate) => {
2347
2779
  if (controlledOnDateChange) {
2348
2780
  controlledOnDateChange(newDate);
2349
2781
  } else {
2350
2782
  setInternalDate(newDate);
2351
2783
  }
2352
- };
2353
- const handlePrev = () => {
2784
+ });
2785
+ const handlePrev = useStableCallback(() => {
2354
2786
  switch (view) {
2355
2787
  case "month":
2356
- handleDateChange(subMonths(currentDate, 1));
2788
+ handleDateChange(subMonths2(currentDate, 1));
2357
2789
  break;
2358
2790
  case "week":
2359
2791
  handleDateChange(subWeeks(currentDate, 1));
@@ -2366,133 +2798,139 @@ var useCalendarLogic = ({
2366
2798
  handleDateChange(subDays(currentDate, 7));
2367
2799
  break;
2368
2800
  }
2369
- };
2370
- const handleNext = () => {
2801
+ });
2802
+ const handleNext = useStableCallback(() => {
2371
2803
  switch (view) {
2372
2804
  case "month":
2373
- handleDateChange(addMonths(currentDate, 1));
2805
+ handleDateChange(addMonths3(currentDate, 1));
2374
2806
  break;
2375
2807
  case "week":
2376
2808
  handleDateChange(addWeeks(currentDate, 1));
2377
2809
  break;
2378
2810
  case "day":
2379
2811
  case "resource":
2380
- handleDateChange(addDays(currentDate, 1));
2812
+ handleDateChange(addDays5(currentDate, 1));
2381
2813
  break;
2382
2814
  case "agenda":
2383
- handleDateChange(addDays(currentDate, 7));
2815
+ handleDateChange(addDays5(currentDate, 7));
2384
2816
  break;
2385
2817
  }
2386
- };
2387
- const handleToday = () => {
2818
+ });
2819
+ const handleToday = useStableCallback(() => {
2388
2820
  handleDateChange(/* @__PURE__ */ new Date());
2389
- };
2390
- const handleDateClick = (date) => {
2821
+ });
2822
+ const handleDateClick = useStableCallback((date) => {
2391
2823
  handleDateChange(date);
2392
2824
  handleViewChange("day");
2393
- };
2394
- const handleTimeSlotClick = (date) => {
2825
+ });
2826
+ const handleTimeSlotClick = useStableCallback((date, resourceId) => {
2395
2827
  if (readOnly) return;
2396
2828
  setSelectedEvent(null);
2397
2829
  setModalInitialDate(date);
2830
+ setModalInitialResourceId(resourceId);
2398
2831
  setIsModalOpen(true);
2399
- };
2400
- const handleEventClickInternal = (event) => {
2401
- if (onEventClick) {
2402
- onEventClick(event);
2403
- }
2832
+ });
2833
+ const handleEventClickInternal = useStableCallback((event) => {
2834
+ onEventClick?.(event);
2404
2835
  if (!readOnly) {
2405
2836
  setSelectedEvent(event);
2406
2837
  setModalInitialDate(void 0);
2838
+ setModalInitialResourceId(void 0);
2407
2839
  setIsModalOpen(true);
2408
2840
  }
2409
- };
2410
- const handleCreateEvent = () => {
2841
+ });
2842
+ const handleCreateEvent = useStableCallback(() => {
2411
2843
  if (readOnly) return;
2412
2844
  setSelectedEvent(null);
2413
2845
  setModalInitialDate(/* @__PURE__ */ new Date());
2846
+ setModalInitialResourceId(void 0);
2414
2847
  setIsModalOpen(true);
2415
- };
2416
- const handleModalSave = (eventData) => {
2417
- let effectiveEventId = selectedEvent?.id;
2848
+ });
2849
+ const handleModalSave = useStableCallback((eventData) => {
2418
2850
  if (selectedEvent?.originalEventId) {
2419
- effectiveEventId = selectedEvent.originalEventId;
2420
- }
2421
- if (effectiveEventId) {
2422
- if (onEventUpdate) {
2423
- onEventUpdate({
2424
- ...eventData,
2425
- id: effectiveEventId
2426
- });
2427
- }
2851
+ const master = masterOf(selectedEvent);
2852
+ if (!master) return;
2853
+ const edited = {
2854
+ ...master,
2855
+ ...stripOccurrenceFields(eventData),
2856
+ id: master.id,
2857
+ start: master.start,
2858
+ end: master.end
2859
+ };
2860
+ onEventUpdate?.(
2861
+ shiftSeries(edited, selectedEvent, eventData.start ?? selectedEvent.start, eventData.end ?? selectedEvent.end, timezone)
2862
+ );
2863
+ } else if (selectedEvent) {
2864
+ onEventUpdate?.({ ...eventData, id: selectedEvent.id });
2428
2865
  } else {
2429
- if (onEventCreate) {
2430
- onEventCreate(eventData);
2431
- }
2432
- }
2433
- };
2434
- const handleModalDelete = (eventId) => {
2435
- let effectiveEventId = eventId;
2436
- if (selectedEvent?.originalEventId && selectedEvent.id === eventId) {
2437
- effectiveEventId = selectedEvent.originalEventId;
2866
+ onEventCreate?.(
2867
+ modalInitialResourceId && eventData.resourceId === void 0 ? { ...eventData, resourceId: modalInitialResourceId } : eventData
2868
+ );
2438
2869
  }
2439
- if (onEventDelete) {
2440
- onEventDelete(effectiveEventId);
2870
+ });
2871
+ const handleEventDelete = useStableCallback((event) => {
2872
+ if (!event.originalEventId) {
2873
+ onEventDelete?.(event.id);
2874
+ return;
2441
2875
  }
2442
- };
2443
- const handleDragEnd = (event) => {
2444
- const { active, over } = event;
2445
- if (!over) return;
2446
- const activeEvent = active.data.current?.event;
2447
- const overDate = over.data.current?.date;
2448
- if (!activeEvent || !overDate) return;
2449
- const originalStart = new Date(activeEvent.start);
2450
- const originalEnd = new Date(activeEvent.end);
2451
- const duration = differenceInMilliseconds(originalEnd, originalStart);
2452
- let newStart;
2453
- if (view === "month") {
2454
- if (timezone) {
2455
- const zonedOriginal = toZonedTime(originalStart, timezone);
2456
- const zonedNew = new Date(overDate);
2457
- zonedNew.setHours(zonedOriginal.getHours());
2458
- zonedNew.setMinutes(zonedOriginal.getMinutes());
2459
- zonedNew.setSeconds(zonedOriginal.getSeconds());
2460
- zonedNew.setMilliseconds(zonedOriginal.getMilliseconds());
2461
- newStart = fromZonedTime(zonedNew, timezone);
2462
- } else {
2463
- newStart = new Date(overDate);
2464
- newStart.setHours(originalStart.getHours());
2465
- newStart.setMinutes(originalStart.getMinutes());
2466
- newStart.setSeconds(originalStart.getSeconds());
2467
- newStart.setMilliseconds(originalStart.getMilliseconds());
2468
- }
2876
+ const master = masterOf(event);
2877
+ if (onOccurrenceDelete && master) {
2878
+ onOccurrenceDelete(event, excludeOccurrence(master, event.occurrenceStart ?? event.start));
2469
2879
  } else {
2470
- if (timezone) {
2471
- newStart = fromZonedTime(overDate, timezone);
2472
- } else {
2473
- newStart = new Date(overDate);
2474
- }
2475
- newStart.setSeconds(0);
2476
- newStart.setMilliseconds(0);
2477
- }
2478
- const newEnd = new Date(newStart.getTime() + duration);
2479
- let newResourceId = activeEvent.resourceId;
2480
- const overResourceId = over.data.current?.resourceId;
2481
- if (overResourceId) {
2482
- newResourceId = overResourceId;
2483
- }
2484
- if (newStart.getTime() === originalStart.getTime() && newEnd.getTime() === originalEnd.getTime() && newResourceId === activeEvent.resourceId) {
2485
- return;
2880
+ onEventDelete?.(event.originalEventId);
2486
2881
  }
2487
- if (onEventUpdate) {
2488
- onEventUpdate({
2489
- ...activeEvent,
2490
- start: newStart,
2491
- end: newEnd,
2492
- resourceId: newResourceId
2493
- });
2882
+ });
2883
+ const handleModalDelete = useStableCallback((eventId) => {
2884
+ if (selectedEvent && selectedEvent.id === eventId) {
2885
+ handleEventDelete(selectedEvent);
2886
+ } else {
2887
+ onEventDelete?.(eventId);
2494
2888
  }
2889
+ });
2890
+ const handleEventDuplicate = useStableCallback((event) => {
2891
+ const { recurrence: _recurrence, ...copy } = stripOccurrenceFields(event);
2892
+ onEventCreate?.({
2893
+ ...copy,
2894
+ id: `${event.originalEventId ?? event.id}-copy-${Date.now()}`,
2895
+ title: `${event.title} (Copy)`,
2896
+ start: new Date(event.start.getTime() + DAY_MS2),
2897
+ end: new Date(event.end.getTime() + DAY_MS2)
2898
+ });
2899
+ });
2900
+ const applyChange = (event, start, end) => {
2901
+ if (!event.originalEventId) return { original: event, updated: { ...event, start, end } };
2902
+ const master = masterOf(event);
2903
+ if (!master) return null;
2904
+ return { original: master, updated: shiftSeries(master, event, start, end, timezone) };
2495
2905
  };
2906
+ const handleDragEnd = useStableCallback((dragEvent) => {
2907
+ const { active, over } = dragEvent;
2908
+ if (!over) return;
2909
+ const dragged = active.data.current?.event;
2910
+ const overDate = over.data.current?.date;
2911
+ if (!dragged || !overDate) return;
2912
+ const drop = computeDrop({
2913
+ event: dragged,
2914
+ overDate,
2915
+ overResourceId: over.data.current?.resourceId,
2916
+ grabOffsetMs: active.data.current?.grabOffsetMs,
2917
+ view,
2918
+ tz: timezone
2919
+ });
2920
+ if (!drop) return;
2921
+ const change = applyChange(dragged, drop.start, drop.end);
2922
+ if (!change) return;
2923
+ const updated = { ...change.updated, resourceId: drop.resourceId };
2924
+ onEventDrop?.(change.original, updated.start, updated.end);
2925
+ onEventUpdate?.(updated);
2926
+ });
2927
+ const handleEventResize = useStableCallback((event, newEnd) => {
2928
+ if (readOnly) return;
2929
+ const change = applyChange(event, event.start, newEnd);
2930
+ if (!change) return;
2931
+ onEventResize?.(change.original, change.updated.start, change.updated.end);
2932
+ onEventUpdate?.(change.updated);
2933
+ });
2496
2934
  return {
2497
2935
  view,
2498
2936
  currentDate,
@@ -2514,9 +2952,18 @@ var useCalendarLogic = ({
2514
2952
  handleCreateEvent,
2515
2953
  handleModalSave,
2516
2954
  handleModalDelete,
2955
+ handleEventDelete,
2956
+ handleEventDuplicate,
2957
+ handleEventResize,
2517
2958
  handleDragEnd
2518
2959
  };
2519
2960
  };
2961
+
2962
+ // src/index.tsx
2963
+ import { differenceInMinutes as differenceInMinutes6, format as format14 } from "date-fns";
2964
+
2965
+ // src/hooks/useSwipeGesture.ts
2966
+ import { useRef as useRef6, useCallback as useCallback4, useEffect as useEffect5 } from "react";
2520
2967
  var useSwipeGesture = (options) => {
2521
2968
  const {
2522
2969
  onSwipeLeft,
@@ -2528,9 +2975,9 @@ var useSwipeGesture = (options) => {
2528
2975
  allowedTime = 500,
2529
2976
  enabled = true
2530
2977
  } = options;
2531
- const touchInfoRef = useRef(null);
2532
- const elementRef = useRef(null);
2533
- const handleTouchStart = useCallback((e) => {
2978
+ const touchInfoRef = useRef6(null);
2979
+ const elementRef = useRef6(null);
2980
+ const handleTouchStart = useCallback4((e) => {
2534
2981
  if (!enabled) return;
2535
2982
  const touch = e.touches[0];
2536
2983
  touchInfoRef.current = {
@@ -2539,7 +2986,7 @@ var useSwipeGesture = (options) => {
2539
2986
  startTime: Date.now()
2540
2987
  };
2541
2988
  }, [enabled]);
2542
- const handleTouchEnd = useCallback((e) => {
2989
+ const handleTouchEnd = useCallback4((e) => {
2543
2990
  if (!enabled || !touchInfoRef.current) return;
2544
2991
  const touch = e.changedTouches[0];
2545
2992
  const { startX, startY, startTime } = touchInfoRef.current;
@@ -2563,7 +3010,7 @@ var useSwipeGesture = (options) => {
2563
3010
  }
2564
3011
  touchInfoRef.current = null;
2565
3012
  }, [enabled, threshold, restraint, allowedTime, onSwipeLeft, onSwipeRight, onSwipeUp, onSwipeDown]);
2566
- useEffect(() => {
3013
+ useEffect5(() => {
2567
3014
  const element = elementRef.current;
2568
3015
  if (!element) return;
2569
3016
  element.addEventListener("touchstart", handleTouchStart, { passive: true });
@@ -2597,7 +3044,9 @@ var Scheduler = ({
2597
3044
  onEventCreate,
2598
3045
  onEventUpdate,
2599
3046
  onEventDelete,
3047
+ onEventDrop,
2600
3048
  onEventResize,
3049
+ onOccurrenceDelete,
2601
3050
  timezone,
2602
3051
  onTimezoneChange,
2603
3052
  className,
@@ -2619,7 +3068,7 @@ var Scheduler = ({
2619
3068
  locale
2620
3069
  // Date-fns locale
2621
3070
  }) => {
2622
- const [activeDragEvent, setActiveDragEvent] = useState(null);
3071
+ const [activeDragEvent, setActiveDragEvent] = useState6(null);
2623
3072
  const {
2624
3073
  contextMenuEvent,
2625
3074
  contextMenuPosition,
@@ -2645,9 +3094,11 @@ var Scheduler = ({
2645
3094
  handleCreateEvent,
2646
3095
  handleModalSave,
2647
3096
  handleModalDelete,
3097
+ handleEventDelete,
3098
+ handleEventDuplicate,
3099
+ handleEventResize,
2648
3100
  handleDragEnd,
2649
3101
  expandedEvents
2650
- // New export
2651
3102
  } = useCalendarLogic({
2652
3103
  events,
2653
3104
  view: controlledView,
@@ -2658,6 +3109,9 @@ var Scheduler = ({
2658
3109
  onEventUpdate,
2659
3110
  onEventCreate,
2660
3111
  onEventDelete,
3112
+ onEventDrop,
3113
+ onEventResize,
3114
+ onOccurrenceDelete,
2661
3115
  readOnly,
2662
3116
  timezone
2663
3117
  });
@@ -2672,57 +3126,40 @@ var Scheduler = ({
2672
3126
  const snapToGrid = createSnapModifier(gridSize);
2673
3127
  const modifiers = [snapToGrid, restrictToWindowEdges];
2674
3128
  const dndSensors = readOnly ? [] : sensors;
2675
- const handleEventResize = (event, newEnd) => {
2676
- if (readOnly) return;
2677
- if (onEventResize) {
2678
- onEventResize(event, event.start, newEnd);
2679
- }
2680
- if (onEventUpdate) {
2681
- onEventUpdate({
2682
- ...event,
2683
- end: newEnd
2684
- });
2685
- }
2686
- };
2687
3129
  const id = useId();
2688
3130
  const swipeRef = useViewSwipe(handlePrev, handleNext, true);
2689
- const languagePack = language === "fr" ? fr : en;
2690
- const t = {
2691
- ...languagePack,
2692
- ...translations
2693
- };
2694
- const overlayTimeFormat = uses24HourClock(locale) ? "H:mm" : "h:mm a";
2695
- const handleDragStart = (event) => {
2696
- const { active } = event;
2697
- const draggedEvent = expandedEvents.find((e) => e.id === active.id);
3131
+ const t = useMemo4(() => resolveTranslations(language, translations), [language, translations]);
3132
+ const overlayTimeFormat = timeFormats(locale).time;
3133
+ const handleDragStart = useCallback5((event) => {
3134
+ const draggedEvent = event.active.data.current?.event;
2698
3135
  if (draggedEvent) {
2699
3136
  setActiveDragEvent(draggedEvent);
2700
3137
  }
2701
- };
2702
- const onDragEndWrapper = (event) => {
3138
+ }, []);
3139
+ const onDragEndWrapper = useCallback5((event) => {
2703
3140
  setActiveDragEvent(null);
2704
3141
  handleDragEnd(event);
2705
- };
3142
+ }, [handleDragEnd]);
2706
3143
  const getDragHeight = () => {
2707
3144
  if (!activeDragEvent) return void 0;
2708
3145
  if (view === "resource") {
2709
3146
  return 80;
2710
3147
  }
2711
3148
  if (view !== "week" && view !== "day") return void 0;
2712
- const duration = differenceInMinutes(activeDragEvent.end, activeDragEvent.start);
3149
+ const duration = differenceInMinutes6(activeDragEvent.end, activeDragEvent.start);
2713
3150
  const hourHeight = view === "day" ? 80 : 60;
2714
3151
  return duration / 60 * hourHeight;
2715
3152
  };
2716
3153
  const getDragWidth = () => {
2717
3154
  if (view === "month") return "100%";
2718
3155
  if (view === "resource" && activeDragEvent) {
2719
- const duration = differenceInMinutes(activeDragEvent.end, activeDragEvent.start);
3156
+ const duration = differenceInMinutes6(activeDragEvent.end, activeDragEvent.start);
2720
3157
  const width = duration / 60 * 100;
2721
3158
  return `${Math.max(width, 4)}px`;
2722
3159
  }
2723
3160
  return "150px";
2724
3161
  };
2725
- const filteredEvents = useMemo(() => {
3162
+ const filteredEvents = useMemo4(() => {
2726
3163
  if (!calendars) return expandedEvents;
2727
3164
  const activeCalendarIds = calendars.filter((c) => c.active !== false).map((c) => c.id);
2728
3165
  return expandedEvents.filter((e) => {
@@ -2730,7 +3167,7 @@ var Scheduler = ({
2730
3167
  return activeCalendarIds.includes(e.calendarId);
2731
3168
  });
2732
3169
  }, [expandedEvents, calendars]);
2733
- return /* @__PURE__ */ React15__default.createElement(
3170
+ return /* @__PURE__ */ React18.createElement(
2734
3171
  DndContext,
2735
3172
  {
2736
3173
  id,
@@ -2739,13 +3176,13 @@ var Scheduler = ({
2739
3176
  onDragEnd: onDragEndWrapper,
2740
3177
  modifiers
2741
3178
  },
2742
- /* @__PURE__ */ React15__default.createElement(
3179
+ /* @__PURE__ */ React18.createElement(
2743
3180
  "div",
2744
3181
  {
2745
3182
  className: cn("flex flex-col h-full bg-background text-foreground relative", className),
2746
3183
  style: getThemeStyles(theme)
2747
3184
  },
2748
- /* @__PURE__ */ React15__default.createElement(
3185
+ /* @__PURE__ */ React18.createElement(
2749
3186
  CalendarHeader,
2750
3187
  {
2751
3188
  currentDate,
@@ -2764,8 +3201,8 @@ var Scheduler = ({
2764
3201
  locale
2765
3202
  }
2766
3203
  ),
2767
- /* @__PURE__ */ React15__default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React15__default.createElement(
2768
- motion.div,
3204
+ /* @__PURE__ */ React18.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React18.createElement(
3205
+ motion4.div,
2769
3206
  {
2770
3207
  className: cn(
2771
3208
  "hidden md:block overflow-hidden"
@@ -2780,7 +3217,7 @@ var Scheduler = ({
2780
3217
  ease: [0.4, 0, 0.2, 1]
2781
3218
  }
2782
3219
  },
2783
- /* @__PURE__ */ React15__default.createElement(
3220
+ /* @__PURE__ */ React18.createElement(
2784
3221
  Sidebar,
2785
3222
  {
2786
3223
  currentDate,
@@ -2797,8 +3234,8 @@ var Scheduler = ({
2797
3234
  locale
2798
3235
  }
2799
3236
  )
2800
- ), /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 flex flex-col overflow-hidden relative" }, isLoading ? /* @__PURE__ */ React15__default.createElement("div", { className: "flex-1 overflow-auto p-0 md:p-4" }, /* @__PURE__ */ React15__default.createElement("div", { className: "h-full min-w-full" }, view === "month" && /* @__PURE__ */ React15__default.createElement(MonthViewSkeleton, null), view === "week" && /* @__PURE__ */ React15__default.createElement(WeekViewSkeleton, null), view === "day" && /* @__PURE__ */ React15__default.createElement(DayViewSkeleton, null), view === "agenda" && /* @__PURE__ */ React15__default.createElement(AgendaViewSkeleton, null), view === "resource" && /* @__PURE__ */ React15__default.createElement(WeekViewSkeleton, null))) : /* @__PURE__ */ React15__default.createElement("div", { ref: swipeRef, className: "flex-1 overflow-auto p-0 md:p-4 touch-pan-y" }, /* @__PURE__ */ React15__default.createElement("div", { className: "h-full min-w-full" }, /* @__PURE__ */ React15__default.createElement(AnimatePresence, { mode: "wait", initial: false }, /* @__PURE__ */ React15__default.createElement(
2801
- motion.div,
3237
+ ), /* @__PURE__ */ React18.createElement("div", { className: "flex-1 flex flex-col overflow-hidden relative" }, isLoading ? /* @__PURE__ */ React18.createElement("div", { className: "flex-1 overflow-auto p-0 md:p-4" }, /* @__PURE__ */ React18.createElement("div", { className: "h-full min-w-full" }, view === "month" && /* @__PURE__ */ React18.createElement(MonthViewSkeleton, null), view === "week" && /* @__PURE__ */ React18.createElement(WeekViewSkeleton, null), view === "day" && /* @__PURE__ */ React18.createElement(DayViewSkeleton, null), view === "agenda" && /* @__PURE__ */ React18.createElement(AgendaViewSkeleton, null), view === "resource" && /* @__PURE__ */ React18.createElement(WeekViewSkeleton, null))) : /* @__PURE__ */ React18.createElement("div", { ref: swipeRef, className: "flex-1 overflow-auto p-0 md:p-4 touch-pan-y" }, /* @__PURE__ */ React18.createElement("div", { className: "h-full min-w-full" }, /* @__PURE__ */ React18.createElement(AnimatePresence3, { mode: "wait", initial: false }, /* @__PURE__ */ React18.createElement(
3238
+ motion4.div,
2802
3239
  {
2803
3240
  key: `${view}-${currentDate.toISOString()}-${timezone || "local"}`,
2804
3241
  initial: { opacity: 0, scale: 0.98, y: 15 },
@@ -2822,7 +3259,7 @@ var Scheduler = ({
2822
3259
  },
2823
3260
  className: "h-full"
2824
3261
  },
2825
- view === "month" && /* @__PURE__ */ React15__default.createElement(
3262
+ view === "month" && /* @__PURE__ */ React18.createElement(
2826
3263
  MonthView,
2827
3264
  {
2828
3265
  currentDate,
@@ -2833,7 +3270,7 @@ var Scheduler = ({
2833
3270
  locale
2834
3271
  }
2835
3272
  ),
2836
- view === "week" && /* @__PURE__ */ React15__default.createElement(
3273
+ view === "week" && /* @__PURE__ */ React18.createElement(
2837
3274
  WeekView,
2838
3275
  {
2839
3276
  currentDate,
@@ -2846,7 +3283,7 @@ var Scheduler = ({
2846
3283
  readonly: readOnly
2847
3284
  }
2848
3285
  ),
2849
- view === "day" && /* @__PURE__ */ React15__default.createElement(
3286
+ view === "day" && /* @__PURE__ */ React18.createElement(
2850
3287
  DayView,
2851
3288
  {
2852
3289
  currentDate,
@@ -2859,7 +3296,7 @@ var Scheduler = ({
2859
3296
  readonly: readOnly
2860
3297
  }
2861
3298
  ),
2862
- view === "agenda" && /* @__PURE__ */ React15__default.createElement(
3299
+ view === "agenda" && /* @__PURE__ */ React18.createElement(
2863
3300
  AgendaView,
2864
3301
  {
2865
3302
  currentDate,
@@ -2867,30 +3304,29 @@ var Scheduler = ({
2867
3304
  onEventClick: handleEventClickInternal,
2868
3305
  onCreateEvent: handleCreateEvent,
2869
3306
  locale,
2870
- translations: t
3307
+ translations: t,
3308
+ timezone
2871
3309
  }
2872
3310
  ),
2873
- view === "resource" && resources && /* @__PURE__ */ React15__default.createElement(
3311
+ view === "resource" && resources && /* @__PURE__ */ React18.createElement(
2874
3312
  ResourceView,
2875
3313
  {
2876
3314
  currentDate,
2877
3315
  events: filteredEvents,
2878
3316
  resources,
2879
3317
  onEventClick: handleEventClickInternal,
2880
- onTimeSlotClick: (date, resourceId) => {
2881
- if (readOnly) return;
2882
- handleTimeSlotClick(date);
2883
- },
2884
- locale
3318
+ onTimeSlotClick: handleTimeSlotClick,
3319
+ locale,
3320
+ timezone
2885
3321
  }
2886
3322
  )
2887
- )))), /* @__PURE__ */ React15__default.createElement("div", { className: "md:hidden absolute bottom-6 right-6 z-50" }, /* @__PURE__ */ React15__default.createElement(
3323
+ )))), /* @__PURE__ */ React18.createElement("div", { className: "md:hidden absolute bottom-6 right-6 z-50" }, /* @__PURE__ */ React18.createElement(
2888
3324
  "button",
2889
3325
  {
2890
3326
  onClick: handleCreateEvent,
2891
3327
  className: "w-14 h-14 bg-blue-600 rounded-full shadow-lg flex items-center justify-center text-white active:scale-90 transition-transform"
2892
3328
  },
2893
- /* @__PURE__ */ React15__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__ */ React15__default.createElement("path", { d: "M5 12h14" }), /* @__PURE__ */ React15__default.createElement("path", { d: "M12 5v14" }))
3329
+ /* @__PURE__ */ React18.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React18.createElement("path", { d: "M5 12h14" }), /* @__PURE__ */ React18.createElement("path", { d: "M12 5v14" }))
2894
3330
  )))),
2895
3331
  renderEventForm ? renderEventForm({
2896
3332
  isOpen: isModalOpen,
@@ -2899,7 +3335,7 @@ var Scheduler = ({
2899
3335
  initialDate: modalInitialDate,
2900
3336
  onSave: handleModalSave,
2901
3337
  onDelete: handleModalDelete
2902
- }) : /* @__PURE__ */ React15__default.createElement(
3338
+ }) : /* @__PURE__ */ React18.createElement(
2903
3339
  EventModal,
2904
3340
  {
2905
3341
  isOpen: isModalOpen,
@@ -2913,7 +3349,7 @@ var Scheduler = ({
2913
3349
  translations: t
2914
3350
  }
2915
3351
  ),
2916
- /* @__PURE__ */ React15__default.createElement(
3352
+ /* @__PURE__ */ React18.createElement(
2917
3353
  EventContextMenu,
2918
3354
  {
2919
3355
  event: contextMenuEvent,
@@ -2923,20 +3359,12 @@ var Scheduler = ({
2923
3359
  handleEventClickInternal(event);
2924
3360
  closeContextMenu();
2925
3361
  },
2926
- onDelete: (eventId) => {
2927
- onEventDelete?.(eventId);
3362
+ onDelete: () => {
3363
+ if (contextMenuEvent) handleEventDelete(contextMenuEvent);
2928
3364
  closeContextMenu();
2929
3365
  },
2930
3366
  onDuplicate: (event) => {
2931
- const duplicatedEvent = {
2932
- ...event,
2933
- id: `${event.id}-copy-${Date.now()}`,
2934
- title: `${event.title} (Copy)`,
2935
- start: new Date(event.start.getTime() + 24 * 60 * 60 * 1e3),
2936
- // +1 day
2937
- end: new Date(event.end.getTime() + 24 * 60 * 60 * 1e3)
2938
- };
2939
- onEventCreate?.(duplicatedEvent);
3367
+ handleEventDuplicate(event);
2940
3368
  closeContextMenu();
2941
3369
  },
2942
3370
  translations: {
@@ -2946,7 +3374,7 @@ var Scheduler = ({
2946
3374
  }
2947
3375
  }
2948
3376
  ),
2949
- /* @__PURE__ */ React15__default.createElement(DragOverlay, { dropAnimation: null }, activeDragEvent ? /* @__PURE__ */ React15__default.createElement(
3377
+ /* @__PURE__ */ React18.createElement(DragOverlay, { dropAnimation: null }, activeDragEvent ? /* @__PURE__ */ React18.createElement(
2950
3378
  "div",
2951
3379
  {
2952
3380
  className: cn(
@@ -2964,18 +3392,18 @@ var Scheduler = ({
2964
3392
  transform: "rotate(-2deg) scale(1.02)"
2965
3393
  }
2966
3394
  },
2967
- /* @__PURE__ */ React15__default.createElement("div", { className: "p-2.5 h-full flex flex-col" }, /* @__PURE__ */ React15__default.createElement(
3395
+ /* @__PURE__ */ React18.createElement("div", { className: "p-2.5 h-full flex flex-col" }, /* @__PURE__ */ React18.createElement(
2968
3396
  "div",
2969
3397
  {
2970
3398
  className: "absolute left-0 top-0 bottom-0 w-1 rounded-l-lg",
2971
3399
  style: { backgroundColor: activeDragEvent.color || "var(--primary)" }
2972
3400
  }
2973
- ), /* @__PURE__ */ React15__default.createElement("div", { className: "pl-2" }, /* @__PURE__ */ React15__default.createElement("div", { className: "font-semibold truncate text-sm" }, activeDragEvent.title), (view === "week" || view === "day") && getDragHeight() && getDragHeight() > 40 && /* @__PURE__ */ React15__default.createElement("div", { className: "text-xs opacity-80 mt-0.5 flex items-center gap-1" }, /* @__PURE__ */ React15__default.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ React15__default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React15__default.createElement("path", { d: "M12 6v6l4 2" })), format(activeDragEvent.start, overlayTimeFormat, { locale }), " - ", format(activeDragEvent.end, overlayTimeFormat, { locale }))), /* @__PURE__ */ React15__default.createElement("div", { className: "absolute bottom-1.5 right-1.5 opacity-60" }, /* @__PURE__ */ React15__default.createElement("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React15__default.createElement("circle", { cx: "9", cy: "5", r: "1.5" }), /* @__PURE__ */ React15__default.createElement("circle", { cx: "15", cy: "5", r: "1.5" }), /* @__PURE__ */ React15__default.createElement("circle", { cx: "9", cy: "12", r: "1.5" }), /* @__PURE__ */ React15__default.createElement("circle", { cx: "15", cy: "12", r: "1.5" }), /* @__PURE__ */ React15__default.createElement("circle", { cx: "9", cy: "19", r: "1.5" }), /* @__PURE__ */ React15__default.createElement("circle", { cx: "15", cy: "19", r: "1.5" }))))
3401
+ ), /* @__PURE__ */ React18.createElement("div", { className: "pl-2" }, /* @__PURE__ */ React18.createElement("div", { className: "font-semibold truncate text-sm" }, activeDragEvent.title), (view === "week" || view === "day") && getDragHeight() && getDragHeight() > 40 && /* @__PURE__ */ React18.createElement("div", { className: "text-xs opacity-80 mt-0.5 flex items-center gap-1" }, /* @__PURE__ */ React18.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ React18.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React18.createElement("path", { d: "M12 6v6l4 2" })), format14(activeDragEvent.start, overlayTimeFormat, { locale }), " - ", format14(activeDragEvent.end, overlayTimeFormat, { locale }))), /* @__PURE__ */ React18.createElement("div", { className: "absolute bottom-1.5 right-1.5 opacity-60" }, /* @__PURE__ */ React18.createElement("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React18.createElement("circle", { cx: "9", cy: "5", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "15", cy: "5", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "9", cy: "12", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "15", cy: "12", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "9", cy: "19", r: "1.5" }), /* @__PURE__ */ React18.createElement("circle", { cx: "15", cy: "19", r: "1.5" }))))
2974
3402
  ) : null)
2975
3403
  )
2976
3404
  );
2977
3405
  };
2978
-
2979
- export { Scheduler, cn };
2980
- //# sourceMappingURL=index.mjs.map
2981
- //# sourceMappingURL=index.mjs.map
3406
+ export {
3407
+ Scheduler,
3408
+ cn
3409
+ };