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 (
)
}