beautify-event 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2165 @@
1
+ 'use strict';
2
+
3
+ var React2 = require('react');
4
+ var clsx = require('clsx');
5
+ var tailwindMerge = require('tailwind-merge');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var lucideReact = require('lucide-react');
8
+ var core = require('@dnd-kit/core');
9
+ var dateFns = require('date-fns');
10
+ var locale = require('date-fns/locale');
11
+ var reactSlot = require('@radix-ui/react-slot');
12
+ var classVarianceAuthority = require('class-variance-authority');
13
+ var ToggleGroupPrimitive = require('@radix-ui/react-toggle-group');
14
+ require('@radix-ui/react-toggle');
15
+
16
+ function _interopNamespace(e) {
17
+ if (e && e.__esModule) return e;
18
+ var n = Object.create(null);
19
+ if (e) {
20
+ Object.keys(e).forEach(function (k) {
21
+ if (k !== 'default') {
22
+ var d = Object.getOwnPropertyDescriptor(e, k);
23
+ Object.defineProperty(n, k, d.get ? d : {
24
+ enumerable: true,
25
+ get: function () { return e[k]; }
26
+ });
27
+ }
28
+ });
29
+ }
30
+ n.default = e;
31
+ return Object.freeze(n);
32
+ }
33
+
34
+ var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
35
+ var ToggleGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(ToggleGroupPrimitive);
36
+
37
+ var __defProp = Object.defineProperty;
38
+ var __defProps = Object.defineProperties;
39
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
40
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
41
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
42
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
43
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
44
+ var __spreadValues = (a, b) => {
45
+ for (var prop in b || (b = {}))
46
+ if (__hasOwnProp.call(b, prop))
47
+ __defNormalProp(a, prop, b[prop]);
48
+ if (__getOwnPropSymbols)
49
+ for (var prop of __getOwnPropSymbols(b)) {
50
+ if (__propIsEnum.call(b, prop))
51
+ __defNormalProp(a, prop, b[prop]);
52
+ }
53
+ return a;
54
+ };
55
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
56
+ var __objRest = (source, exclude) => {
57
+ var target = {};
58
+ for (var prop in source)
59
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
60
+ target[prop] = source[prop];
61
+ if (source != null && __getOwnPropSymbols)
62
+ for (var prop of __getOwnPropSymbols(source)) {
63
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
64
+ target[prop] = source[prop];
65
+ }
66
+ return target;
67
+ };
68
+ function cn(...inputs) {
69
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
70
+ }
71
+ function Card(_a) {
72
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
73
+ return /* @__PURE__ */ jsxRuntime.jsx(
74
+ "div",
75
+ __spreadValues({
76
+ "data-slot": "card",
77
+ className: cn(
78
+ "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
79
+ className
80
+ )
81
+ }, props)
82
+ );
83
+ }
84
+ function Spinner(_a) {
85
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
86
+ return /* @__PURE__ */ jsxRuntime.jsx(
87
+ lucideReact.Loader2Icon,
88
+ __spreadValues({
89
+ role: "status",
90
+ "aria-label": "Loading",
91
+ className: cn("size-4 animate-spin", className)
92
+ }, props)
93
+ );
94
+ }
95
+ function useSystemTheme() {
96
+ const [systemTheme, setSystemTheme] = React2__namespace.useState("light");
97
+ React2__namespace.useEffect(() => {
98
+ const mq = window.matchMedia("(prefers-color-scheme: dark)");
99
+ const handler = () => setSystemTheme(mq.matches ? "dark" : "light");
100
+ handler();
101
+ mq.addEventListener("change", handler);
102
+ return () => mq.removeEventListener("change", handler);
103
+ }, []);
104
+ return systemTheme;
105
+ }
106
+ function normalizeThemeVars(vars) {
107
+ if (!vars || Object.keys(vars).length === 0) return {};
108
+ return Object.fromEntries(
109
+ Object.entries(vars).map(([key, value]) => [
110
+ key.startsWith("--") ? key : `--${key}`,
111
+ value
112
+ ])
113
+ );
114
+ }
115
+ function EventCalendarThemeProvider({
116
+ theme = "system",
117
+ themeVars,
118
+ children
119
+ }) {
120
+ const systemTheme = useSystemTheme();
121
+ const resolvedTheme = theme === "system" ? systemTheme : theme;
122
+ const isDark = resolvedTheme === "dark";
123
+ const customStyle = normalizeThemeVars(themeVars);
124
+ return /* @__PURE__ */ jsxRuntime.jsx(
125
+ "div",
126
+ {
127
+ className: `event-calendar-root ${isDark ? "dark" : ""}`,
128
+ "data-event-calendar-theme": resolvedTheme,
129
+ style: customStyle,
130
+ children
131
+ }
132
+ );
133
+ }
134
+ var LOCALE_MAP = {
135
+ en: locale.enUS,
136
+ "en-US": locale.enUS,
137
+ fr: locale.fr,
138
+ ar: locale.ar
139
+ };
140
+ function getDateFnsLocale(localeCode) {
141
+ var _a;
142
+ return (_a = LOCALE_MAP[localeCode]) != null ? _a : locale.enUS;
143
+ }
144
+ function formatDate(date, formatStr, localeCode = "en-US") {
145
+ const locale = getDateFnsLocale(localeCode);
146
+ return dateFns.format(date, formatStr, { locale });
147
+ }
148
+ function getMonthDays(date, weekStartsOn = 0) {
149
+ const start = dateFns.startOfWeek(dateFns.startOfMonth(date), { weekStartsOn });
150
+ const end = dateFns.endOfWeek(dateFns.endOfMonth(date), { weekStartsOn });
151
+ return dateFns.eachDayOfInterval({ start, end });
152
+ }
153
+ function getWeekDays(date, weekStartsOn = 0) {
154
+ const start = dateFns.startOfWeek(date, { weekStartsOn });
155
+ const end = dateFns.endOfWeek(date, { weekStartsOn });
156
+ return dateFns.eachDayOfInterval({ start, end });
157
+ }
158
+ function getTwoDays(date, _weekStartsOn = 0) {
159
+ const start = dateFns.startOfDay(date);
160
+ return [start, dateFns.addDays(start, 1)];
161
+ }
162
+ function getEventsForDay(events, day) {
163
+ return events.filter((event) => {
164
+ const eventStart = dateFns.startOfDay(event.start);
165
+ const eventEnd = dateFns.endOfDay(event.end);
166
+ return dateFns.isWithinInterval(day, { start: eventStart, end: eventEnd }) || dateFns.isSameDay(event.start, day) || dateFns.isSameDay(event.end, day);
167
+ });
168
+ }
169
+ function navigateDate(date, view, direction) {
170
+ switch (view) {
171
+ case "month":
172
+ return direction === "next" ? dateFns.addMonths(date, 1) : dateFns.subMonths(date, 1);
173
+ case "week":
174
+ case "resource":
175
+ return direction === "next" ? dateFns.addWeeks(date, 1) : dateFns.subWeeks(date, 1);
176
+ case "day":
177
+ return direction === "next" ? dateFns.addDays(date, 1) : dateFns.subDays(date, 1);
178
+ case "2day":
179
+ return direction === "next" ? dateFns.addDays(date, 2) : dateFns.subDays(date, 2);
180
+ default:
181
+ return date;
182
+ }
183
+ }
184
+ function getViewTitle(date, view, weekStartsOn = 0, localeCode = "en-US") {
185
+ const locale = getDateFnsLocale(localeCode);
186
+ const fmt = (d, str) => dateFns.format(d, str, { locale });
187
+ switch (view) {
188
+ case "month":
189
+ return fmt(date, "MMMM yyyy");
190
+ case "week":
191
+ case "resource": {
192
+ const weekStart = dateFns.startOfWeek(date, { weekStartsOn });
193
+ const weekEnd = dateFns.endOfWeek(date, { weekStartsOn });
194
+ return `${fmt(weekStart, "MMM d")} - ${fmt(weekEnd, "MMM d, yyyy")}`;
195
+ }
196
+ case "day":
197
+ return fmt(date, "EEEE, MMMM d, yyyy");
198
+ case "2day": {
199
+ const days = getTwoDays(date, weekStartsOn);
200
+ return `${fmt(days[0], "MMM d")} \u2013 ${fmt(days[1], "MMM d, yyyy")}`;
201
+ }
202
+ default:
203
+ return fmt(date, "MMMM yyyy");
204
+ }
205
+ }
206
+ function getViewDateRange(date, view, weekStartsOn = 0) {
207
+ switch (view) {
208
+ case "month":
209
+ return {
210
+ start: dateFns.startOfWeek(dateFns.startOfMonth(date), { weekStartsOn }),
211
+ end: dateFns.endOfWeek(dateFns.endOfMonth(date), { weekStartsOn })
212
+ };
213
+ case "week":
214
+ case "resource":
215
+ return {
216
+ start: dateFns.startOfWeek(date, { weekStartsOn }),
217
+ end: dateFns.endOfWeek(date, { weekStartsOn })
218
+ };
219
+ case "day":
220
+ return {
221
+ start: dateFns.startOfDay(date),
222
+ end: dateFns.endOfDay(date)
223
+ };
224
+ case "2day": {
225
+ const days = getTwoDays(date, weekStartsOn);
226
+ return {
227
+ start: dateFns.startOfDay(days[0]),
228
+ end: dateFns.endOfDay(days[1])
229
+ };
230
+ }
231
+ default:
232
+ return {
233
+ start: dateFns.startOfMonth(date),
234
+ end: dateFns.endOfMonth(date)
235
+ };
236
+ }
237
+ }
238
+ function getEventPosition(event, hourHeight = 64, startHour = 0) {
239
+ const eventStartHour = dateFns.getHours(event.start);
240
+ const eventStartMinutes = dateFns.getMinutes(event.start);
241
+ const startMinutes = (eventStartHour - startHour) * 60 + eventStartMinutes;
242
+ const duration = dateFns.differenceInMinutes(event.end, event.start);
243
+ const top = startMinutes / 60 * hourHeight;
244
+ const height = Math.max(duration / 60 * hourHeight, 24);
245
+ return { top: Math.max(top, 0), height };
246
+ }
247
+ function createSlotDate(day, hour, minute = 0) {
248
+ return dateFns.setMinutes(dateFns.setHours(day, hour), minute);
249
+ }
250
+ function getWeekdayNames(weekStartsOn = 0, short = true, localeCode = "en-US") {
251
+ const locale = getDateFnsLocale(localeCode);
252
+ const baseDate = new Date(2024, 0, 7);
253
+ const days = [];
254
+ for (let i = 0; i < 7; i++) {
255
+ const dayIndex = (weekStartsOn + i) % 7;
256
+ const date = dateFns.addDays(baseDate, dayIndex);
257
+ days.push(dateFns.format(date, short ? "EEE" : "EEEE", { locale }));
258
+ }
259
+ return days;
260
+ }
261
+ function getHoursArray(startHour = 0, endHour = 24) {
262
+ const hours = [];
263
+ for (let i = startHour; i < endHour; i++) {
264
+ hours.push(i);
265
+ }
266
+ return hours;
267
+ }
268
+ function getCurrentTimeLineTop(now, startHour, endHour, hourHeight, topPadding = 16) {
269
+ const currentHour = dateFns.getHours(now);
270
+ const currentMinute = dateFns.getMinutes(now);
271
+ const currentTimeInHours = currentHour + currentMinute / 60;
272
+ if (currentTimeInHours < startHour || currentTimeInHours >= endHour) return null;
273
+ const top = topPadding + (currentTimeInHours - startHour) * hourHeight;
274
+ return top;
275
+ }
276
+ function formatHour(hour, timeFormat = "12h", localeCode = "en-US") {
277
+ if (timeFormat === "24h") {
278
+ return `${hour.toString().padStart(2, "0")}:00`;
279
+ }
280
+ const locale = getDateFnsLocale(localeCode);
281
+ const d = new Date(2e3, 0, 1, hour, 0, 0);
282
+ return dateFns.format(d, "h a", { locale });
283
+ }
284
+ var defaultConfig = {
285
+ weekStartsOn: 0,
286
+ startHour: 0,
287
+ // 12:00 AM - full day start
288
+ endHour: 24,
289
+ // 11:59 PM - full day end
290
+ hourHeight: 64,
291
+ timeSeriesMaxHeight: 400,
292
+ showCurrentTimeLine: true,
293
+ maxEventsPerDay: 3,
294
+ defaultEventColor: "#3b82f6",
295
+ defaultResourceColor: "#6366f1",
296
+ locale: "en-US",
297
+ timeFormat: "12h"
298
+ };
299
+
300
+ // components/event-calendar/dnd/helpers.ts
301
+ function slotDataToSlotInfo(data, endHour) {
302
+ switch (data.view) {
303
+ case "day":
304
+ case "week": {
305
+ const start = createSlotDate(data.day, data.hour);
306
+ const end = createSlotDate(data.day, data.hour + 1);
307
+ return { start, end };
308
+ }
309
+ case "month": {
310
+ const start = dateFns.startOfDay(data.day);
311
+ const end = dateFns.endOfDay(data.day);
312
+ return { start, end };
313
+ }
314
+ case "resource": {
315
+ const start = createSlotDate(data.day, data.hour);
316
+ const end = createSlotDate(data.day, data.hour + 1);
317
+ return { start, end, resourceId: data.resourceId };
318
+ }
319
+ }
320
+ }
321
+ function computeCreateSlotInfo(from, to) {
322
+ if (from.view === "month" && to.view === "month") {
323
+ const start = dateFns.startOfDay(to.day);
324
+ const end = dateFns.endOfDay(to.day);
325
+ return { start, end };
326
+ }
327
+ if ((from.view === "day" || from.view === "week") && (to.view === "day" || to.view === "week")) {
328
+ const startDate = from.day.getTime() < to.day.getTime() ? from.day : to.day;
329
+ const endDate = from.day.getTime() < to.day.getTime() ? to.day : from.day;
330
+ const startHour = from.day.getTime() === startDate.getTime() ? from.hour : to.hour;
331
+ const endHour = from.day.getTime() === endDate.getTime() ? from.hour : to.hour;
332
+ const start = createSlotDate(startDate, Math.min(startHour, endHour));
333
+ const end = createSlotDate(endDate, Math.max(startHour, endHour) + 1);
334
+ return { start, end };
335
+ }
336
+ if (from.view === "resource" && to.view === "resource" && from.resourceId === to.resourceId) {
337
+ const startDate = from.day.getTime() < to.day.getTime() ? from.day : to.day;
338
+ const endDate = from.day.getTime() < to.day.getTime() ? to.day : from.day;
339
+ const startHour = from.day.getTime() === startDate.getTime() ? from.hour : to.hour;
340
+ const endHour = from.day.getTime() === endDate.getTime() ? from.hour : to.hour;
341
+ const start = createSlotDate(startDate, Math.min(startHour, endHour));
342
+ const end = createSlotDate(endDate, Math.max(startHour, endHour) + 1);
343
+ return { start, end, resourceId: from.resourceId };
344
+ }
345
+ return slotDataToSlotInfo(to);
346
+ }
347
+ function computeMoveEvent(event, dropData) {
348
+ const duration = dateFns.differenceInMinutes(event.end, event.start);
349
+ switch (dropData.view) {
350
+ case "day":
351
+ case "week": {
352
+ const newStart = createSlotDate(dropData.day, dropData.hour);
353
+ const newEnd = dateFns.addMinutes(newStart, duration);
354
+ return { newStart, newEnd };
355
+ }
356
+ case "month": {
357
+ const newStart = dateFns.setMinutes(
358
+ dateFns.setHours(dropData.day, event.start.getHours()),
359
+ event.start.getMinutes()
360
+ );
361
+ const newEnd = dateFns.addMinutes(newStart, duration);
362
+ return { newStart, newEnd };
363
+ }
364
+ case "resource": {
365
+ const newStart = createSlotDate(dropData.day, dropData.hour);
366
+ const newEnd = dateFns.addMinutes(newStart, duration);
367
+ return { newStart, newEnd, resourceId: dropData.resourceId };
368
+ }
369
+ }
370
+ }
371
+ function CalendarDragOverlay({
372
+ activeEvent,
373
+ activeCreateSlotInfo,
374
+ defaultEventColor,
375
+ locale = "en-US",
376
+ renderEvent
377
+ }) {
378
+ return /* @__PURE__ */ jsxRuntime.jsx(core.DragOverlay, { dropAnimation: null, children: activeEvent ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-border bg-card px-3 py-2 shadow-lg opacity-90", children: renderEvent ? renderEvent(activeEvent, "day") : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
379
+ /* @__PURE__ */ jsxRuntime.jsx(
380
+ "div",
381
+ {
382
+ className: "font-semibold text-sm",
383
+ style: {
384
+ color: activeEvent.color || defaultEventColor
385
+ },
386
+ children: activeEvent.title
387
+ }
388
+ ),
389
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground mt-0.5", children: [
390
+ formatDate(activeEvent.start, "h:mm a", locale),
391
+ " -",
392
+ " ",
393
+ formatDate(activeEvent.end, "h:mm a", locale)
394
+ ] })
395
+ ] }) }) : activeCreateSlotInfo ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-2 border-dashed border-primary/50 bg-primary/10 px-3 py-2 shadow-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-medium text-primary", children: [
396
+ formatDate(activeCreateSlotInfo.start, "h:mm a", locale),
397
+ " -",
398
+ " ",
399
+ formatDate(activeCreateSlotInfo.end, "h:mm a", locale)
400
+ ] }) }) : null });
401
+ }
402
+ function EventCalendarDndProvider({
403
+ enableDragToCreate = false,
404
+ enableDragToMove = false,
405
+ onEventCreate,
406
+ onEventMove,
407
+ defaultEventColor,
408
+ locale = "en-US",
409
+ renderEvent,
410
+ children
411
+ }) {
412
+ const [activeEvent, setActiveEvent] = React2__namespace.useState(null);
413
+ const [activeCreateSlotInfo, setActiveCreateSlotInfo] = React2__namespace.useState(null);
414
+ const handleDragStart = React2__namespace.useCallback(
415
+ (event) => {
416
+ const data = event.active.data.current;
417
+ if (!data) return;
418
+ if (typeof data !== "object" || data === null) return;
419
+ if ("event" in data && data.event) {
420
+ setActiveEvent(data.event);
421
+ } else if ("slotData" in data && data.slotData) {
422
+ const slotData = data.slotData;
423
+ const info = slotDataToSlotInfo(slotData);
424
+ setActiveCreateSlotInfo({ start: info.start, end: info.end });
425
+ }
426
+ },
427
+ []
428
+ );
429
+ const handleDragEnd = React2__namespace.useCallback(
430
+ (event) => {
431
+ var _a;
432
+ const activeData = event.active.data.current;
433
+ const overData = (_a = event.over) == null ? void 0 : _a.data.current;
434
+ setActiveEvent(null);
435
+ setActiveCreateSlotInfo(null);
436
+ if (!overData || typeof overData !== "object") return;
437
+ const overSlot = overData;
438
+ if (activeData && typeof activeData === "object" && "event" in activeData && enableDragToMove && onEventMove) {
439
+ const eventData = activeData.event;
440
+ const { newStart, newEnd, resourceId } = computeMoveEvent(
441
+ eventData,
442
+ overSlot
443
+ );
444
+ onEventMove({ event: eventData, newStart, newEnd, resourceId });
445
+ } else if (activeData && typeof activeData === "object" && "slotData" in activeData && enableDragToCreate && onEventCreate) {
446
+ const fromSlot = activeData.slotData;
447
+ const slotInfo = computeCreateSlotInfo(fromSlot, overSlot);
448
+ onEventCreate(slotInfo);
449
+ }
450
+ },
451
+ [enableDragToCreate, enableDragToMove, onEventCreate, onEventMove]
452
+ );
453
+ return /* @__PURE__ */ jsxRuntime.jsxs(
454
+ core.DndContext,
455
+ {
456
+ onDragStart: handleDragStart,
457
+ onDragEnd: handleDragEnd,
458
+ collisionDetection: core.pointerWithin,
459
+ children: [
460
+ children,
461
+ /* @__PURE__ */ jsxRuntime.jsx(
462
+ CalendarDragOverlay,
463
+ {
464
+ activeEvent,
465
+ activeCreateSlotInfo,
466
+ defaultEventColor,
467
+ locale,
468
+ renderEvent
469
+ }
470
+ )
471
+ ]
472
+ }
473
+ );
474
+ }
475
+ var BREAKPOINTS = {
476
+ sm: 640,
477
+ md: 768,
478
+ lg: 1024
479
+ };
480
+ function useMediaQuery(breakpoint) {
481
+ const query = `(max-width: ${BREAKPOINTS[breakpoint] - 1}px)`;
482
+ const [matches, setMatches] = React2.useState(false);
483
+ React2.useEffect(() => {
484
+ if (typeof window === "undefined") return;
485
+ const media = window.matchMedia(query);
486
+ setMatches(media.matches);
487
+ const listener = (e) => setMatches(e.matches);
488
+ media.addEventListener("change", listener);
489
+ return () => media.removeEventListener("change", listener);
490
+ }, [query]);
491
+ return matches;
492
+ }
493
+ var CalendarContext = React2.createContext(null);
494
+ function useCalendar() {
495
+ const context = React2.useContext(CalendarContext);
496
+ if (!context) {
497
+ throw new Error("useCalendar must be used within an EventCalendar");
498
+ }
499
+ return context;
500
+ }
501
+ function CalendarProvider({
502
+ children,
503
+ value
504
+ }) {
505
+ return /* @__PURE__ */ jsxRuntime.jsx(CalendarContext.Provider, { value, children });
506
+ }
507
+ var buttonVariants = classVarianceAuthority.cva(
508
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
509
+ {
510
+ variants: {
511
+ variant: {
512
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
513
+ outline: "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
514
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
515
+ ghost: "hover:bg-accent hover:text-accent-foreground"
516
+ },
517
+ size: {
518
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
519
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
520
+ icon: "size-9",
521
+ "icon-sm": "size-8"
522
+ }
523
+ },
524
+ defaultVariants: {
525
+ variant: "outline",
526
+ size: "default"
527
+ }
528
+ }
529
+ );
530
+ function Button(_a) {
531
+ var _b = _a, {
532
+ className,
533
+ variant,
534
+ size,
535
+ asChild = false
536
+ } = _b, props = __objRest(_b, [
537
+ "className",
538
+ "variant",
539
+ "size",
540
+ "asChild"
541
+ ]);
542
+ const Comp = asChild ? reactSlot.Slot : "button";
543
+ return /* @__PURE__ */ jsxRuntime.jsx(
544
+ Comp,
545
+ __spreadValues({
546
+ "data-slot": "button",
547
+ className: cn(buttonVariants({ variant, size, className }))
548
+ }, props)
549
+ );
550
+ }
551
+ var toggleVariants = classVarianceAuthority.cva(
552
+ "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] whitespace-nowrap",
553
+ {
554
+ variants: {
555
+ variant: {
556
+ default: "bg-transparent",
557
+ outline: "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground"
558
+ },
559
+ size: {
560
+ default: "h-9 px-2 min-w-9",
561
+ sm: "h-8 px-1.5 min-w-8"
562
+ }
563
+ },
564
+ defaultVariants: {
565
+ variant: "default",
566
+ size: "default"
567
+ }
568
+ }
569
+ );
570
+ var ToggleGroupContext = React2__namespace.createContext({
571
+ size: "default",
572
+ variant: "default"
573
+ });
574
+ function ToggleGroup(_a) {
575
+ var _b = _a, {
576
+ className,
577
+ variant,
578
+ size,
579
+ children
580
+ } = _b, props = __objRest(_b, [
581
+ "className",
582
+ "variant",
583
+ "size",
584
+ "children"
585
+ ]);
586
+ return /* @__PURE__ */ jsxRuntime.jsx(
587
+ ToggleGroupPrimitive__namespace.Root,
588
+ __spreadProps(__spreadValues({
589
+ "data-slot": "toggle-group",
590
+ "data-variant": variant,
591
+ "data-size": size,
592
+ className: cn(
593
+ "group/toggle-group flex w-fit items-center rounded-md data-[variant=outline]:shadow-xs",
594
+ className
595
+ )
596
+ }, props), {
597
+ children: /* @__PURE__ */ jsxRuntime.jsx(ToggleGroupContext.Provider, { value: { variant, size }, children })
598
+ })
599
+ );
600
+ }
601
+ function ToggleGroupItem(_a) {
602
+ var _b = _a, {
603
+ className,
604
+ children,
605
+ variant,
606
+ size
607
+ } = _b, props = __objRest(_b, [
608
+ "className",
609
+ "children",
610
+ "variant",
611
+ "size"
612
+ ]);
613
+ var _a2, _b2, _c, _d;
614
+ const context = React2__namespace.useContext(ToggleGroupContext);
615
+ return /* @__PURE__ */ jsxRuntime.jsx(
616
+ ToggleGroupPrimitive__namespace.Item,
617
+ __spreadProps(__spreadValues({
618
+ "data-slot": "toggle-group-item",
619
+ "data-variant": (_a2 = context.variant) != null ? _a2 : variant,
620
+ "data-size": (_b2 = context.size) != null ? _b2 : size,
621
+ className: cn(
622
+ toggleVariants({
623
+ variant: (_c = context.variant) != null ? _c : variant,
624
+ size: (_d = context.size) != null ? _d : size
625
+ }),
626
+ "min-w-0 flex-1 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l",
627
+ className
628
+ )
629
+ }, props), {
630
+ children
631
+ })
632
+ );
633
+ }
634
+ function MobileWeekStrip({
635
+ selectedDate,
636
+ onDaySelect,
637
+ onPrevWeek,
638
+ onNextWeek,
639
+ weekStartsOn = 0,
640
+ locale = "en-US",
641
+ className
642
+ }) {
643
+ const days = getWeekDays(selectedDate, weekStartsOn);
644
+ const today = /* @__PURE__ */ new Date();
645
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-0.5", className), children: [
646
+ /* @__PURE__ */ jsxRuntime.jsx(
647
+ Button,
648
+ {
649
+ variant: "ghost",
650
+ size: "icon",
651
+ onClick: onPrevWeek,
652
+ className: "h-7 w-7 shrink-0",
653
+ "aria-label": "Previous week",
654
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-4 w-4" })
655
+ }
656
+ ),
657
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 justify-between gap-0 min-w-0 overflow-visible", children: days.map((day) => {
658
+ const isToday = dateFns.isSameDay(day, today);
659
+ const isSelected = dateFns.isSameDay(day, selectedDate);
660
+ return /* @__PURE__ */ jsxRuntime.jsxs(
661
+ "button",
662
+ {
663
+ type: "button",
664
+ onClick: () => onDaySelect(day),
665
+ className: cn(
666
+ "flex flex-col items-center justify-center min-w-[32px] flex-1 py-1 px-0.5 text-[11px] font-medium transition-colors overflow-visible",
667
+ !isToday && !isSelected && "text-muted-foreground hover:text-foreground",
668
+ isToday && !isSelected && "text-primary font-semibold",
669
+ isSelected && "text-primary-foreground font-semibold"
670
+ ),
671
+ children: [
672
+ /* @__PURE__ */ jsxRuntime.jsx(
673
+ "span",
674
+ {
675
+ className: cn(
676
+ "text-[9px] uppercase leading-tight",
677
+ isSelected ? "text-primary-foreground" : "text-inherit opacity-80"
678
+ ),
679
+ children: formatDate(day, "EEE", locale)
680
+ }
681
+ ),
682
+ /* @__PURE__ */ jsxRuntime.jsx(
683
+ "span",
684
+ {
685
+ className: cn(
686
+ "mt-0.5 w-6 h-6 shrink-0 flex items-center justify-center rounded-full text-[11px] font-semibold tabular-nums",
687
+ isSelected && "bg-primary text-primary-foreground",
688
+ isToday && !isSelected && "bg-primary/15 text-primary",
689
+ !isSelected && !isToday && "text-foreground"
690
+ ),
691
+ children: formatDate(day, "d", locale)
692
+ }
693
+ )
694
+ ]
695
+ },
696
+ day.toISOString()
697
+ );
698
+ }) }),
699
+ /* @__PURE__ */ jsxRuntime.jsx(
700
+ Button,
701
+ {
702
+ variant: "ghost",
703
+ size: "icon",
704
+ onClick: onNextWeek,
705
+ className: "h-7 w-7 shrink-0",
706
+ "aria-label": "Next week",
707
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4" })
708
+ }
709
+ )
710
+ ] });
711
+ }
712
+ function MobileMonthPicker({
713
+ selectedDate,
714
+ onDaySelect,
715
+ weekStartsOn = 0,
716
+ locale = "en-US",
717
+ className
718
+ }) {
719
+ const [viewMonth, setViewMonth] = React2.useState(() => dateFns.startOfMonth(selectedDate));
720
+ React2.useEffect(() => {
721
+ setViewMonth((prev) => {
722
+ const target = dateFns.startOfMonth(selectedDate);
723
+ return dateFns.isSameMonth(prev, target) ? prev : target;
724
+ });
725
+ }, [selectedDate]);
726
+ const days = getMonthDays(viewMonth, weekStartsOn);
727
+ const weekdays = getWeekdayNames(weekStartsOn, true, locale);
728
+ const today = /* @__PURE__ */ new Date();
729
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
730
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-1", children: [
731
+ /* @__PURE__ */ jsxRuntime.jsx(
732
+ Button,
733
+ {
734
+ variant: "ghost",
735
+ size: "icon",
736
+ onClick: () => setViewMonth((m) => dateFns.subMonths(m, 1)),
737
+ className: "h-8 w-8 shrink-0",
738
+ "aria-label": "Previous month",
739
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-4 w-4" })
740
+ }
741
+ ),
742
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground", children: formatDate(viewMonth, "MMMM yyyy", locale) }),
743
+ /* @__PURE__ */ jsxRuntime.jsx(
744
+ Button,
745
+ {
746
+ variant: "ghost",
747
+ size: "icon",
748
+ onClick: () => setViewMonth((m) => dateFns.addMonths(m, 1)),
749
+ className: "h-8 w-8 shrink-0",
750
+ "aria-label": "Next month",
751
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4" })
752
+ }
753
+ )
754
+ ] }),
755
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-0.5", children: weekdays.map((day) => /* @__PURE__ */ jsxRuntime.jsx(
756
+ "div",
757
+ {
758
+ className: "py-1 text-center text-[10px] font-medium text-muted-foreground uppercase",
759
+ children: day
760
+ },
761
+ day
762
+ )) }),
763
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-0.5", children: days.map((day) => {
764
+ const isCurrentMonth = dateFns.isSameMonth(day, viewMonth);
765
+ const isToday = dateFns.isSameDay(day, today);
766
+ const isSelected = dateFns.isSameDay(day, selectedDate);
767
+ return /* @__PURE__ */ jsxRuntime.jsx(
768
+ "button",
769
+ {
770
+ type: "button",
771
+ onClick: () => onDaySelect(day),
772
+ className: cn(
773
+ "aspect-square flex items-center justify-center rounded-full text-xs font-medium transition-colors",
774
+ !isCurrentMonth && "text-muted-foreground/50",
775
+ isCurrentMonth && !isToday && !isSelected && "text-foreground hover:bg-muted",
776
+ isToday && !isSelected && "bg-primary/20 text-primary font-semibold",
777
+ isSelected && "bg-primary text-primary-foreground font-semibold"
778
+ ),
779
+ children: formatDate(day, "d", locale)
780
+ },
781
+ day.toISOString()
782
+ );
783
+ }) })
784
+ ] });
785
+ }
786
+ var VIEW_LABELS = {
787
+ month: "Month",
788
+ week: "Week",
789
+ day: "Day",
790
+ "2day": "2 Day",
791
+ resource: "Resource"
792
+ };
793
+ function CalendarHeader({
794
+ currentDate,
795
+ view,
796
+ views,
797
+ title,
798
+ showNavigation = true,
799
+ showViewSwitcher = true,
800
+ showTodayButton = true,
801
+ isMobile = false,
802
+ showMobileMonthPicker = true,
803
+ weekStartsOn = 0,
804
+ locale = "en-US",
805
+ onNavigate,
806
+ onViewChange,
807
+ onToday,
808
+ onDateSelect,
809
+ onWeekNavigate,
810
+ renderHeader
811
+ }) {
812
+ const [monthPickerExpanded, setMonthPickerExpanded] = React2.useState(false);
813
+ if (renderHeader) {
814
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderHeader({
815
+ date: currentDate,
816
+ view,
817
+ views,
818
+ title,
819
+ onNavigate,
820
+ onViewChange,
821
+ onToday
822
+ }) });
823
+ }
824
+ if (isMobile) {
825
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
826
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
827
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-4 w-4 text-primary shrink-0" }),
828
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5 flex-1 min-w-0", children: [
829
+ showMobileMonthPicker && onDateSelect && onWeekNavigate ? /* @__PURE__ */ jsxRuntime.jsx(
830
+ "button",
831
+ {
832
+ type: "button",
833
+ onClick: () => setMonthPickerExpanded((v) => !v),
834
+ className: "text-base font-semibold text-foreground truncate text-left hover:underline",
835
+ children: title
836
+ }
837
+ ) : /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-base font-semibold text-foreground truncate", children: title }),
838
+ showMobileMonthPicker && onDateSelect && onWeekNavigate && /* @__PURE__ */ jsxRuntime.jsx(
839
+ Button,
840
+ {
841
+ variant: "ghost",
842
+ size: "icon",
843
+ onClick: () => setMonthPickerExpanded((v) => !v),
844
+ className: "h-7 w-7 shrink-0",
845
+ "aria-expanded": monthPickerExpanded,
846
+ "aria-label": monthPickerExpanded ? "Collapse month view" : "Expand month view",
847
+ children: monthPickerExpanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "h-4 w-4 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-4 w-4 text-muted-foreground" })
848
+ }
849
+ )
850
+ ] })
851
+ ] }),
852
+ showMobileMonthPicker && onDateSelect && onWeekNavigate && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col overflow-hidden", children: [
853
+ /* @__PURE__ */ jsxRuntime.jsx(
854
+ "div",
855
+ {
856
+ className: cn(
857
+ "flex items-center rounded-lg px-1.5 py-1 bg-muted/30",
858
+ monthPickerExpanded && "rounded-b-none"
859
+ ),
860
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: !monthPickerExpanded && /* @__PURE__ */ jsxRuntime.jsx(
861
+ MobileWeekStrip,
862
+ {
863
+ selectedDate: currentDate,
864
+ onDaySelect: onDateSelect,
865
+ onPrevWeek: () => onWeekNavigate("prev"),
866
+ onNextWeek: () => onWeekNavigate("next"),
867
+ weekStartsOn,
868
+ locale
869
+ }
870
+ ) })
871
+ }
872
+ ),
873
+ /* @__PURE__ */ jsxRuntime.jsx(
874
+ "div",
875
+ {
876
+ className: "overflow-hidden transition-[max-height] duration-300 ease-in-out",
877
+ style: { maxHeight: monthPickerExpanded ? 400 : 0 },
878
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-b-lg bg-muted/30 px-2 pt-1 pb-2 border-t border-border/50", children: /* @__PURE__ */ jsxRuntime.jsx(
879
+ MobileMonthPicker,
880
+ {
881
+ selectedDate: currentDate,
882
+ onDaySelect: onDateSelect,
883
+ weekStartsOn,
884
+ locale
885
+ }
886
+ ) }) })
887
+ }
888
+ )
889
+ ] })
890
+ ] });
891
+ }
892
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between", children: [
893
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
894
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "h-5 w-5 text-primary" }),
895
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-semibold text-foreground", children: title })
896
+ ] }) }),
897
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 sm:gap-4", children: [
898
+ showNavigation && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
899
+ /* @__PURE__ */ jsxRuntime.jsxs(
900
+ Button,
901
+ {
902
+ variant: "outline",
903
+ size: "icon",
904
+ onClick: () => onNavigate("prev"),
905
+ className: "h-8 w-8",
906
+ children: [
907
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-4 w-4" }),
908
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Previous" })
909
+ ]
910
+ }
911
+ ),
912
+ showTodayButton && /* @__PURE__ */ jsxRuntime.jsx(
913
+ Button,
914
+ {
915
+ variant: "outline",
916
+ size: "sm",
917
+ onClick: onToday,
918
+ className: "h-8 px-3 text-xs font-medium",
919
+ children: "Today"
920
+ }
921
+ ),
922
+ /* @__PURE__ */ jsxRuntime.jsxs(
923
+ Button,
924
+ {
925
+ variant: "outline",
926
+ size: "icon",
927
+ onClick: () => onNavigate("next"),
928
+ className: "h-8 w-8",
929
+ children: [
930
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4" }),
931
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Next" })
932
+ ]
933
+ }
934
+ )
935
+ ] }),
936
+ showViewSwitcher && views.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
937
+ ToggleGroup,
938
+ {
939
+ type: "single",
940
+ value: view,
941
+ onValueChange: (value) => value && onViewChange(value),
942
+ className: "border border-border rounded-lg p-0.5",
943
+ children: views.map((v) => /* @__PURE__ */ jsxRuntime.jsx(
944
+ ToggleGroupItem,
945
+ {
946
+ value: v,
947
+ className: "h-7 px-3 text-xs data-[state=on]:bg-primary data-[state=on]:text-primary-foreground",
948
+ children: VIEW_LABELS[v]
949
+ },
950
+ v
951
+ ))
952
+ }
953
+ )
954
+ ] })
955
+ ] });
956
+ }
957
+
958
+ // components/event-calendar/dnd/types.ts
959
+ function createEventId(event) {
960
+ return `event-${event.id}`;
961
+ }
962
+ function createSlotId(data) {
963
+ switch (data.view) {
964
+ case "day":
965
+ return `slot-day-${data.day.getTime()}-${data.hour}`;
966
+ case "week":
967
+ return `slot-week-${data.day.getTime()}-${data.hour}`;
968
+ case "month":
969
+ return `slot-month-${data.day.getTime()}`;
970
+ case "resource":
971
+ return `slot-resource-${data.resourceId}-${data.day.getTime()}-${data.hour}`;
972
+ }
973
+ }
974
+ function DroppableSlot({
975
+ data,
976
+ children,
977
+ className,
978
+ style
979
+ }) {
980
+ const id = createSlotId(data);
981
+ const { setNodeRef, isOver } = core.useDroppable({
982
+ id,
983
+ data
984
+ });
985
+ return /* @__PURE__ */ jsxRuntime.jsx(
986
+ "div",
987
+ {
988
+ ref: setNodeRef,
989
+ className,
990
+ style: __spreadValues(__spreadValues({}, style), isOver ? { backgroundColor: "var(--accent)" } : {}),
991
+ children
992
+ }
993
+ );
994
+ }
995
+ function DraggableCreateSlot({
996
+ data,
997
+ children,
998
+ disabled = false,
999
+ className,
1000
+ style
1001
+ }) {
1002
+ const id = `create-${createSlotId(data)}`;
1003
+ const { attributes, listeners, setNodeRef, isDragging } = core.useDraggable({
1004
+ id,
1005
+ data: { type: "create", slotData: data },
1006
+ disabled
1007
+ });
1008
+ return /* @__PURE__ */ jsxRuntime.jsx(
1009
+ "div",
1010
+ __spreadProps(__spreadValues(__spreadValues({
1011
+ ref: setNodeRef
1012
+ }, listeners), attributes), {
1013
+ className,
1014
+ style: __spreadProps(__spreadValues({}, style), {
1015
+ opacity: isDragging ? 0.5 : 1,
1016
+ cursor: disabled ? "default" : "crosshair"
1017
+ }),
1018
+ children
1019
+ })
1020
+ );
1021
+ }
1022
+ function DraggableEvent({
1023
+ event,
1024
+ children,
1025
+ disabled = false,
1026
+ className,
1027
+ style
1028
+ }) {
1029
+ const { attributes, listeners, setNodeRef, isDragging } = core.useDraggable({
1030
+ id: createEventId(event),
1031
+ data: { type: "event", event },
1032
+ disabled
1033
+ });
1034
+ return /* @__PURE__ */ jsxRuntime.jsx(
1035
+ "div",
1036
+ __spreadProps(__spreadValues(__spreadValues({
1037
+ ref: setNodeRef
1038
+ }, listeners), attributes), {
1039
+ className,
1040
+ style: __spreadProps(__spreadValues({}, style), {
1041
+ opacity: isDragging ? 0.5 : 1,
1042
+ cursor: disabled ? "default" : "grab",
1043
+ position: "absolute"
1044
+ }),
1045
+ children
1046
+ })
1047
+ );
1048
+ }
1049
+ function MonthView({ currentDate, events }) {
1050
+ const {
1051
+ config,
1052
+ onEventClick,
1053
+ onEventDoubleClick,
1054
+ onSlotClick,
1055
+ onSlotDoubleClick,
1056
+ onDayClick,
1057
+ renderEvent,
1058
+ enableDragToCreate = false,
1059
+ enableDragToMove = false
1060
+ } = useCalendar();
1061
+ const days = getMonthDays(currentDate, config.weekStartsOn);
1062
+ const weekdays = getWeekdayNames(config.weekStartsOn, true, config.locale);
1063
+ const today = /* @__PURE__ */ new Date();
1064
+ const handleSlotClick = (day) => {
1065
+ if (onDayClick) {
1066
+ onDayClick(day);
1067
+ }
1068
+ if (onSlotClick) {
1069
+ const slotInfo = {
1070
+ start: dateFns.startOfDay(day),
1071
+ end: dateFns.endOfDay(day)
1072
+ };
1073
+ onSlotClick(slotInfo);
1074
+ }
1075
+ };
1076
+ const handleSlotDoubleClick = (day) => {
1077
+ if (onSlotDoubleClick) {
1078
+ const slotInfo = {
1079
+ start: dateFns.startOfDay(day),
1080
+ end: dateFns.endOfDay(day)
1081
+ };
1082
+ onSlotDoubleClick(slotInfo);
1083
+ }
1084
+ };
1085
+ const handleEventClick = (e, event) => {
1086
+ e.stopPropagation();
1087
+ onEventClick == null ? void 0 : onEventClick(event);
1088
+ };
1089
+ const handleEventDoubleClick = (e, event) => {
1090
+ e.stopPropagation();
1091
+ onEventDoubleClick == null ? void 0 : onEventDoubleClick(event);
1092
+ };
1093
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full", children: [
1094
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 border-b border-border", children: weekdays.map((day) => /* @__PURE__ */ jsxRuntime.jsx(
1095
+ "div",
1096
+ {
1097
+ className: "py-3 text-center text-xs font-medium text-muted-foreground uppercase tracking-wider",
1098
+ children: day
1099
+ },
1100
+ day
1101
+ )) }),
1102
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 flex-1 auto-rows-fr", children: days.map((day, index) => {
1103
+ const dayEvents = getEventsForDay(events, day);
1104
+ const isCurrentMonth = dateFns.isSameMonth(day, currentDate);
1105
+ const isToday = dateFns.isSameDay(day, today);
1106
+ const slotData = { view: "month", day };
1107
+ const cellContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1108
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between mb-1", children: /* @__PURE__ */ jsxRuntime.jsx(
1109
+ "span",
1110
+ {
1111
+ className: cn(
1112
+ "inline-flex items-center justify-center w-7 h-7 text-sm font-medium rounded-full",
1113
+ isToday && "bg-primary text-primary-foreground",
1114
+ !isToday && isCurrentMonth && "text-foreground",
1115
+ !isToday && !isCurrentMonth && "text-muted-foreground"
1116
+ ),
1117
+ children: formatDate(day, "d", config.locale)
1118
+ }
1119
+ ) }),
1120
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5 overflow-hidden", children: [
1121
+ dayEvents.slice(0, config.maxEventsPerDay).map((event) => {
1122
+ const eventColor = event.color || config.defaultEventColor;
1123
+ const eventContent = renderEvent ? renderEvent(event, "month") : /* @__PURE__ */ jsxRuntime.jsx("span", { children: event.title });
1124
+ const eventEl = /* @__PURE__ */ jsxRuntime.jsx(
1125
+ "div",
1126
+ {
1127
+ className: cn(
1128
+ "px-1.5 py-0.5 text-xs font-medium rounded truncate transition-opacity hover:opacity-80",
1129
+ !enableDragToMove && "cursor-pointer"
1130
+ ),
1131
+ style: {
1132
+ backgroundColor: `${eventColor}20`,
1133
+ color: eventColor,
1134
+ borderLeft: `2px solid ${eventColor}`
1135
+ },
1136
+ title: event.title,
1137
+ onClick: (e) => handleEventClick(e, event),
1138
+ onDoubleClick: (e) => handleEventDoubleClick(e, event),
1139
+ children: eventContent
1140
+ }
1141
+ );
1142
+ return enableDragToMove ? /* @__PURE__ */ jsxRuntime.jsx(DraggableEvent, { event, children: eventEl }, event.id) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: eventEl }, event.id);
1143
+ }),
1144
+ dayEvents.length > config.maxEventsPerDay && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground pl-1.5 font-medium", children: [
1145
+ "+",
1146
+ dayEvents.length - config.maxEventsPerDay,
1147
+ " more"
1148
+ ] })
1149
+ ] })
1150
+ ] });
1151
+ const cell = /* @__PURE__ */ jsxRuntime.jsx(
1152
+ "div",
1153
+ {
1154
+ className: cn(
1155
+ "min-h-[100px] border-b border-r border-border p-1.5 transition-colors hover:bg-muted/50 cursor-pointer h-full",
1156
+ !isCurrentMonth && "bg-muted/30",
1157
+ index % 7 === 0 && "border-l-0",
1158
+ index < 7 && "border-t-0"
1159
+ ),
1160
+ onClick: () => handleSlotClick(day),
1161
+ onDoubleClick: () => handleSlotDoubleClick(day),
1162
+ children: cellContent
1163
+ }
1164
+ );
1165
+ return enableDragToCreate || enableDragToMove ? /* @__PURE__ */ jsxRuntime.jsx(DroppableSlot, { data: slotData, className: "min-h-[100px]", children: enableDragToCreate ? /* @__PURE__ */ jsxRuntime.jsx(DraggableCreateSlot, { data: slotData, className: "h-full", children: cell }) : cell }, index) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: cell }, index);
1166
+ }) })
1167
+ ] });
1168
+ }
1169
+ function WeekView({ currentDate, events, dayCount, isMobile = false }) {
1170
+ var _a;
1171
+ const {
1172
+ config,
1173
+ onEventClick,
1174
+ onEventDoubleClick,
1175
+ onSlotClick,
1176
+ onSlotDoubleClick,
1177
+ renderEvent,
1178
+ enableDragToCreate = false,
1179
+ enableDragToMove = false
1180
+ } = useCalendar();
1181
+ const days = dayCount === 2 ? getTwoDays(currentDate, config.weekStartsOn) : getWeekDays(currentDate, config.weekStartsOn);
1182
+ const hours = getHoursArray(config.startHour, config.endHour);
1183
+ const today = /* @__PURE__ */ new Date();
1184
+ const totalHours = hours.length;
1185
+ const showCurrentTimeLine = (_a = config.showCurrentTimeLine) != null ? _a : true;
1186
+ const includesToday = days.some((d) => dateFns.isSameDay(d, today));
1187
+ const [now, setNow] = React2.useState(() => /* @__PURE__ */ new Date());
1188
+ const columnRefs = React2.useRef(/* @__PURE__ */ new Map());
1189
+ React2.useEffect(() => {
1190
+ if (!showCurrentTimeLine || !includesToday) return;
1191
+ const id = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
1192
+ return () => clearInterval(id);
1193
+ }, [showCurrentTimeLine, includesToday]);
1194
+ React2.useEffect(() => {
1195
+ const key = currentDate.toISOString().slice(0, 10);
1196
+ const el = columnRefs.current.get(key);
1197
+ if (el) {
1198
+ el.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" });
1199
+ }
1200
+ }, [currentDate]);
1201
+ const currentTimeLineTop = showCurrentTimeLine && includesToday ? getCurrentTimeLineTop(now, config.startHour, config.endHour, config.hourHeight, 0) : null;
1202
+ const dayColumnMinWidth = isMobile && dayCount !== 2 ? "min(45vw, 200px)" : "140px";
1203
+ const handleSlotClick = (day, hour) => {
1204
+ if (onSlotClick) {
1205
+ const slotInfo = {
1206
+ start: createSlotDate(day, hour),
1207
+ end: createSlotDate(day, hour + 1)
1208
+ };
1209
+ onSlotClick(slotInfo);
1210
+ }
1211
+ };
1212
+ const handleSlotDoubleClick = (day, hour) => {
1213
+ if (onSlotDoubleClick) {
1214
+ const slotInfo = {
1215
+ start: createSlotDate(day, hour),
1216
+ end: createSlotDate(day, hour + 1)
1217
+ };
1218
+ onSlotDoubleClick(slotInfo);
1219
+ }
1220
+ };
1221
+ const handleEventClick = (e, event) => {
1222
+ e.stopPropagation();
1223
+ onEventClick == null ? void 0 : onEventClick(event);
1224
+ };
1225
+ const handleEventDoubleClick = (e, event) => {
1226
+ e.stopPropagation();
1227
+ onEventDoubleClick == null ? void 0 : onEventDoubleClick(event);
1228
+ };
1229
+ const maxHeightStyle = config.timeSeriesMaxHeight != null ? typeof config.timeSeriesMaxHeight === "number" ? `${config.timeSeriesMaxHeight}px` : config.timeSeriesMaxHeight : void 0;
1230
+ return /* @__PURE__ */ jsxRuntime.jsx(
1231
+ "div",
1232
+ {
1233
+ className: "h-full overflow-auto",
1234
+ style: { maxHeight: maxHeightStyle },
1235
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-max flex-1", children: [
1236
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex border-b border-border shrink-0 bg-background z-10 sticky top-0 shadow-[0_4px_12px_-2px_rgba(0,0,0,0.08)] dark:shadow-[0_4px_12px_-2px_rgba(0,0,0,0.2)]", children: [
1237
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 shrink-0 border-r border-border sticky left-0 z-10 bg-background shadow-[4px_0_12px_-2px_rgba(0,0,0,0.08),6px_0_16px_-4px_rgba(0,0,0,0.06)] dark:shadow-[4px_0_16px_-2px_rgba(0,0,0,0.25),6px_0_24px_-4px_rgba(0,0,0,0.2)]" }),
1238
+ days.map((day, index) => {
1239
+ const isToday = dateFns.isSameDay(day, today);
1240
+ const dayKey = day.toISOString().slice(0, 10);
1241
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1242
+ "div",
1243
+ {
1244
+ ref: (el) => {
1245
+ if (el) columnRefs.current.set(dayKey, el);
1246
+ },
1247
+ className: cn(
1248
+ "flex-1 py-3 text-center border-r border-border last:border-r-0",
1249
+ isToday && "bg-primary/5"
1250
+ ),
1251
+ style: { minWidth: dayColumnMinWidth },
1252
+ children: [
1253
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-medium text-muted-foreground uppercase", children: formatDate(day, "EEE", config.locale) }),
1254
+ /* @__PURE__ */ jsxRuntime.jsx(
1255
+ "div",
1256
+ {
1257
+ className: cn(
1258
+ "mt-1 inline-flex items-center justify-center w-8 h-8 text-lg font-semibold rounded-full",
1259
+ isToday && "bg-primary text-primary-foreground",
1260
+ !isToday && "text-foreground"
1261
+ ),
1262
+ children: formatDate(day, "d", config.locale)
1263
+ }
1264
+ )
1265
+ ]
1266
+ },
1267
+ index
1268
+ );
1269
+ })
1270
+ ] }),
1271
+ /* @__PURE__ */ jsxRuntime.jsxs(
1272
+ "div",
1273
+ {
1274
+ className: "flex flex-1 relative",
1275
+ style: { minHeight: totalHours * config.hourHeight },
1276
+ children: [
1277
+ currentTimeLineTop != null && /* @__PURE__ */ jsxRuntime.jsx(
1278
+ "div",
1279
+ {
1280
+ className: "absolute left-16 right-0 h-0.5 bg-sky-300 z-20 pointer-events-none",
1281
+ style: { top: currentTimeLineTop },
1282
+ "aria-hidden": true,
1283
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -left-1 top-1/2 -translate-y-1/2 w-2 h-2 rounded-full bg-sky-300" })
1284
+ }
1285
+ ),
1286
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 shrink-0 border-r border-border sticky left-0 z-10 bg-background shadow-[4px_0_12px_-2px_rgba(0,0,0,0.08),6px_0_16px_-4px_rgba(0,0,0,0.06)] dark:shadow-[4px_0_16px_-2px_rgba(0,0,0,0.25),6px_0_24px_-4px_rgba(0,0,0,0.2)]", children: hours.map((hour) => /* @__PURE__ */ jsxRuntime.jsx(
1287
+ "div",
1288
+ {
1289
+ className: "pr-2 flex items-start justify-end",
1290
+ style: { height: `${config.hourHeight}px` },
1291
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground -mt-2", children: formatHour(hour, config.timeFormat, config.locale) })
1292
+ },
1293
+ hour
1294
+ )) }),
1295
+ days.map((day, dayIndex) => {
1296
+ const dayEvents = getEventsForDay(events, day);
1297
+ const isToday = dateFns.isSameDay(day, today);
1298
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1299
+ "div",
1300
+ {
1301
+ className: cn(
1302
+ "flex-1 border-r border-border last:border-r-0 relative",
1303
+ isToday && "bg-primary/5"
1304
+ ),
1305
+ style: { minWidth: dayColumnMinWidth },
1306
+ children: [
1307
+ hours.map((hour, index) => {
1308
+ const slotData = { view: "week", day, hour };
1309
+ const slotContent = /* @__PURE__ */ jsxRuntime.jsx(
1310
+ "div",
1311
+ {
1312
+ className: cn(
1313
+ "cursor-pointer hover:bg-muted/30 transition-colors h-full w-full",
1314
+ index < totalHours - 1 && "border-b border-border"
1315
+ ),
1316
+ style: { height: `${config.hourHeight}px` },
1317
+ onClick: () => handleSlotClick(day, hour),
1318
+ onDoubleClick: () => handleSlotDoubleClick(day, hour)
1319
+ }
1320
+ );
1321
+ return enableDragToCreate || enableDragToMove ? /* @__PURE__ */ jsxRuntime.jsx(
1322
+ DroppableSlot,
1323
+ {
1324
+ data: slotData,
1325
+ style: { height: `${config.hourHeight}px` },
1326
+ className: cn(index < totalHours - 1 && "border-b border-border"),
1327
+ children: enableDragToCreate ? /* @__PURE__ */ jsxRuntime.jsx(DraggableCreateSlot, { data: slotData, className: "h-full w-full", children: slotContent }) : slotContent
1328
+ },
1329
+ hour
1330
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1331
+ "div",
1332
+ {
1333
+ className: cn(
1334
+ "cursor-pointer hover:bg-muted/30 transition-colors",
1335
+ index < totalHours - 1 && "border-b border-border"
1336
+ ),
1337
+ style: { height: `${config.hourHeight}px` },
1338
+ onClick: () => handleSlotClick(day, hour),
1339
+ onDoubleClick: () => handleSlotDoubleClick(day, hour)
1340
+ },
1341
+ hour
1342
+ );
1343
+ }),
1344
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-0 left-0 right-0 h-px bg-border" }),
1345
+ dayEvents.map((event) => {
1346
+ if (!dateFns.isSameDay(event.start, day)) return null;
1347
+ const { top, height } = getEventPosition(event, config.hourHeight, config.startHour);
1348
+ const eventColor = event.color || config.defaultEventColor;
1349
+ const eventContent = renderEvent ? renderEvent(event, "week") : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1350
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold truncate", children: event.title }),
1351
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[10px] opacity-80", children: [
1352
+ formatDate(event.start, "h:mm a", config.locale),
1353
+ " - ",
1354
+ formatDate(event.end, "h:mm a", config.locale)
1355
+ ] })
1356
+ ] });
1357
+ const eventEl = /* @__PURE__ */ jsxRuntime.jsx(
1358
+ "div",
1359
+ {
1360
+ className: cn(
1361
+ "px-1.5 py-1 rounded text-xs font-medium overflow-hidden transition-opacity hover:opacity-90 h-full w-full",
1362
+ !enableDragToMove && "cursor-pointer"
1363
+ ),
1364
+ style: {
1365
+ backgroundColor: `${eventColor}15`,
1366
+ borderLeft: `3px solid ${eventColor}`,
1367
+ color: eventColor
1368
+ },
1369
+ title: event.title,
1370
+ onClick: (e) => handleEventClick(e, event),
1371
+ onDoubleClick: (e) => handleEventDoubleClick(e, event),
1372
+ children: eventContent
1373
+ }
1374
+ );
1375
+ return enableDragToMove ? /* @__PURE__ */ jsxRuntime.jsx(
1376
+ DraggableEvent,
1377
+ {
1378
+ event,
1379
+ className: "absolute left-0.5 right-0.5",
1380
+ style: { top: `${top}px`, height: `${height}px` },
1381
+ children: eventEl
1382
+ },
1383
+ event.id
1384
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1385
+ "div",
1386
+ {
1387
+ className: "absolute left-0.5 right-0.5",
1388
+ style: { top: `${top}px`, height: `${height}px` },
1389
+ children: eventEl
1390
+ },
1391
+ event.id
1392
+ );
1393
+ })
1394
+ ]
1395
+ },
1396
+ dayIndex
1397
+ );
1398
+ })
1399
+ ]
1400
+ }
1401
+ )
1402
+ ] })
1403
+ }
1404
+ );
1405
+ }
1406
+ function DayView({ currentDate, events }) {
1407
+ var _a;
1408
+ const {
1409
+ config,
1410
+ onEventClick,
1411
+ onEventDoubleClick,
1412
+ onSlotClick,
1413
+ onSlotDoubleClick,
1414
+ renderEvent,
1415
+ enableDragToCreate = false,
1416
+ enableDragToMove = false
1417
+ } = useCalendar();
1418
+ const dayEvents = getEventsForDay(events, currentDate);
1419
+ const hours = getHoursArray(config.startHour, config.endHour);
1420
+ const today = /* @__PURE__ */ new Date();
1421
+ const isToday = dateFns.isSameDay(currentDate, today);
1422
+ const totalHours = hours.length;
1423
+ const showCurrentTimeLine = (_a = config.showCurrentTimeLine) != null ? _a : true;
1424
+ const [now, setNow] = React2.useState(() => /* @__PURE__ */ new Date());
1425
+ React2.useEffect(() => {
1426
+ if (!showCurrentTimeLine || !isToday) return;
1427
+ const id = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
1428
+ return () => clearInterval(id);
1429
+ }, [showCurrentTimeLine, isToday]);
1430
+ const currentTimeLineTop = showCurrentTimeLine && isToday ? getCurrentTimeLineTop(now, config.startHour, config.endHour, config.hourHeight, 0) : null;
1431
+ const handleSlotClick = (hour) => {
1432
+ if (onSlotClick) {
1433
+ const slotInfo = {
1434
+ start: createSlotDate(currentDate, hour),
1435
+ end: createSlotDate(currentDate, hour + 1)
1436
+ };
1437
+ onSlotClick(slotInfo);
1438
+ }
1439
+ };
1440
+ const handleSlotDoubleClick = (hour) => {
1441
+ if (onSlotDoubleClick) {
1442
+ const slotInfo = {
1443
+ start: createSlotDate(currentDate, hour),
1444
+ end: createSlotDate(currentDate, hour + 1)
1445
+ };
1446
+ onSlotDoubleClick(slotInfo);
1447
+ }
1448
+ };
1449
+ const handleEventClick = (e, event) => {
1450
+ e.stopPropagation();
1451
+ onEventClick == null ? void 0 : onEventClick(event);
1452
+ };
1453
+ const handleEventDoubleClick = (e, event) => {
1454
+ e.stopPropagation();
1455
+ onEventDoubleClick == null ? void 0 : onEventDoubleClick(event);
1456
+ };
1457
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full overflow-hidden", children: [
1458
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex border-b border-border shrink-0 bg-background z-10 shadow-[0_4px_12px_-2px_rgba(0,0,0,0.08)] dark:shadow-[0_4px_12px_-2px_rgba(0,0,0,0.2)]", children: [
1459
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-20 shrink-0 border-r border-border" }),
1460
+ /* @__PURE__ */ jsxRuntime.jsxs(
1461
+ "div",
1462
+ {
1463
+ className: cn(
1464
+ "flex-1 py-4 text-center border-r border-border",
1465
+ isToday && "bg-primary/5"
1466
+ ),
1467
+ children: [
1468
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-muted-foreground uppercase", children: formatDate(currentDate, "EEEE", config.locale) }),
1469
+ /* @__PURE__ */ jsxRuntime.jsx(
1470
+ "div",
1471
+ {
1472
+ className: cn(
1473
+ "mt-1 inline-flex items-center justify-center w-10 h-10 text-xl font-semibold rounded-full",
1474
+ isToday && "bg-primary text-primary-foreground",
1475
+ !isToday && "text-foreground"
1476
+ ),
1477
+ children: formatDate(currentDate, "d", config.locale)
1478
+ }
1479
+ )
1480
+ ]
1481
+ }
1482
+ )
1483
+ ] }),
1484
+ /* @__PURE__ */ jsxRuntime.jsx(
1485
+ "div",
1486
+ {
1487
+ className: "flex flex-1 overflow-auto min-h-0",
1488
+ style: {
1489
+ maxHeight: config.timeSeriesMaxHeight != null ? typeof config.timeSeriesMaxHeight === "number" ? `${config.timeSeriesMaxHeight}px` : config.timeSeriesMaxHeight : void 0
1490
+ },
1491
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1492
+ "div",
1493
+ {
1494
+ className: "flex min-w-full relative",
1495
+ style: { minHeight: totalHours * config.hourHeight },
1496
+ children: [
1497
+ currentTimeLineTop != null && /* @__PURE__ */ jsxRuntime.jsx(
1498
+ "div",
1499
+ {
1500
+ className: "absolute left-20 right-0 h-0.5 bg-sky-300 z-20 pointer-events-none",
1501
+ style: { top: currentTimeLineTop },
1502
+ "aria-hidden": true,
1503
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -left-1 top-1/2 -translate-y-1/2 w-2 h-2 rounded-full bg-sky-300" })
1504
+ }
1505
+ ),
1506
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-20 shrink-0 border-r border-border relative", children: hours.map((hour) => /* @__PURE__ */ jsxRuntime.jsx(
1507
+ "div",
1508
+ {
1509
+ className: "pr-3 flex items-start justify-end",
1510
+ style: { height: `${config.hourHeight}px` },
1511
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground -mt-2", children: formatHour(hour, config.timeFormat, config.locale) })
1512
+ },
1513
+ hour
1514
+ )) }),
1515
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex-1 relative border-r border-border", isToday && "bg-primary/5"), children: [
1516
+ hours.map((hour, index) => {
1517
+ const slotData = { view: "day", day: currentDate, hour };
1518
+ const slotContent = /* @__PURE__ */ jsxRuntime.jsx(
1519
+ "div",
1520
+ {
1521
+ className: cn(
1522
+ "cursor-pointer hover:bg-muted/30 transition-colors h-full w-full",
1523
+ index < totalHours - 1 && "border-b border-border"
1524
+ ),
1525
+ style: { height: `${config.hourHeight}px` },
1526
+ onClick: () => handleSlotClick(hour),
1527
+ onDoubleClick: () => handleSlotDoubleClick(hour)
1528
+ }
1529
+ );
1530
+ return enableDragToCreate || enableDragToMove ? /* @__PURE__ */ jsxRuntime.jsx(
1531
+ DroppableSlot,
1532
+ {
1533
+ data: slotData,
1534
+ style: { height: `${config.hourHeight}px` },
1535
+ className: cn(index < totalHours - 1 && "border-b border-border"),
1536
+ children: enableDragToCreate ? /* @__PURE__ */ jsxRuntime.jsx(DraggableCreateSlot, { data: slotData, className: "h-full w-full", children: slotContent }) : slotContent
1537
+ },
1538
+ hour
1539
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1540
+ "div",
1541
+ {
1542
+ className: cn(
1543
+ "cursor-pointer hover:bg-muted/30 transition-colors",
1544
+ index < totalHours - 1 && "border-b border-border"
1545
+ ),
1546
+ style: { height: `${config.hourHeight}px` },
1547
+ onClick: () => handleSlotClick(hour),
1548
+ onDoubleClick: () => handleSlotDoubleClick(hour)
1549
+ },
1550
+ hour
1551
+ );
1552
+ }),
1553
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-0 left-0 right-0 h-px bg-border" }),
1554
+ dayEvents.map((event) => {
1555
+ if (!dateFns.isSameDay(event.start, currentDate)) return null;
1556
+ const { top, height } = getEventPosition(event, config.hourHeight, config.startHour);
1557
+ const eventColor = event.color || config.defaultEventColor;
1558
+ const eventContent = renderEvent ? renderEvent(event, "day") : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1559
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-sm", style: { color: eventColor }, children: event.title }),
1560
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground mt-0.5", children: [
1561
+ formatDate(event.start, "h:mm a", config.locale),
1562
+ " - ",
1563
+ formatDate(event.end, "h:mm a", config.locale)
1564
+ ] }),
1565
+ event.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground mt-1 line-clamp-2", children: event.description })
1566
+ ] });
1567
+ const eventEl = /* @__PURE__ */ jsxRuntime.jsx(
1568
+ "div",
1569
+ {
1570
+ className: cn(
1571
+ "px-3 py-2 rounded-lg overflow-hidden transition-all hover:shadow-md h-full w-full",
1572
+ !enableDragToMove && "cursor-pointer"
1573
+ ),
1574
+ style: {
1575
+ backgroundColor: `${eventColor}15`,
1576
+ borderLeft: `4px solid ${eventColor}`
1577
+ },
1578
+ title: event.title,
1579
+ onClick: (e) => handleEventClick(e, event),
1580
+ onDoubleClick: (e) => handleEventDoubleClick(e, event),
1581
+ children: eventContent
1582
+ }
1583
+ );
1584
+ return enableDragToMove ? /* @__PURE__ */ jsxRuntime.jsx(
1585
+ DraggableEvent,
1586
+ {
1587
+ event,
1588
+ className: "absolute left-2 right-2",
1589
+ style: { top: `${top}px`, height: `${height}px` },
1590
+ children: eventEl
1591
+ },
1592
+ event.id
1593
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-2 right-2", style: { top: `${top}px`, height: `${height}px` }, children: eventEl }, event.id);
1594
+ })
1595
+ ] })
1596
+ ]
1597
+ }
1598
+ )
1599
+ }
1600
+ )
1601
+ ] });
1602
+ }
1603
+ function ResourceView({ currentDate, events, resources }) {
1604
+ const {
1605
+ config,
1606
+ onEventClick,
1607
+ onEventDoubleClick,
1608
+ onSlotClick,
1609
+ onSlotDoubleClick,
1610
+ renderEvent,
1611
+ enableDragToCreate = false,
1612
+ enableDragToMove = false
1613
+ } = useCalendar();
1614
+ const days = getWeekDays(currentDate, config.weekStartsOn);
1615
+ const hours = getHoursArray(config.startHour, config.endHour);
1616
+ const today = /* @__PURE__ */ new Date();
1617
+ const hourHeight = 56;
1618
+ const totalHours = hours.length;
1619
+ const getResourceDayEvents = (resourceId, day) => {
1620
+ return events.filter(
1621
+ (event) => event.resourceId === resourceId && dateFns.isSameDay(event.start, day)
1622
+ );
1623
+ };
1624
+ const handleSlotClick = (day, hour, resourceId) => {
1625
+ if (onSlotClick) {
1626
+ const slotInfo = {
1627
+ start: createSlotDate(day, hour),
1628
+ end: createSlotDate(day, hour + 1),
1629
+ resourceId
1630
+ };
1631
+ onSlotClick(slotInfo);
1632
+ }
1633
+ };
1634
+ const handleSlotDoubleClick = (day, hour, resourceId) => {
1635
+ if (onSlotDoubleClick) {
1636
+ const slotInfo = {
1637
+ start: createSlotDate(day, hour),
1638
+ end: createSlotDate(day, hour + 1),
1639
+ resourceId
1640
+ };
1641
+ onSlotDoubleClick(slotInfo);
1642
+ }
1643
+ };
1644
+ const handleEventClick = (e, event) => {
1645
+ e.stopPropagation();
1646
+ onEventClick == null ? void 0 : onEventClick(event);
1647
+ };
1648
+ const handleEventDoubleClick = (e, event) => {
1649
+ e.stopPropagation();
1650
+ onEventDoubleClick == null ? void 0 : onEventDoubleClick(event);
1651
+ };
1652
+ if (resources.length === 0) {
1653
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-muted-foreground", children: "No resources available. Add resources to use the resource view." });
1654
+ }
1655
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full overflow-hidden", children: [
1656
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex border-b border-border shrink-0 bg-background z-10", children: [
1657
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 shrink-0 border-r border-border" }),
1658
+ resources.map((resource) => {
1659
+ const resourceColor = resource.color || config.defaultResourceColor;
1660
+ return /* @__PURE__ */ jsxRuntime.jsx(
1661
+ "div",
1662
+ {
1663
+ className: "flex-1 py-3 px-2 text-center border-r border-border last:border-r-0",
1664
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2", children: [
1665
+ /* @__PURE__ */ jsxRuntime.jsx(
1666
+ "div",
1667
+ {
1668
+ className: "w-3 h-3 rounded-full shrink-0",
1669
+ style: { backgroundColor: resourceColor }
1670
+ }
1671
+ ),
1672
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground truncate", children: resource.name })
1673
+ ] })
1674
+ },
1675
+ resource.id
1676
+ );
1677
+ })
1678
+ ] }),
1679
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex border-b border-border shrink-0 bg-muted/50 z-10", children: [
1680
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 shrink-0 border-r border-border py-2 px-2 text-xs font-medium text-muted-foreground", children: "Week View" }),
1681
+ resources.map((resource) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex border-r border-border last:border-r-0", children: days.map((day, dayIndex) => {
1682
+ const isToday = dateFns.isSameDay(day, today);
1683
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1684
+ "div",
1685
+ {
1686
+ className: cn(
1687
+ "flex-1 py-2 text-center border-r border-border/50 last:border-r-0",
1688
+ isToday && "bg-primary/5"
1689
+ ),
1690
+ children: [
1691
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-muted-foreground uppercase", children: formatDate(day, "EEE", config.locale) }),
1692
+ /* @__PURE__ */ jsxRuntime.jsx(
1693
+ "div",
1694
+ {
1695
+ className: cn(
1696
+ "text-xs font-medium",
1697
+ isToday && "text-primary",
1698
+ !isToday && "text-foreground"
1699
+ ),
1700
+ children: formatDate(day, "d", config.locale)
1701
+ }
1702
+ )
1703
+ ]
1704
+ },
1705
+ dayIndex
1706
+ );
1707
+ }) }, resource.id))
1708
+ ] }),
1709
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 overflow-y-auto min-h-0", children: /* @__PURE__ */ jsxRuntime.jsxs(
1710
+ "div",
1711
+ {
1712
+ className: "flex min-w-full",
1713
+ style: { minHeight: totalHours * hourHeight },
1714
+ children: [
1715
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-16 shrink-0 border-r border-border relative", children: [
1716
+ hours.map((hour, index) => /* @__PURE__ */ jsxRuntime.jsx(
1717
+ "div",
1718
+ {
1719
+ className: cn(
1720
+ "pr-2 flex items-start justify-end",
1721
+ index < totalHours - 1 && "border-b border-border"
1722
+ ),
1723
+ style: { height: `${hourHeight}px` },
1724
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground -mt-1.5", children: formatHour(hour, config.timeFormat, config.locale) })
1725
+ },
1726
+ hour
1727
+ )),
1728
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-0 left-0 right-0 h-px bg-border" })
1729
+ ] }),
1730
+ resources.map((resource) => {
1731
+ const resourceColor = resource.color || config.defaultResourceColor;
1732
+ return /* @__PURE__ */ jsxRuntime.jsx(
1733
+ "div",
1734
+ {
1735
+ className: "flex-1 flex border-r border-border last:border-r-0",
1736
+ children: days.map((day, dayIndex) => {
1737
+ const dayEvents = getResourceDayEvents(resource.id, day);
1738
+ const isToday = dateFns.isSameDay(day, today);
1739
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1740
+ "div",
1741
+ {
1742
+ className: cn(
1743
+ "flex-1 border-r border-border/50 last:border-r-0 relative",
1744
+ isToday && "bg-primary/5"
1745
+ ),
1746
+ children: [
1747
+ hours.map((hour, index) => {
1748
+ const slotData = {
1749
+ view: "resource",
1750
+ day,
1751
+ hour,
1752
+ resourceId: resource.id
1753
+ };
1754
+ const slotContent = /* @__PURE__ */ jsxRuntime.jsx(
1755
+ "div",
1756
+ {
1757
+ className: cn(
1758
+ "cursor-pointer hover:bg-muted/30 transition-colors h-full w-full",
1759
+ index < totalHours - 1 && "border-b border-border"
1760
+ ),
1761
+ style: { height: `${hourHeight}px` },
1762
+ onClick: () => handleSlotClick(day, hour, resource.id),
1763
+ onDoubleClick: () => handleSlotDoubleClick(day, hour, resource.id)
1764
+ }
1765
+ );
1766
+ return enableDragToCreate || enableDragToMove ? /* @__PURE__ */ jsxRuntime.jsx(
1767
+ DroppableSlot,
1768
+ {
1769
+ data: slotData,
1770
+ style: { height: `${hourHeight}px` },
1771
+ className: cn(index < totalHours - 1 && "border-b border-border"),
1772
+ children: enableDragToCreate ? /* @__PURE__ */ jsxRuntime.jsx(DraggableCreateSlot, { data: slotData, className: "h-full w-full", children: slotContent }) : slotContent
1773
+ },
1774
+ hour
1775
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1776
+ "div",
1777
+ {
1778
+ className: cn(
1779
+ "cursor-pointer hover:bg-muted/30 transition-colors",
1780
+ index < totalHours - 1 && "border-b border-border"
1781
+ ),
1782
+ style: { height: `${hourHeight}px` },
1783
+ onClick: () => handleSlotClick(day, hour, resource.id),
1784
+ onDoubleClick: () => handleSlotDoubleClick(day, hour, resource.id)
1785
+ },
1786
+ hour
1787
+ );
1788
+ }),
1789
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-0 left-0 right-0 h-px bg-border" }),
1790
+ dayEvents.map((event) => {
1791
+ const { top, height } = getEventPosition(event, config.hourHeight, config.startHour);
1792
+ const scaledTop = top / config.hourHeight * hourHeight;
1793
+ const scaledHeight = height / config.hourHeight * hourHeight;
1794
+ const eventColor = event.color || resourceColor;
1795
+ const eventContent = renderEvent ? renderEvent(event, "resource") : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1796
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate font-semibold", children: event.title }),
1797
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate opacity-80", children: formatDate(event.start, "h:mm", config.locale) })
1798
+ ] });
1799
+ const eventEl = /* @__PURE__ */ jsxRuntime.jsx(
1800
+ "div",
1801
+ {
1802
+ className: cn(
1803
+ "px-1 py-0.5 rounded text-[10px] font-medium overflow-hidden transition-opacity hover:opacity-90 h-full w-full",
1804
+ !enableDragToMove && "cursor-pointer"
1805
+ ),
1806
+ style: {
1807
+ backgroundColor: `${eventColor}20`,
1808
+ borderLeft: `2px solid ${eventColor}`,
1809
+ color: eventColor
1810
+ },
1811
+ title: `${event.title} - ${resource.name}`,
1812
+ onClick: (e) => handleEventClick(e, event),
1813
+ onDoubleClick: (e) => handleEventDoubleClick(e, event),
1814
+ children: eventContent
1815
+ }
1816
+ );
1817
+ return enableDragToMove ? /* @__PURE__ */ jsxRuntime.jsx(
1818
+ DraggableEvent,
1819
+ {
1820
+ event,
1821
+ className: "absolute left-0.5 right-0.5",
1822
+ style: { top: `${scaledTop}px`, height: `${scaledHeight}px` },
1823
+ children: eventEl
1824
+ },
1825
+ event.id
1826
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1827
+ "div",
1828
+ {
1829
+ className: "absolute left-0.5 right-0.5",
1830
+ style: { top: `${scaledTop}px`, height: `${scaledHeight}px` },
1831
+ children: eventEl
1832
+ },
1833
+ event.id
1834
+ );
1835
+ })
1836
+ ]
1837
+ },
1838
+ dayIndex
1839
+ );
1840
+ })
1841
+ },
1842
+ resource.id
1843
+ );
1844
+ })
1845
+ ]
1846
+ }
1847
+ ) })
1848
+ ] });
1849
+ }
1850
+ function EventCalendar({
1851
+ events,
1852
+ resources = [],
1853
+ date,
1854
+ defaultDate = /* @__PURE__ */ new Date(),
1855
+ view,
1856
+ defaultView = "month",
1857
+ views = ["month", "week", "day", "resource"],
1858
+ calendarOptions = {},
1859
+ showNavigation = true,
1860
+ showViewSwitcher = true,
1861
+ showTodayButton = true,
1862
+ className,
1863
+ loading = false,
1864
+ theme = "system",
1865
+ themeVars,
1866
+ enableDragToCreate = false,
1867
+ enableDragToMove = false,
1868
+ mobileBreakpoint = "md",
1869
+ showMobileMonthPicker = true,
1870
+ onEventClick,
1871
+ onEventDoubleClick,
1872
+ onSlotClick,
1873
+ onSlotDoubleClick,
1874
+ onDateChange,
1875
+ onViewChange,
1876
+ onNavigate,
1877
+ onRangeChange,
1878
+ onDayClick,
1879
+ onEventCreate,
1880
+ onEventMove,
1881
+ renderEvent,
1882
+ renderDayCell,
1883
+ renderHeader,
1884
+ renderResourceHeader,
1885
+ renderTimeSlot,
1886
+ renderEmpty,
1887
+ renderSelectedEvent,
1888
+ renderSelectedSlot
1889
+ }) {
1890
+ const [internalDate, setInternalDate] = React2.useState(defaultDate);
1891
+ const [selectedEvent, setSelectedEvent] = React2.useState(null);
1892
+ const [selectedSlot, setSelectedSlot] = React2.useState(null);
1893
+ const currentDate = date != null ? date : internalDate;
1894
+ const isMobile = useMediaQuery(mobileBreakpoint);
1895
+ const [internalView, setInternalView] = React2.useState(defaultView);
1896
+ const currentView = view != null ? view : internalView;
1897
+ const config = React2.useMemo(
1898
+ () => {
1899
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1900
+ return {
1901
+ weekStartsOn: (_a = calendarOptions.weekStartsOn) != null ? _a : defaultConfig.weekStartsOn,
1902
+ startHour: (_b = calendarOptions.startHour) != null ? _b : defaultConfig.startHour,
1903
+ endHour: (_c = calendarOptions.endHour) != null ? _c : defaultConfig.endHour,
1904
+ hourHeight: (_d = calendarOptions.hourHeight) != null ? _d : defaultConfig.hourHeight,
1905
+ maxEventsPerDay: (_e = calendarOptions.maxEventsPerDay) != null ? _e : defaultConfig.maxEventsPerDay,
1906
+ timeSeriesMaxHeight: (_f = calendarOptions.timeSeriesMaxHeight) != null ? _f : defaultConfig.timeSeriesMaxHeight,
1907
+ showCurrentTimeLine: (_g = calendarOptions.showCurrentTimeLine) != null ? _g : defaultConfig.showCurrentTimeLine,
1908
+ defaultEventColor: (_h = calendarOptions.defaultEventColor) != null ? _h : defaultConfig.defaultEventColor,
1909
+ defaultResourceColor: (_i = calendarOptions.defaultResourceColor) != null ? _i : defaultConfig.defaultResourceColor,
1910
+ locale: (_j = calendarOptions.locale) != null ? _j : defaultConfig.locale,
1911
+ timeFormat: (_k = calendarOptions.timeFormat) != null ? _k : defaultConfig.timeFormat
1912
+ };
1913
+ },
1914
+ [calendarOptions]
1915
+ );
1916
+ const effectiveView = isMobile ? ["week", "day", "2day"].includes(currentView) ? currentView : "week" : currentView;
1917
+ const handleNavigate = React2.useCallback(
1918
+ (direction) => {
1919
+ const newDate = navigateDate(currentDate, effectiveView, direction);
1920
+ if (date === void 0) {
1921
+ setInternalDate(newDate);
1922
+ }
1923
+ onDateChange == null ? void 0 : onDateChange(newDate);
1924
+ onNavigate == null ? void 0 : onNavigate(newDate, direction);
1925
+ },
1926
+ [currentDate, effectiveView, date, onDateChange, onNavigate]
1927
+ );
1928
+ const handleWeekNavigate = React2.useCallback(
1929
+ (direction) => {
1930
+ const newDate = direction === "next" ? dateFns.addWeeks(currentDate, 1) : dateFns.subWeeks(currentDate, 1);
1931
+ if (date === void 0) {
1932
+ setInternalDate(newDate);
1933
+ }
1934
+ onDateChange == null ? void 0 : onDateChange(newDate);
1935
+ },
1936
+ [currentDate, date, onDateChange]
1937
+ );
1938
+ const handleDateSelect = React2.useCallback(
1939
+ (newDate) => {
1940
+ if (date === void 0) {
1941
+ setInternalDate(newDate);
1942
+ }
1943
+ onDateChange == null ? void 0 : onDateChange(newDate);
1944
+ },
1945
+ [date, onDateChange]
1946
+ );
1947
+ const handleToday = React2.useCallback(() => {
1948
+ const today = /* @__PURE__ */ new Date();
1949
+ if (date === void 0) {
1950
+ setInternalDate(today);
1951
+ }
1952
+ onDateChange == null ? void 0 : onDateChange(today);
1953
+ onNavigate == null ? void 0 : onNavigate(today, "today");
1954
+ }, [date, onDateChange, onNavigate]);
1955
+ const handleViewChange = React2.useCallback(
1956
+ (newView) => {
1957
+ if (view === void 0) {
1958
+ setInternalView(newView);
1959
+ }
1960
+ onViewChange == null ? void 0 : onViewChange(newView);
1961
+ },
1962
+ [view, onViewChange]
1963
+ );
1964
+ const handleEventClick = React2.useCallback(
1965
+ (event) => {
1966
+ onEventClick == null ? void 0 : onEventClick(event);
1967
+ if (renderSelectedEvent) {
1968
+ setSelectedEvent(event);
1969
+ setSelectedSlot(null);
1970
+ }
1971
+ },
1972
+ [onEventClick, renderSelectedEvent]
1973
+ );
1974
+ const handleSlotClick = React2.useCallback(
1975
+ (slot) => {
1976
+ onSlotClick == null ? void 0 : onSlotClick(slot);
1977
+ if (renderSelectedSlot) {
1978
+ setSelectedSlot(slot);
1979
+ setSelectedEvent(null);
1980
+ }
1981
+ },
1982
+ [onSlotClick, renderSelectedSlot]
1983
+ );
1984
+ const handleCloseSelected = React2.useCallback(() => {
1985
+ setSelectedEvent(null);
1986
+ setSelectedSlot(null);
1987
+ }, []);
1988
+ const contextValue = React2.useMemo(
1989
+ () => ({
1990
+ currentDate,
1991
+ view: currentView,
1992
+ events,
1993
+ resources,
1994
+ config,
1995
+ onEventClick: renderSelectedEvent ? handleEventClick : onEventClick,
1996
+ onEventDoubleClick,
1997
+ onSlotClick: renderSelectedSlot ? handleSlotClick : onSlotClick,
1998
+ onSlotDoubleClick,
1999
+ onDayClick,
2000
+ renderEvent,
2001
+ enableDragToCreate,
2002
+ enableDragToMove,
2003
+ onEventCreate,
2004
+ onEventMove
2005
+ }),
2006
+ [
2007
+ currentDate,
2008
+ currentView,
2009
+ events,
2010
+ resources,
2011
+ config,
2012
+ renderSelectedEvent,
2013
+ renderSelectedSlot,
2014
+ handleEventClick,
2015
+ handleSlotClick,
2016
+ onEventClick,
2017
+ onEventDoubleClick,
2018
+ onSlotClick,
2019
+ onSlotDoubleClick,
2020
+ onDayClick,
2021
+ renderEvent,
2022
+ enableDragToCreate,
2023
+ enableDragToMove,
2024
+ onEventCreate,
2025
+ onEventMove
2026
+ ]
2027
+ );
2028
+ const mobileViews = ["week", "day", "2day"];
2029
+ const title = getViewTitle(currentDate, effectiveView, config.weekStartsOn, config.locale);
2030
+ React2.useEffect(() => {
2031
+ if (onRangeChange) {
2032
+ const range = getViewDateRange(currentDate, effectiveView, config.weekStartsOn);
2033
+ onRangeChange(range);
2034
+ }
2035
+ }, [currentDate, effectiveView, config.weekStartsOn, onRangeChange]);
2036
+ const availableViews = (isMobile ? mobileViews : views).filter((v) => {
2037
+ if (v === "resource" && resources.length === 0) return false;
2038
+ return true;
2039
+ });
2040
+ const calendarContent = /* @__PURE__ */ jsxRuntime.jsx(CalendarProvider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
2041
+ Card,
2042
+ {
2043
+ className: cn(
2044
+ "flex flex-col h-full overflow-hidden border-border",
2045
+ isMobile && "gap-0 py-0",
2046
+ className
2047
+ ),
2048
+ children: [
2049
+ (showNavigation || showViewSwitcher) && /* @__PURE__ */ jsxRuntime.jsx(
2050
+ "div",
2051
+ {
2052
+ className: cn(
2053
+ "bg-card",
2054
+ isMobile ? "px-3 py-2 border-b border-border relative z-10 rounded-t-xl shadow-[0_4px_24px_rgba(0,0,0,0.12),0_8px_40px_rgba(0,0,0,0.1),0_12px_48px_rgba(0,0,0,0.08)] dark:shadow-[0_4px_24px_rgba(0,0,0,0.35),0_8px_40px_rgba(0,0,0,0.3),0_12px_48px_rgba(0,0,0,0.2)]" : "p-4 border-b border-border"
2055
+ ),
2056
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2057
+ CalendarHeader,
2058
+ {
2059
+ currentDate,
2060
+ view: effectiveView,
2061
+ views: availableViews,
2062
+ title,
2063
+ showNavigation,
2064
+ showViewSwitcher,
2065
+ showTodayButton,
2066
+ isMobile,
2067
+ showMobileMonthPicker,
2068
+ weekStartsOn: config.weekStartsOn,
2069
+ locale: config.locale,
2070
+ onNavigate: handleNavigate,
2071
+ onViewChange: handleViewChange,
2072
+ onToday: handleToday,
2073
+ onDateSelect: isMobile ? handleDateSelect : void 0,
2074
+ onWeekNavigate: isMobile ? handleWeekNavigate : void 0,
2075
+ renderHeader
2076
+ }
2077
+ )
2078
+ }
2079
+ ),
2080
+ /* @__PURE__ */ jsxRuntime.jsxs(
2081
+ "div",
2082
+ {
2083
+ className: cn(
2084
+ "flex-1 overflow-hidden relative",
2085
+ isMobile && "rounded-b-xl bg-background shadow-[inset_0_8px_12px_-6px_rgba(0,0,0,0.1),0_2px_8px_rgba(0,0,0,0.06)] dark:shadow-[inset_0_8px_12px_-6px_rgba(0,0,0,0.25),0_2px_8px_rgba(0,0,0,0.15)]"
2086
+ ),
2087
+ children: [
2088
+ loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-background/50 flex items-center justify-center z-20", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { className: "h-8 w-8" }) }),
2089
+ events.length === 0 && renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2090
+ effectiveView === "month" && /* @__PURE__ */ jsxRuntime.jsx(MonthView, { currentDate, events }),
2091
+ (effectiveView === "week" || effectiveView === "2day") && /* @__PURE__ */ jsxRuntime.jsx(
2092
+ WeekView,
2093
+ {
2094
+ currentDate,
2095
+ events,
2096
+ dayCount: effectiveView === "2day" ? 2 : void 0,
2097
+ isMobile
2098
+ }
2099
+ ),
2100
+ effectiveView === "day" && /* @__PURE__ */ jsxRuntime.jsx(DayView, { currentDate, events }),
2101
+ effectiveView === "resource" && /* @__PURE__ */ jsxRuntime.jsx(
2102
+ ResourceView,
2103
+ {
2104
+ currentDate,
2105
+ events,
2106
+ resources
2107
+ }
2108
+ )
2109
+ ] })
2110
+ ]
2111
+ }
2112
+ ),
2113
+ renderSelectedEvent && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderSelectedEvent({
2114
+ event: selectedEvent,
2115
+ onClose: handleCloseSelected
2116
+ }) }),
2117
+ renderSelectedSlot && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderSelectedSlot({
2118
+ slot: selectedSlot,
2119
+ onClose: handleCloseSelected
2120
+ }) })
2121
+ ]
2122
+ }
2123
+ ) });
2124
+ const wrappedContent = enableDragToCreate || enableDragToMove ? /* @__PURE__ */ jsxRuntime.jsx(
2125
+ EventCalendarDndProvider,
2126
+ {
2127
+ enableDragToCreate,
2128
+ enableDragToMove,
2129
+ onEventCreate,
2130
+ onEventMove,
2131
+ defaultEventColor: config.defaultEventColor,
2132
+ locale: config.locale,
2133
+ renderEvent,
2134
+ children: calendarContent
2135
+ }
2136
+ ) : calendarContent;
2137
+ if (theme || themeVars) {
2138
+ return /* @__PURE__ */ jsxRuntime.jsx(
2139
+ EventCalendarThemeProvider,
2140
+ {
2141
+ theme: theme != null ? theme : "system",
2142
+ themeVars,
2143
+ children: wrappedContent
2144
+ }
2145
+ );
2146
+ }
2147
+ return wrappedContent;
2148
+ }
2149
+
2150
+ exports.EventCalendar = EventCalendar;
2151
+ exports.EventCalendarThemeProvider = EventCalendarThemeProvider;
2152
+ exports.createSlotDate = createSlotDate;
2153
+ exports.formatDate = formatDate;
2154
+ exports.formatHour = formatHour;
2155
+ exports.getDateFnsLocale = getDateFnsLocale;
2156
+ exports.getEventsForDay = getEventsForDay;
2157
+ exports.getHoursArray = getHoursArray;
2158
+ exports.getMonthDays = getMonthDays;
2159
+ exports.getViewDateRange = getViewDateRange;
2160
+ exports.getViewTitle = getViewTitle;
2161
+ exports.getWeekDays = getWeekDays;
2162
+ exports.navigateDate = navigateDate;
2163
+ exports.useCalendar = useCalendar;
2164
+ //# sourceMappingURL=index.js.map
2165
+ //# sourceMappingURL=index.js.map