"use client"; import { AnimatePresence, motion } from "framer-motion"; import { Bot, CalendarPlus, Download, FileUp, ImageIcon, Info, Loader2, LogIn, Sparkles, Trash2, X, } from "lucide-react"; import Image from "next/image"; import { useEffect, useRef, useState } from "react"; import { IcsFilePicker } from "@/components/ics-file-picker"; import { ImagePicker } from "@/components/image-picker"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { HoverCard, HoverCardContent, HoverCardTrigger, } from "@/components/ui/hover-card"; import { Kbd, KbdGroup } from "@/components/ui/kbd"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Skeleton } from "@/components/ui/skeleton"; import { Textarea } from "@/components/ui/textarea"; import { SHORTCUT_DEFINITIONS, detectOs, resolveKeys, type Os, } from "@/lib/keyboard-shortcuts"; import type { CalendarEvent } from "@/lib/types"; // ─── OS detection hook ──────────────────────────────────────────────────────── function useOs(): Os { // Start with "unknown" for SSR — effect sets the real value after hydration const [os, setOs] = useState("unknown"); useEffect(() => { setOs(detectOs()); }, []); return os; } // ─── Shared shortcuts list (rendered in both HoverCard and Popover) ─────────── function ShortcutsList({ os }: { os: Os }) { return ( <>

Keyboard shortcuts

); } // ─── Types ──────────────────────────────────────────────────────────────────── interface AIToolbarProps { isAuthenticated: boolean; isPending: boolean; aiPrompt: string; setAiPrompt: (prompt: string) => void; aiLoading: boolean; imagePreview: string | null; onImageSelect: (file: File) => void; onImageClear: () => void; onAiCreate: () => void; onAiSummarize: () => void; onSummaryDismiss: () => void; summary: string | null; summaryUpdated: string | null; // event actions events: CalendarEvent[]; onAddEvent: () => void; onImport: (file: File) => void; onExport: () => void; onClearAll: () => void; } // ─── Component ──────────────────────────────────────────────────────────────── export const AIToolbar = ({ isAuthenticated, isPending, aiPrompt, setAiPrompt, aiLoading, imagePreview, onImageSelect, onImageClear, onAiCreate, onAiSummarize, onSummaryDismiss, summary, summaryUpdated, events, onAddEvent, onImport, onExport, onClearAll, }: AIToolbarProps) => { // Ref to imperatively open the file picker from the keyboard shortcut const imageTriggerRef = useRef<{ open: () => void }>(null); // When the popover is pinned open, suppress the hover card so they don't overlap const [isPopoverOpen, setIsPopoverOpen] = useState(false); // Detect OS after hydration for keyboard shortcut glyphs const os = useOs(); if (isPending) { return (
); } return (
{/* ── Zone 1: AI ───────────────────────────────────────────────────────── */}
{isAuthenticated ? ( /* ── Authenticated: full prompt composer ── */
{/* Header */}
AI
{/* Textarea */}