"use client";
import { cn } from "./index3.js";
import { Button } from "./index6.js";
import { Badge } from "./index13.js";
import { ScrollArea } from "./index45.js";
import { motion } from "./index359.js";
import { Avatar, AvatarFallback, AvatarGroup, AvatarImage } from "./index376.js";
import { snapMinutes } from "./index377.js";
import { ArrowLeft, ArrowRight, CalendarCheck2 } from "lucide-react";
import * as React from "react";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
import { addDays, addWeeks, endOfWeek, format, getWeek, isBefore, isSameDay, isToday, setMinutes, setSeconds, startOfDay, startOfWeek, subWeeks } from "date-fns";
//#region src/components/molecules/data/WeekCalendar/WeekCalendar.tsx
/** Minimum meeting duration in minutes */
var MIN_MEETING_DURATION = 15;
/** Time adjustment step in milliseconds (15 minutes) */
var TIME_STEP_MS = MIN_MEETING_DURATION * 6e4;
/** Minimum card height in pixels for content readability */
var MIN_CARD_HEIGHT = 60;
/** Snap interval for list-edit mode (always 15 min) */
var LIST_EDIT_SNAP_INTERVAL = 15;
/** Animation duration for position swaps in ms */
var SWAP_ANIMATION_DURATION = 200;
/** Maps meeting color variants to Tailwind background classes */
var MEETING_COLOR_MAP = {
	brand: "bg-primary",
	error: "bg-destructive",
	warning: "bg-warning",
	success: "bg-success",
	purple: "bg-purple-400 dark:bg-purple-500",
	blue: "bg-blue-400 dark:bg-blue-500",
	orange: "bg-orange-400 dark:bg-orange-500"
};
/** Shared keyboard handler for time adjustment on meeting cards */
function handleTimeAdjustKeyDown(e, meeting, onTimeAdjust) {
	if (!onTimeAdjust) return;
	if (e.key === "ArrowUp" && !e.shiftKey) {
		e.preventDefault();
		onTimeAdjust(meeting.id, new Date(meeting.startTime.getTime() - TIME_STEP_MS), new Date(meeting.endTime.getTime() - TIME_STEP_MS));
	} else if (e.key === "ArrowDown" && !e.shiftKey) {
		e.preventDefault();
		onTimeAdjust(meeting.id, new Date(meeting.startTime.getTime() + TIME_STEP_MS), new Date(meeting.endTime.getTime() + TIME_STEP_MS));
	} else if (e.key === "ArrowUp" && e.shiftKey) {
		e.preventDefault();
		const newEnd = new Date(meeting.endTime.getTime() - TIME_STEP_MS);
		if (newEnd.getTime() - meeting.startTime.getTime() >= TIME_STEP_MS) onTimeAdjust(meeting.id, meeting.startTime, newEnd);
	} else if (e.key === "ArrowDown" && e.shiftKey) {
		e.preventDefault();
		onTimeAdjust(meeting.id, meeting.startTime, new Date(meeting.endTime.getTime() + TIME_STEP_MS));
	}
}
/**
* Snap a date to the nearest interval
*/
function snapToInterval(date, interval) {
	return setMinutes(setSeconds(date, 0), snapMinutes(date.getMinutes(), interval));
}
/**
* Calculate card height based on meeting duration
*/
function calculateCardHeight(startTime, endTime, pixelsPerMinute) {
	const calculatedHeight = (endTime.getTime() - startTime.getTime()) / 6e4 * pixelsPerMinute;
	return Math.max(calculatedHeight, MIN_CARD_HEIGHT);
}
function useDrag({ meetings, pixelsPerMinute, gridContainerRef, onDragEnd, snapInterval = LIST_EDIT_SNAP_INTERVAL }) {
	const [dragState, setDragState] = React.useState(null);
	const scrollAnimationRef = React.useRef(null);
	const lastMouseYRef = React.useRef(0);
	const initialScrollTopRef = React.useRef(0);
	const SCROLL_ZONE = 40;
	const SCROLL_SPEED_BASE = 2;
	const SCROLL_SPEED_MAX = 12;
	const handleDragStart = React.useCallback((meetingId, type, initialMouseY) => {
		const meeting = meetings.find((m) => m.id === meetingId);
		if (!meeting) return;
		initialScrollTopRef.current = gridContainerRef.current?.scrollTop ?? 0;
		setDragState({
			meetingId,
			type,
			initialMouseY,
			initialStartTime: meeting.startTime,
			initialEndTime: meeting.endTime,
			currentStartTime: meeting.startTime,
			currentEndTime: meeting.endTime
		});
	}, [meetings, gridContainerRef]);
	const handleAutoScroll = React.useCallback((mouseY) => {
		if (!gridContainerRef.current) return;
		const container = gridContainerRef.current;
		const rect = container.getBoundingClientRect();
		const relativeY = mouseY - rect.top;
		let scrollSpeed = 0;
		if (relativeY < SCROLL_ZONE) {
			const depth = SCROLL_ZONE - relativeY;
			scrollSpeed = -Math.min(SCROLL_SPEED_MAX, SCROLL_SPEED_BASE + depth / SCROLL_ZONE * SCROLL_SPEED_MAX);
		} else if (relativeY > rect.height - SCROLL_ZONE) {
			const depth = relativeY - (rect.height - SCROLL_ZONE);
			scrollSpeed = Math.min(SCROLL_SPEED_MAX, SCROLL_SPEED_BASE + depth / SCROLL_ZONE * SCROLL_SPEED_MAX);
		}
		if (scrollSpeed !== 0) {
			container.scrollTop += scrollSpeed;
			scrollAnimationRef.current = requestAnimationFrame(() => handleAutoScroll(lastMouseYRef.current));
		} else if (scrollAnimationRef.current) {
			cancelAnimationFrame(scrollAnimationRef.current);
			scrollAnimationRef.current = null;
		}
	}, [gridContainerRef]);
	React.useEffect(() => {
		if (!dragState) return;
		const handleMouseMove = (e) => {
			if (!dragState) return;
			lastMouseYRef.current = e.clientY;
			if (!scrollAnimationRef.current) handleAutoScroll(e.clientY);
			const scrollDelta = (gridContainerRef.current?.scrollTop ?? 0) - initialScrollTopRef.current;
			const deltaY = e.clientY - dragState.initialMouseY + scrollDelta;
			const deltaMinutes = Math.round(deltaY / pixelsPerMinute);
			let newStartTime = new Date(dragState.initialStartTime);
			let newEndTime = new Date(dragState.initialEndTime);
			if (dragState.type === "resize-start") {
				newStartTime = new Date(dragState.initialStartTime.getTime() + deltaMinutes * 6e4);
				newStartTime = snapToInterval(newStartTime, snapInterval);
				const maxStartTime = /* @__PURE__ */ new Date(dragState.initialEndTime.getTime() - MIN_MEETING_DURATION * 6e4);
				if (newStartTime > maxStartTime) newStartTime = maxStartTime;
			} else if (dragState.type === "resize-end") {
				newEndTime = new Date(dragState.initialEndTime.getTime() + deltaMinutes * 6e4);
				newEndTime = snapToInterval(newEndTime, snapInterval);
				const minEndTime = new Date(dragState.initialStartTime.getTime() + MIN_MEETING_DURATION * 6e4);
				if (newEndTime < minEndTime) newEndTime = minEndTime;
			}
			if (dragState.type === "move") {
				newStartTime = new Date(dragState.initialStartTime.getTime() + deltaMinutes * 6e4);
				newStartTime = snapToInterval(newStartTime, snapInterval);
				const durationMs = dragState.initialEndTime.getTime() - dragState.initialStartTime.getTime();
				newEndTime = new Date(newStartTime.getTime() + durationMs);
			}
			setDragState((prev) => prev ? {
				...prev,
				currentStartTime: newStartTime,
				currentEndTime: newEndTime
			} : null);
		};
		const handleMouseUp = () => {
			if (!dragState) return;
			if (scrollAnimationRef.current) {
				cancelAnimationFrame(scrollAnimationRef.current);
				scrollAnimationRef.current = null;
			}
			onDragEnd?.(dragState.meetingId, dragState.currentStartTime, dragState.currentEndTime);
			setDragState(null);
		};
		document.addEventListener("mousemove", handleMouseMove);
		document.addEventListener("mouseup", handleMouseUp);
		return () => {
			document.removeEventListener("mousemove", handleMouseMove);
			document.removeEventListener("mouseup", handleMouseUp);
			if (scrollAnimationRef.current) cancelAnimationFrame(scrollAnimationRef.current);
		};
	}, [
		dragState,
		pixelsPerMinute,
		onDragEnd,
		handleAutoScroll,
		gridContainerRef,
		snapInterval
	]);
	return {
		dragState,
		handleDragStart
	};
}
function DayColumnHeader({ date, isSelected, isDisabled, onClick }) {
	const dayName = format(date, "EEE");
	const dayNumber = format(date, "d");
	const isTodayDate = isToday(date);
	return /* @__PURE__ */ jsxs("button", {
		type: "button",
		onClick,
		disabled: isDisabled,
		"aria-label": format(date, "EEEE, MMMM d, yyyy"),
		className: cn("flex flex-1 flex-col items-center gap-1.5 border-b border-e border-border bg-background p-2 last:border-e-0 transition-colors duration-200 ease-smooth motion-reduce:transition-none", !isDisabled && "hover:bg-muted cursor-pointer", isDisabled && "cursor-not-allowed opacity-50"),
		children: [/* @__PURE__ */ jsx("span", {
			className: cn("text-xs font-medium", "text-quaternary-foreground"),
			children: dayName
		}), /* @__PURE__ */ jsx("div", {
			className: cn("flex size-8 items-center justify-center rounded-full text-xs font-semibold transition-colors duration-200 ease-smooth motion-reduce:transition-none", isSelected ? "bg-primary text-primary-foreground" : isTodayDate ? "bg-primary/20 text-primary" : isDisabled ? "text-quaternary-foreground" : "text-secondary-foreground"),
			children: dayNumber
		})]
	});
}
function MeetingCard({ meeting, variant = "list", onJoin, onClick, maxAttendees = 5 }) {
	const indicatorColor = MEETING_COLOR_MAP[meeting.color || "brand"];
	const startTimeStr = format(meeting.startTime, "h:mm a");
	const endTimeStr = format(meeting.endTime, "h:mm a");
	const visibleAttendees = meeting.attendees.slice(0, maxAttendees);
	const remainingCount = meeting.attendees.length - maxAttendees;
	return /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsx("div", {
		className: cn("flex w-full min-w-0 sm:min-w-[320px] flex-col items-start rounded-xl border border-border bg-background py-4 ps-px pe-4 shadow-xs transition-all duration-200 ease-smooth motion-reduce:transition-none", onClick && "cursor-pointer hover:border-border hover:-translate-y-px hover:shadow-md motion-reduce:hover:translate-y-0"),
		onClick,
		onKeyDown: (e) => {
			if (onClick && (e.key === "Enter" || e.key === " ")) {
				e.preventDefault();
				onClick();
			}
		},
		role: onClick ? "button" : void 0,
		tabIndex: onClick ? 0 : void 0,
		children: /* @__PURE__ */ jsxs("div", {
			className: "flex w-full items-start gap-3",
			children: [/* @__PURE__ */ jsx("div", { className: cn("h-10 w-1.5 shrink-0 rounded-r-lg", indicatorColor) }), /* @__PURE__ */ jsxs("div", {
				className: "flex flex-1 flex-col gap-3",
				children: [/* @__PURE__ */ jsxs("div", {
					className: "flex w-full items-start gap-3",
					children: [/* @__PURE__ */ jsxs("div", {
						className: "flex shrink-0 flex-col gap-1.5 text-nowrap",
						children: [
							/* @__PURE__ */ jsx("span", {
								className: "text-lg font-semibold text-secondary-foreground",
								children: startTimeStr
							}),
							/* @__PURE__ */ jsx("span", {
								className: "text-sm text-quaternary-foreground",
								children: endTimeStr
							}),
							variant === "next" && meeting.minutesUntil !== void 0 && /* @__PURE__ */ jsxs("span", {
								className: "text-sm font-semibold text-destructive",
								children: [
									"In ",
									meeting.minutesUntil,
									" mins"
								]
							})
						]
					}), /* @__PURE__ */ jsxs("div", {
						className: "flex flex-1 flex-col gap-1.5",
						children: [
							/* @__PURE__ */ jsx("span", {
								className: "text-lg font-semibold text-secondary-foreground",
								children: meeting.title
							}),
							/* @__PURE__ */ jsxs("span", {
								className: "text-sm text-secondary-foreground",
								children: ["Host: ", meeting.host]
							}),
							/* @__PURE__ */ jsxs("div", {
								className: "flex items-center gap-1.5",
								children: [/* @__PURE__ */ jsx("span", {
									className: "text-sm text-secondary-foreground",
									children: "Attendees:"
								}), /* @__PURE__ */ jsxs(AvatarGroup, { children: [visibleAttendees.map((attendee) => /* @__PURE__ */ jsx(Avatar, {
									size: "xs",
									children: attendee.avatar ? /* @__PURE__ */ jsx(AvatarImage, {
										src: attendee.avatar,
										alt: attendee.name
									}) : /* @__PURE__ */ jsx(AvatarFallback, { children: attendee.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) })
								}, attendee.id)), remainingCount > 0 && /* @__PURE__ */ jsx(Avatar, {
									size: "xs",
									children: /* @__PURE__ */ jsxs(AvatarFallback, {
										className: "text-[10px]",
										children: ["+", remainingCount]
									})
								})] })]
							})
						]
					})]
				}), variant === "next" && onJoin && /* @__PURE__ */ jsx("div", {
					className: "flex justify-end",
					children: /* @__PURE__ */ jsx(Button, {
						variant: "primary",
						size: "sm",
						onClick: (e) => {
							e.stopPropagation();
							onJoin();
						},
						children: "Join"
					})
				})]
			})]
		})
	}) });
}
function EditableMeetingCard({ meeting, variant = "list", onJoin, onClick, maxAttendees = 5, onDragStart, isDragging = false, currentStartTime, currentEndTime, height, animationOffset = 0, isSwapping = false, onTimeAdjust }) {
	const indicatorColor = MEETING_COLOR_MAP[meeting.color || "brand"];
	const displayStartTime = currentStartTime ?? meeting.startTime;
	const displayEndTime = currentEndTime ?? meeting.endTime;
	const startTimeStr = format(displayStartTime, "h:mm a");
	const endTimeStr = format(displayEndTime, "h:mm a");
	const visibleAttendees = meeting.attendees.slice(0, maxAttendees);
	const remainingCount = meeting.attendees.length - maxAttendees;
	const handleMouseDown = (e, type) => {
		e.preventDefault();
		e.stopPropagation();
		onDragStart?.(meeting.id, type, e.clientY);
	};
	return /* @__PURE__ */ jsxs(motion.div, {
		className: cn("relative flex w-full min-w-0 sm:min-w-[320px] flex-col items-start rounded-xl border border-border bg-background py-4 ps-px pe-4 shadow-xs transition-all duration-200 ease-smooth motion-reduce:transition-none", onClick && !isDragging && "cursor-pointer hover:border-border hover:-translate-y-px hover:shadow-md motion-reduce:hover:translate-y-0", isDragging && "ring-2 ring-primary ring-offset-2 z-10"),
		initial: false,
		animate: {
			height: height ? height : "auto",
			y: animationOffset
		},
		transition: {
			height: {
				type: "spring",
				stiffness: 300,
				damping: 30
			},
			y: isSwapping ? {
				type: "spring",
				stiffness: 300,
				damping: 30
			} : { duration: 0 }
		},
		style: { willChange: isSwapping ? "transform" : "auto" },
		onClick,
		onKeyDown: (e) => {
			if (onClick && (e.key === "Enter" || e.key === " ")) {
				e.preventDefault();
				onClick();
			}
			handleTimeAdjustKeyDown(e, meeting, onTimeAdjust);
		},
		role: onClick ? "button" : void 0,
		tabIndex: onClick ? 0 : void 0,
		children: [
			/* @__PURE__ */ jsx(motion.div, {
				className: "absolute left-0 right-0 top-0 z-20 flex h-8 cursor-ns-resize items-center justify-center rounded-t-xl",
				initial: false,
				animate: { backgroundColor: isDragging ? "var(--primary-alpha-10)" : "transparent" },
				transition: { duration: .15 },
				onMouseDown: (e) => handleMouseDown(e, "resize-start"),
				children: /* @__PURE__ */ jsx(motion.div, {
					className: "flex gap-0.5",
					initial: {
						opacity: 0,
						scale: .8
					},
					animate: {
						opacity: isDragging ? 1 : 0,
						scale: isDragging ? 1 : .8
					},
					transition: { duration: .15 },
					children: /* @__PURE__ */ jsx("div", { className: "h-1 w-8 rounded-full bg-primary" })
				})
			}),
			/* @__PURE__ */ jsxs("div", {
				className: "flex w-full items-start gap-3",
				children: [/* @__PURE__ */ jsx("div", { className: cn("h-10 w-1.5 shrink-0 rounded-r-lg", indicatorColor) }), /* @__PURE__ */ jsxs("div", {
					className: "flex flex-1 flex-col gap-3",
					children: [/* @__PURE__ */ jsxs("div", {
						className: "flex w-full items-start gap-3",
						children: [/* @__PURE__ */ jsxs("div", {
							className: "flex shrink-0 cursor-grab flex-col gap-1.5 text-nowrap active:cursor-grabbing",
							onMouseDown: (e) => handleMouseDown(e, "move"),
							children: [
								/* @__PURE__ */ jsx("span", {
									className: cn("text-lg font-semibold text-secondary-foreground", isDragging && "text-primary"),
									children: startTimeStr
								}),
								/* @__PURE__ */ jsx("span", {
									className: cn("text-sm text-quaternary-foreground", isDragging && "text-primary"),
									children: endTimeStr
								}),
								variant === "next" && meeting.minutesUntil !== void 0 && /* @__PURE__ */ jsxs("span", {
									className: "text-sm font-semibold text-destructive",
									children: [
										"In ",
										meeting.minutesUntil,
										" mins"
									]
								})
							]
						}), /* @__PURE__ */ jsxs("div", {
							className: "flex flex-1 cursor-grab flex-col gap-1.5 active:cursor-grabbing",
							onMouseDown: (e) => handleMouseDown(e, "move"),
							children: [
								/* @__PURE__ */ jsx("span", {
									className: "text-lg font-semibold text-secondary-foreground",
									children: meeting.title
								}),
								/* @__PURE__ */ jsxs("span", {
									className: "text-sm text-secondary-foreground",
									children: ["Host: ", meeting.host]
								}),
								/* @__PURE__ */ jsxs("div", {
									className: "flex items-center gap-1.5",
									children: [/* @__PURE__ */ jsx("span", {
										className: "text-sm text-secondary-foreground",
										children: "Attendees:"
									}), /* @__PURE__ */ jsxs(AvatarGroup, { children: [visibleAttendees.map((attendee) => /* @__PURE__ */ jsx(Avatar, {
										size: "xs",
										children: attendee.avatar ? /* @__PURE__ */ jsx(AvatarImage, {
											src: attendee.avatar,
											alt: attendee.name
										}) : /* @__PURE__ */ jsx(AvatarFallback, { children: attendee.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) })
									}, attendee.id)), remainingCount > 0 && /* @__PURE__ */ jsx(Avatar, {
										size: "xs",
										children: /* @__PURE__ */ jsxs(AvatarFallback, {
											className: "text-[10px]",
											children: ["+", remainingCount]
										})
									})] })]
								})
							]
						})]
					}), variant === "next" && onJoin && /* @__PURE__ */ jsx("div", {
						className: "flex justify-end",
						children: /* @__PURE__ */ jsx(Button, {
							variant: "primary",
							size: "sm",
							onClick: (e) => {
								e.stopPropagation();
								onJoin();
							},
							children: "Join"
						})
					})]
				})]
			}),
			/* @__PURE__ */ jsx(motion.div, {
				className: "absolute bottom-0 left-0 right-0 z-20 flex h-8 cursor-ns-resize items-center justify-center rounded-b-xl",
				initial: false,
				animate: { backgroundColor: isDragging ? "var(--primary-alpha-10)" : "transparent" },
				transition: { duration: .15 },
				onMouseDown: (e) => handleMouseDown(e, "resize-end"),
				children: /* @__PURE__ */ jsx(motion.div, {
					className: "flex gap-0.5",
					initial: {
						opacity: 0,
						scale: .8
					},
					animate: {
						opacity: isDragging ? 1 : 0,
						scale: isDragging ? 1 : .8
					},
					transition: { duration: .15 },
					children: /* @__PURE__ */ jsx("div", { className: "h-1 w-8 rounded-full bg-primary" })
				})
			})
		]
	});
}
function DraggableMeetingBlock({ meeting, gridStartHour, pixelsPerMinute, onClick, onDragStart, isDragging = false, currentStartTime, currentEndTime, onTimeAdjust }) {
	const indicatorColor = MEETING_COLOR_MAP[meeting.color || "brand"];
	const displayStartTime = currentStartTime ?? meeting.startTime;
	const displayEndTime = currentEndTime ?? meeting.endTime;
	const startMinutes = displayStartTime.getHours() * 60 + displayStartTime.getMinutes();
	const endMinutes = displayEndTime.getHours() * 60 + displayEndTime.getMinutes();
	const topOffset = (startMinutes - gridStartHour * 60) * pixelsPerMinute;
	const height = (endMinutes - startMinutes) * pixelsPerMinute;
	const startTimeStr = format(displayStartTime, "h:mm a");
	const endTimeStr = format(displayEndTime, "h:mm a");
	const handleMouseDown = (e, type) => {
		e.preventDefault();
		e.stopPropagation();
		onDragStart?.(meeting.id, type, e.clientY);
	};
	return /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsxs("div", {
		className: cn("absolute inset-x-1 flex cursor-grab rounded-lg border border-border bg-background shadow-sm transition-all duration-200 ease-smooth motion-reduce:transition-none", isDragging && "ring-2 ring-primary ring-offset-1 z-20 shadow-lg", onClick && !isDragging && "hover:border-border"),
		style: {
			top: `${topOffset}px`,
			height: `${height}px`,
			minHeight: "40px"
		},
		onClick,
		onKeyDown: (e) => {
			if (onClick && (e.key === "Enter" || e.key === " ")) {
				e.preventDefault();
				onClick();
			}
			handleTimeAdjustKeyDown(e, meeting, onTimeAdjust);
		},
		role: onClick ? "button" : void 0,
		tabIndex: onClick ? 0 : void 0,
		children: [/* @__PURE__ */ jsx("div", { className: cn("w-1 shrink-0 rounded-s-lg", indicatorColor) }), /* @__PURE__ */ jsxs("div", {
			className: "flex flex-1 flex-col overflow-hidden px-2 py-1",
			children: [
				/* @__PURE__ */ jsxs("div", {
					className: "flex cursor-ns-resize items-center gap-1 text-[10px] text-muted-foreground hover:text-muted-foreground",
					onMouseDown: (e) => handleMouseDown(e, "resize-start"),
					children: [/* @__PURE__ */ jsx("span", { children: "≡" }), /* @__PURE__ */ jsx("span", {
						className: "font-medium text-secondary-foreground",
						children: startTimeStr
					})]
				}),
				/* @__PURE__ */ jsxs("div", {
					className: "flex flex-1 flex-col justify-center gap-0.5 overflow-hidden",
					onMouseDown: (e) => handleMouseDown(e, "move"),
					children: [/* @__PURE__ */ jsx("span", {
						className: "truncate text-xs font-semibold text-secondary-foreground",
						children: meeting.title
					}), /* @__PURE__ */ jsxs("span", {
						className: "truncate text-[10px] text-muted-foreground",
						children: ["Host: ", meeting.host]
					})]
				}),
				/* @__PURE__ */ jsxs("div", {
					className: "flex cursor-ns-resize items-center gap-1 text-[10px] text-muted-foreground hover:text-muted-foreground",
					onMouseDown: (e) => handleMouseDown(e, "resize-end"),
					children: [/* @__PURE__ */ jsx("span", { children: "≡" }), /* @__PURE__ */ jsx("span", {
						className: "font-medium text-secondary-foreground",
						children: endTimeStr
					})]
				})
			]
		})]
	}) });
}
function TimeGrid({ weekDays, meetings, timeInterval, gridStartHour, gridEndHour, onMeetingClick, onMeetingTimeChange, onMeetingsChange, onTimeAdjust }) {
	const gridRef = React.useRef(null);
	const pixelsPerMinute = 60 / 60;
	const { dragState, handleDragStart } = useDrag({
		meetings,
		pixelsPerMinute,
		gridContainerRef: gridRef,
		onDragEnd: React.useCallback((meetingId, newStartTime, newEndTime) => {
			const meeting = meetings.find((m) => m.id === meetingId);
			if (!meeting) return;
			onMeetingTimeChange?.(meeting, newStartTime, newEndTime);
			if (onMeetingsChange) onMeetingsChange(meetings.map((m) => m.id === meetingId ? {
				...m,
				startTime: newStartTime,
				endTime: newEndTime
			} : m));
		}, [
			meetings,
			onMeetingTimeChange,
			onMeetingsChange
		]),
		snapInterval: timeInterval
	});
	const hourRange = React.useMemo(() => {
		let startHour = gridStartHour ?? 8;
		let endHour = gridEndHour ?? 18;
		if (!gridStartHour || !gridEndHour) {
			const weekStart = weekDays[0];
			const weekEnd = addDays(weekDays[weekDays.length - 1], 1);
			const weekMeetings = meetings.filter((m) => m.startTime >= weekStart && m.startTime < weekEnd);
			if (weekMeetings.length > 0) {
				const earliestHour = Math.min(...weekMeetings.map((m) => m.startTime.getHours()));
				const latestHour = Math.max(...weekMeetings.map((m) => m.endTime.getHours()));
				if (!gridStartHour) startHour = Math.max(0, earliestHour - 1);
				if (!gridEndHour) endHour = Math.min(23, latestHour + 1);
			}
		}
		return {
			startHour,
			endHour
		};
	}, [
		weekDays,
		meetings,
		gridStartHour,
		gridEndHour
	]);
	const timeSlots = React.useMemo(() => {
		const slots = [];
		const baseDate = /* @__PURE__ */ new Date();
		baseDate.setHours(hourRange.startHour, 0, 0, 0);
		const totalMinutes = (hourRange.endHour - hourRange.startHour + 1) * 60;
		const slotCount = Math.ceil(totalMinutes / timeInterval);
		for (let i = 0; i < slotCount; i++) {
			const slotTime = new Date(baseDate);
			slotTime.setMinutes(baseDate.getMinutes() + i * timeInterval);
			slots.push(slotTime);
		}
		return slots;
	}, [hourRange, timeInterval]);
	React.useEffect(() => {
		if (gridRef.current && meetings.length > 0) {
			const weekStart = weekDays[0];
			const weekEnd = addDays(weekDays[weekDays.length - 1], 1);
			const weekMeetings = meetings.filter((m) => m.startTime >= weekStart && m.startTime < weekEnd);
			if (weekMeetings.length > 0) {
				const earliestHour = weekMeetings.reduce((prev, curr) => prev.startTime < curr.startTime ? prev : curr).startTime.getHours();
				const scrollTop = (Math.max(0, earliestHour - 1) - hourRange.startHour) * (pixelsPerMinute * 60);
				gridRef.current.scrollTop = scrollTop;
			}
		}
	}, [
		weekDays,
		meetings,
		hourRange.startHour,
		pixelsPerMinute
	]);
	return /* @__PURE__ */ jsxs("div", {
		ref: gridRef,
		className: "relative flex overflow-y-auto",
		style: { maxHeight: "min(600px, 70vh)" },
		children: [/* @__PURE__ */ jsx("div", {
			className: "sticky start-0 z-10 flex shrink-0 flex-col border-e border-border bg-background",
			children: timeSlots.map((slot, index) => {
				const isHourMark = slot.getMinutes() === 0;
				return /* @__PURE__ */ jsx("div", {
					className: "relative flex items-start justify-end pe-2 text-xs text-quaternary-foreground",
					style: { height: `${timeInterval * pixelsPerMinute}px` },
					children: isHourMark && /* @__PURE__ */ jsx("span", {
						className: "absolute -top-2",
						children: format(slot, "h a")
					})
				}, index);
			})
		}), /* @__PURE__ */ jsx("div", {
			className: "relative flex flex-1",
			children: weekDays.map((day) => {
				const dayStart = startOfDay(day);
				const dayEnd = addDays(dayStart, 1);
				const dayMeetings = meetings.filter((m) => m.startTime >= dayStart && m.startTime < dayEnd);
				return /* @__PURE__ */ jsxs("div", {
					className: "relative flex-1 border-e border-border last:border-e-0",
					children: [timeSlots.map((_slot, slotIndex) => /* @__PURE__ */ jsx("div", {
						className: "border-b border-border",
						style: { height: `${timeInterval * pixelsPerMinute}px` }
					}, slotIndex)), dayMeetings.map((meeting) => {
						const isBeingDragged = dragState?.meetingId === meeting.id;
						return /* @__PURE__ */ jsx(DraggableMeetingBlock, {
							meeting,
							gridStartHour: hourRange.startHour,
							pixelsPerMinute,
							onClick: onMeetingClick ? () => onMeetingClick(meeting) : void 0,
							onDragStart: handleDragStart,
							isDragging: isBeingDragged,
							currentStartTime: isBeingDragged ? dragState.currentStartTime : void 0,
							currentEndTime: isBeingDragged ? dragState.currentEndTime : void 0,
							onTimeAdjust
						}, meeting.id);
					})]
				}, day.toISOString());
			})
		})]
	});
}
function ViewToggle({ viewMode, onChange, isTouchOnly }) {
	if (isTouchOnly) return null;
	return /* @__PURE__ */ jsxs("div", {
		role: "tablist",
		className: "flex items-center gap-0.5 rounded-lg border border-border bg-background p-0.5",
		children: [
			/* @__PURE__ */ jsx("button", {
				type: "button",
				role: "tab",
				"aria-selected": viewMode === "list",
				onClick: () => onChange("list"),
				className: cn("rounded-md px-3 py-1.5 text-sm font-medium transition-colors duration-200 ease-smooth motion-reduce:transition-none", viewMode === "list" ? "bg-accent text-foreground shadow-xs" : "text-muted-foreground hover:text-foreground"),
				children: "List"
			}),
			/* @__PURE__ */ jsx("button", {
				type: "button",
				role: "tab",
				"aria-selected": viewMode === "list-edit",
				onClick: () => onChange("list-edit"),
				className: cn("rounded-md px-3 py-1.5 text-sm font-medium transition-colors duration-200 ease-smooth motion-reduce:transition-none", viewMode === "list-edit" ? "bg-accent text-foreground shadow-xs" : "text-muted-foreground hover:text-foreground"),
				children: "Edit"
			}),
			/* @__PURE__ */ jsx("button", {
				type: "button",
				role: "tab",
				"aria-selected": viewMode === "grid",
				onClick: () => onChange("grid"),
				className: cn("rounded-md px-3 py-1.5 text-sm font-medium transition-colors duration-200 ease-smooth motion-reduce:transition-none", viewMode === "grid" ? "bg-accent text-foreground shadow-xs" : "text-muted-foreground hover:text-foreground"),
				children: "Grid"
			})
		]
	});
}
/**
* @deprecated Use `Calendar` with `view="week"` instead. See migration guide in
* docs/superpowers/specs/2026-04-17-calendar-redesign-design.md
*/
function WeekCalendar({ value = /* @__PURE__ */ new Date(), onChange, minDate, maxDate, meetings = [], onMeetingClick, onJoinMeeting, className, dir = "ltr", weekStartsOn = 1, maxAttendees = 5, showNextMeeting = true, showAllMeetings = true, viewMode: viewModeProp, onViewModeChange, timeInterval = 30, gridStartHour, gridEndHour, listEditPixelsPerMinute = 2, onMeetingTimeChange, onMeetingsChange, showViewModeToggle = false }) {
	const [currentDate, setCurrentDate] = React.useState(value);
	const isRtl = dir === "rtl";
	const touchDetectRef = React.useRef(null);
	const [isTouchOnly, setIsTouchOnly] = React.useState(false);
	React.useEffect(() => {
		const win = touchDetectRef.current?.ownerDocument.defaultView;
		if (!win) return;
		setIsTouchOnly(!win.matchMedia("(pointer: fine)").matches);
	}, []);
	const [internalViewMode, setInternalViewMode] = React.useState("list");
	const viewMode = viewModeProp ?? internalViewMode;
	const handleViewModeChange = React.useCallback((mode) => {
		if (isTouchOnly && (mode === "grid" || mode === "list-edit")) return;
		setInternalViewMode(mode);
		onViewModeChange?.(mode);
	}, [isTouchOnly, onViewModeChange]);
	const listEditRef = React.useRef(null);
	const LIST_EDIT_PIXELS_PER_MINUTE = 1;
	const updateMeetingTime = React.useCallback((meetingId, newStartTime, newEndTime) => {
		const meeting = meetings.find((m) => m.id === meetingId);
		if (!meeting) return;
		onMeetingTimeChange?.(meeting, newStartTime, newEndTime);
		if (onMeetingsChange) onMeetingsChange(meetings.map((m) => m.id === meetingId ? {
			...m,
			startTime: newStartTime,
			endTime: newEndTime
		} : m));
	}, [
		meetings,
		onMeetingTimeChange,
		onMeetingsChange
	]);
	const { dragState: listEditDragState, handleDragStart: handleListEditDragStart } = useDrag({
		meetings,
		pixelsPerMinute: LIST_EDIT_PIXELS_PER_MINUTE,
		gridContainerRef: listEditRef,
		onDragEnd: updateMeetingTime
	});
	const [swapOffsets, setSwapOffsets] = React.useState(/* @__PURE__ */ new Map());
	const [swappingIds, setSwappingIds] = React.useState(/* @__PURE__ */ new Set());
	const prevOrderRef = React.useRef([]);
	const isDateDisabled = React.useCallback((date) => {
		const dayStart = startOfDay(date);
		if (minDate && isBefore(dayStart, startOfDay(minDate))) return true;
		if (maxDate && isBefore(startOfDay(maxDate), dayStart)) return true;
		return false;
	}, [minDate, maxDate]);
	const handleDayClick = React.useCallback((date) => {
		if (!isDateDisabled(date)) {
			setCurrentDate(date);
			onChange?.(date);
		}
	}, [isDateDisabled, onChange]);
	const weekStart = startOfWeek(currentDate, { weekStartsOn });
	const weekEnd = endOfWeek(currentDate, { weekStartsOn });
	const weekNumber = getWeek(currentDate, { weekStartsOn });
	const weekDays = React.useMemo(() => {
		return Array.from({ length: 7 }, (_, i) => addDays(weekStart, i));
	}, [weekStart]);
	const nextMeeting = React.useMemo(() => {
		const now = /* @__PURE__ */ new Date();
		return meetings.filter((m) => m.startTime > now).sort((a, b) => a.startTime.getTime() - b.startTime.getTime())[0];
	}, [meetings]);
	const allMeetings = React.useMemo(() => {
		return meetings.filter((m) => m.startTime >= weekStart && m.startTime <= weekEnd).sort((a, b) => a.startTime.getTime() - b.startTime.getTime());
	}, [
		meetings,
		weekStart,
		weekEnd
	]);
	const allMeetingsSortedByDrag = React.useMemo(() => {
		if (!listEditDragState) return allMeetings;
		const getEffectiveStartTime = (meeting) => {
			if (meeting.id === listEditDragState.meetingId) return listEditDragState.currentStartTime;
			return meeting.startTime;
		};
		return [...allMeetings].sort((a, b) => getEffectiveStartTime(a).getTime() - getEffectiveStartTime(b).getTime());
	}, [allMeetings, listEditDragState]);
	React.useEffect(() => {
		let timeoutId;
		if (!listEditDragState || viewMode !== "list-edit") {
			if (swapOffsets.size > 0) {
				setSwapOffsets(/* @__PURE__ */ new Map());
				setSwappingIds(/* @__PURE__ */ new Set());
			}
			prevOrderRef.current = allMeetingsSortedByDrag.map((m) => m.id);
			return;
		}
		const currentOrder = allMeetingsSortedByDrag.map((m) => m.id);
		const prevOrder = prevOrderRef.current;
		const draggedId = listEditDragState.meetingId;
		const newOffsets = /* @__PURE__ */ new Map();
		const newSwapping = /* @__PURE__ */ new Set();
		for (let i = 0; i < currentOrder.length; i++) {
			const meetingId = currentOrder[i];
			if (meetingId === draggedId) continue;
			const prevIndex = prevOrder.indexOf(meetingId);
			const currentIndex = i;
			if (prevIndex !== -1 && prevIndex !== currentIndex) {
				const meeting = allMeetingsSortedByDrag.find((m) => m.id === meetingId);
				const draggedMeeting = allMeetingsSortedByDrag.find((m) => m.id === draggedId);
				if (meeting && draggedMeeting) {
					const draggedHeight = calculateCardHeight(listEditDragState.currentStartTime, listEditDragState.currentEndTime, listEditPixelsPerMinute);
					const direction = prevIndex < currentIndex ? -1 : 1;
					newOffsets.set(meetingId, direction * (draggedHeight + 16));
					newSwapping.add(meetingId);
				}
			}
		}
		if (newOffsets.size > 0) {
			setSwapOffsets(newOffsets);
			setSwappingIds(newSwapping);
			timeoutId = setTimeout(() => {
				setSwapOffsets(/* @__PURE__ */ new Map());
				setSwappingIds(/* @__PURE__ */ new Set());
			}, SWAP_ANIMATION_DURATION);
		}
		prevOrderRef.current = currentOrder;
		return () => {
			if (timeoutId) clearTimeout(timeoutId);
		};
	}, [
		allMeetingsSortedByDrag,
		listEditDragState,
		viewMode,
		listEditPixelsPerMinute
	]);
	const handlePreviousWeek = () => {
		const newDate = subWeeks(currentDate, 1);
		setCurrentDate(newDate);
		onChange?.(newDate);
	};
	const handleNextWeek = () => {
		const newDate = addWeeks(currentDate, 1);
		setCurrentDate(newDate);
		onChange?.(newDate);
	};
	const handleToday = () => {
		const today = /* @__PURE__ */ new Date();
		setCurrentDate(today);
		onChange?.(today);
	};
	return /* @__PURE__ */ jsxs("div", {
		ref: touchDetectRef,
		className: cn("isolate flex flex-col border border-border bg-background shadow-xs", className),
		dir,
		children: [
			/* @__PURE__ */ jsxs("div", {
				className: "flex flex-col gap-5 border-b border-border px-4 py-5",
				children: [/* @__PURE__ */ jsxs("div", {
					className: "flex flex-col gap-0.5",
					children: [/* @__PURE__ */ jsxs("div", {
						className: "flex items-center gap-2",
						children: [/* @__PURE__ */ jsx("span", {
							className: "text-lg font-semibold text-foreground",
							children: format(currentDate, "MMMM yyyy")
						}), /* @__PURE__ */ jsxs(Badge, {
							variant: "outline",
							shape: "rounded",
							color: "secondary",
							size: "xs",
							children: ["Week ", weekNumber]
						})]
					}), /* @__PURE__ */ jsxs("span", {
						className: "text-sm text-muted-foreground",
						children: [
							format(weekStart, "MMM d, yyyy"),
							" –",
							" ",
							format(weekEnd, "MMM d, yyyy")
						]
					})]
				}), /* @__PURE__ */ jsxs("div", {
					className: "flex w-full overflow-hidden rounded-lg border border-border shadow-xs",
					children: [
						/* @__PURE__ */ jsx("button", {
							type: "button",
							onClick: handlePreviousWeek,
							className: "flex items-center justify-center border-e border-border bg-background px-3 py-2 hover:bg-muted transition-colors duration-200 ease-smooth motion-reduce:transition-none",
							"aria-label": "Previous week",
							children: isRtl ? /* @__PURE__ */ jsx(ArrowRight, { className: "size-5 text-secondary-foreground" }) : /* @__PURE__ */ jsx(ArrowLeft, { className: "size-5 text-secondary-foreground" })
						}),
						/* @__PURE__ */ jsx("button", {
							type: "button",
							onClick: handleToday,
							className: "flex flex-1 items-center justify-center border-e border-border bg-background px-4 py-2 text-sm font-semibold text-secondary-foreground hover:bg-muted transition-colors duration-200 ease-smooth motion-reduce:transition-none",
							children: "Today"
						}),
						/* @__PURE__ */ jsx("button", {
							type: "button",
							onClick: handleNextWeek,
							className: "flex items-center justify-center bg-background px-3 py-2 hover:bg-muted transition-colors duration-200 ease-smooth motion-reduce:transition-none",
							"aria-label": "Next week",
							children: isRtl ? /* @__PURE__ */ jsx(ArrowLeft, { className: "size-5 text-secondary-foreground" }) : /* @__PURE__ */ jsx(ArrowRight, { className: "size-5 text-secondary-foreground" })
						})
					]
				})]
			}),
			/* @__PURE__ */ jsxs("div", {
				className: "relative flex shadow-sm",
				children: [weekDays.map((day) => /* @__PURE__ */ jsx(DayColumnHeader, {
					date: day,
					isSelected: isSameDay(day, currentDate),
					isDisabled: isDateDisabled(day),
					onClick: () => handleDayClick(day)
				}, day.toISOString())), showViewModeToggle && /* @__PURE__ */ jsx("div", {
					className: "absolute end-2 top-1/2 -translate-y-1/2",
					children: /* @__PURE__ */ jsx(ViewToggle, {
						viewMode,
						onChange: handleViewModeChange,
						isTouchOnly
					})
				})]
			}),
			viewMode === "grid" ? /* @__PURE__ */ jsx(TimeGrid, {
				weekDays,
				meetings,
				timeInterval,
				gridStartHour,
				gridEndHour,
				onMeetingClick,
				onMeetingTimeChange,
				onMeetingsChange,
				onTimeAdjust: updateMeetingTime
			}) : viewMode === "list-edit" ? /* @__PURE__ */ jsx(ScrollArea, {
				className: "h-[min(600px,70vh)]",
				children: /* @__PURE__ */ jsxs("div", {
					ref: listEditRef,
					className: "flex flex-1 flex-col gap-8 px-6 py-4",
					children: [
						showNextMeeting && nextMeeting && /* @__PURE__ */ jsxs("div", {
							className: "flex flex-col gap-4",
							children: [/* @__PURE__ */ jsx("h3", {
								className: "text-lg font-semibold text-foreground",
								children: "Next Meeting"
							}), (() => {
								const height = calculateCardHeight(listEditDragState?.meetingId === nextMeeting.id ? listEditDragState.currentStartTime : nextMeeting.startTime, listEditDragState?.meetingId === nextMeeting.id ? listEditDragState.currentEndTime : nextMeeting.endTime, listEditPixelsPerMinute);
								return /* @__PURE__ */ jsx(EditableMeetingCard, {
									meeting: nextMeeting,
									variant: "next",
									onJoin: onJoinMeeting ? () => onJoinMeeting(nextMeeting) : void 0,
									onClick: onMeetingClick ? () => onMeetingClick(nextMeeting) : void 0,
									maxAttendees,
									onDragStart: handleListEditDragStart,
									isDragging: listEditDragState?.meetingId === nextMeeting.id,
									currentStartTime: listEditDragState?.meetingId === nextMeeting.id ? listEditDragState.currentStartTime : void 0,
									currentEndTime: listEditDragState?.meetingId === nextMeeting.id ? listEditDragState.currentEndTime : void 0,
									height,
									animationOffset: swapOffsets.get(nextMeeting.id) ?? 0,
									isSwapping: swappingIds.has(nextMeeting.id),
									onTimeAdjust: updateMeetingTime
								});
							})()]
						}),
						showAllMeetings && allMeetingsSortedByDrag.length > 0 && /* @__PURE__ */ jsxs("div", {
							className: "flex flex-col gap-4",
							children: [/* @__PURE__ */ jsx("h3", {
								className: "text-lg font-semibold text-foreground",
								children: "All Meetings"
							}), /* @__PURE__ */ jsx("div", {
								className: "flex flex-col gap-4",
								children: allMeetingsSortedByDrag.map((meeting) => {
									const height = calculateCardHeight(listEditDragState?.meetingId === meeting.id ? listEditDragState.currentStartTime : meeting.startTime, listEditDragState?.meetingId === meeting.id ? listEditDragState.currentEndTime : meeting.endTime, listEditPixelsPerMinute);
									return /* @__PURE__ */ jsx(EditableMeetingCard, {
										meeting,
										variant: "list",
										onClick: onMeetingClick ? () => onMeetingClick(meeting) : void 0,
										maxAttendees,
										onDragStart: handleListEditDragStart,
										isDragging: listEditDragState?.meetingId === meeting.id,
										currentStartTime: listEditDragState?.meetingId === meeting.id ? listEditDragState.currentStartTime : void 0,
										currentEndTime: listEditDragState?.meetingId === meeting.id ? listEditDragState.currentEndTime : void 0,
										height,
										animationOffset: swapOffsets.get(meeting.id) ?? 0,
										isSwapping: swappingIds.has(meeting.id),
										onTimeAdjust: updateMeetingTime
									}, meeting.id);
								})
							})]
						}),
						(!showNextMeeting || !nextMeeting) && (!showAllMeetings || allMeetingsSortedByDrag.length === 0) && /* @__PURE__ */ jsx("div", {
							className: "flex flex-1 items-center justify-center py-12",
							children: /* @__PURE__ */ jsx("span", {
								className: "text-sm text-quaternary-foreground",
								children: "No meetings scheduled"
							})
						})
					]
				})
			}) : /* @__PURE__ */ jsx(ScrollArea, {
				className: "h-[min(600px,70vh)]",
				children: /* @__PURE__ */ jsxs("div", {
					className: "flex flex-1 flex-col gap-8 px-6 py-4",
					children: [
						showNextMeeting && nextMeeting && /* @__PURE__ */ jsxs("div", {
							className: "flex flex-col gap-4",
							children: [/* @__PURE__ */ jsx("h3", {
								className: "text-lg font-semibold text-foreground",
								children: "Next Meeting"
							}), /* @__PURE__ */ jsx(MeetingCard, {
								meeting: nextMeeting,
								variant: "next",
								onJoin: onJoinMeeting ? () => onJoinMeeting(nextMeeting) : void 0,
								onClick: onMeetingClick ? () => onMeetingClick(nextMeeting) : void 0,
								maxAttendees
							})]
						}),
						showAllMeetings && allMeetings.length > 0 && /* @__PURE__ */ jsxs("div", {
							className: "flex flex-col gap-4",
							children: [/* @__PURE__ */ jsx("h3", {
								className: "text-lg font-semibold text-foreground",
								children: "All Meetings"
							}), /* @__PURE__ */ jsx("div", {
								className: "flex flex-col gap-4",
								children: allMeetings.map((meeting) => /* @__PURE__ */ jsx(MeetingCard, {
									meeting,
									variant: "list",
									onClick: onMeetingClick ? () => onMeetingClick(meeting) : void 0,
									maxAttendees
								}, meeting.id))
							})]
						}),
						(!showNextMeeting || !nextMeeting) && (!showAllMeetings || allMeetings.length === 0) && /* @__PURE__ */ jsxs("div", {
							className: "flex flex-1 flex-col items-center justify-center gap-3 py-12 animate-in fade-in duration-300 motion-reduce:animate-none",
							children: [/* @__PURE__ */ jsx(CalendarCheck2, { className: "size-8 text-muted-foreground/50" }), /* @__PURE__ */ jsxs("div", {
								className: "flex flex-col items-center gap-1",
								children: [/* @__PURE__ */ jsx("span", {
									className: "text-sm font-medium text-secondary-foreground",
									children: "Your schedule is clear"
								}), /* @__PURE__ */ jsx("span", {
									className: "text-xs text-quaternary-foreground",
									children: "No meetings for this week"
								})]
							})]
						})
					]
				})
			})
		]
	});
}
WeekCalendar.displayName = "WeekCalendar";
//#endregion
export { MeetingCard, WeekCalendar };

//# sourceMappingURL=index378.js.map