"use client"
/**
* CommandMenu — ⌘K palette shell (Dialog + Command). Data comes from `CommandMenuProvider`
* (`lib/command-menu-config.ts`); no hard-coded nav or copy here.
*/
import { useRouter } from "@/lib/router-compat"
import { useCallback, useEffect, useRef, useState } from "react"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/components/ui/command"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Kbd } from "@/components/ui/kbd"
import { useAskLeo } from "@/components/ask-leo-sidebar"
import { useCommandMenuConfig } from "@/contexts/command-menu-context"
import type { CommandMenuItem } from "@/lib/command-menu-config"
/** Dispatched to open the palette from sidebar and other callers (avoid synthetic ⌘K). */
export const OPEN_COMMAND_MENU_EVENT = "exxat:open-command-menu"
export function requestOpenCommandMenu() {
window.dispatchEvent(new CustomEvent(OPEN_COMMAND_MENU_EVENT))
}
function CommandMenuItemRow({
item,
onLink,
onLeo,
}: {
item: CommandMenuItem
onLink: (href: string) => void
onLeo: (prompt: string) => void
}) {
const isLeo = Boolean(item.askLeoPrompt)
const iconClass = isLeo
? "fa-duotone fa-solid fa-star-christmas w-5 shrink-0 text-center text-brand"
: `${item.icon ?? "fa-light fa-arrow-right"} w-5 shrink-0 text-center`
return (
{
if (item.askLeoPrompt) onLeo(item.askLeoPrompt)
else if (item.href) onLink(item.href)
}}
>
{item.label}
)
}
export function CommandMenu() {
const config = useCommandMenuConfig()
const [open, setOpen] = useState(false)
const [inputValue, setInputValue] = useState("")
const searchInputRef = useRef(null)
const router = useRouter()
const { openWithPrompt } = useAskLeo()
useEffect(() => {
const down = (e: KeyboardEvent) => {
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
e.preventDefault()
setOpen((prev) => !prev)
}
}
document.addEventListener("keydown", down)
return () => document.removeEventListener("keydown", down)
}, [])
useEffect(() => {
const onOpenRequest = () => setOpen(true)
window.addEventListener(OPEN_COMMAND_MENU_EVENT, onOpenRequest)
return () => window.removeEventListener(OPEN_COMMAND_MENU_EVENT, onOpenRequest)
}, [])
const navigate = useCallback(
(href: string) => {
setOpen(false)
setInputValue("")
router.push(href)
},
[router],
)
const sendLeoSuggestion = useCallback(
(prompt: string) => {
setOpen(false)
setInputValue("")
openWithPrompt(prompt)
},
[openWithPrompt],
)
return (
)
}