import * as React from "react" import * as DialogPrimitive from "@radix-ui/react-dialog" import { Command } from "cmdk" import { Dialog, DialogPortal, DialogHeader, DialogTitle, DialogDescription, } from "@/components/ui/dialog" import { CommandGroup } from "./command-group" import { CommandAction, createCommandGroups } from "./command-data" import { useAccount, useAccountOrGuest } from "@/lib/providers/jazz-provider" import { useAtom } from "jotai" import { useCommandActions } from "~/hooks/actions/use-command-actions" import { filterItems, getTopics, getPersonalLinks, getPersonalPages, handleAction, } from "./utils" import { searchSafeRegExp } from "~/lib/utils" import { commandPaletteOpenAtom } from "~/store/any-store" export function CommandPalette() { const { me } = useAccountOrGuest() if (me._type === "Anonymous") return null return } export function RealCommandPalette() { const { me } = useAccount({ root: { personalLinks: [], personalPages: [] } }) const dialogRef = React.useRef(null) const [inputValue, setInputValue] = React.useState("") const [activePage, setActivePage] = React.useState("home") const [open, setOpen] = useAtom(commandPaletteOpenAtom) const actions = useCommandActions() const commandGroups = React.useMemo( () => me && createCommandGroups(actions, me), [actions, me], ) const bounce = React.useCallback(() => { if (dialogRef.current) { dialogRef.current.style.transform = "scale(0.99) translateX(-50%)" setTimeout(() => { if (dialogRef.current) { dialogRef.current.style.transform = "" } }, 100) } }, []) const handleKeyDown = React.useCallback( (e: React.KeyboardEvent) => { if (e.key === "Enter") { bounce() } if (activePage !== "home" && !inputValue && e.key === "Backspace") { e.preventDefault() setActivePage("home") setInputValue("") bounce() } }, [activePage, inputValue, bounce], ) const topics = React.useMemo(() => getTopics(actions), [actions]) const personalLinks = React.useMemo( () => getPersonalLinks(me?.root.personalLinks || [], actions), [me?.root.personalLinks, actions], ) const personalPages = React.useMemo( () => getPersonalPages(me?.root.personalPages || [], actions), [me?.root.personalPages, actions], ) const getFilteredCommands = React.useCallback(() => { if (!commandGroups) return [] const searchRegex = searchSafeRegExp(inputValue) if (activePage === "home") { if (!inputValue) { return commandGroups.home } const allGroups = [ ...Object.values(commandGroups).flat(), personalLinks, personalPages, topics, ] return allGroups .map((group) => ({ heading: group.heading, items: filterItems(group.items, searchRegex), })) .filter((group) => group.items.length > 0) } switch (activePage) { case "searchLinks": return [ ...commandGroups.searchLinks, { items: filterItems(personalLinks.items, searchRegex) }, ] case "searchPages": return [ ...commandGroups.searchPages, { items: filterItems(personalPages.items, searchRegex) }, ] default: { const pageCommands = commandGroups[activePage] if (!inputValue) return pageCommands return pageCommands .map((group) => ({ heading: group.heading, items: filterItems(group.items, searchRegex), })) .filter((group) => group.items.length > 0) } } }, [ inputValue, activePage, commandGroups, personalLinks, personalPages, topics, ]) const handleActionWrapper = React.useCallback( (action: CommandAction, payload?: any) => { handleAction(action, payload, { setActivePage, setInputValue, bounce, closeDialog: () => setOpen(false), }) }, [bounce, setOpen], ) React.useEffect(() => { if (!open) { setInputValue("") setActivePage("home") } }, [open, setActivePage, setInputValue]) const filteredCommands = React.useMemo( () => getFilteredCommands(), [getFilteredCommands], ) const commandKey = React.useMemo(() => { return filteredCommands .map((group) => { const itemsKey = group.items .map((item) => `${item.label}-${item.value}`) .join("|") return `${group.heading}:${itemsKey}` }) .join("__") }, [filteredCommands]) if (!me) return null return ( Command Palette Search for commands and actions
No results found. {filteredCommands.map((group, index, array) => ( ))}
) }