Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/components/ui/commandPalettes/CommandPalette.tsx
T

59 lines
1.7 KiB
TypeScript

import { createContext, lazy, ReactNode, Suspense, useContext, useEffect, useMemo, useState } from "react";
import type { ScopedCommandAction } from "~/services/command-registry/commandRegistry";
type CommandPaletteContextValue = {
open: boolean;
setOpen: (open: boolean) => void;
toggle: () => void;
};
const CommandPaletteContext = createContext<CommandPaletteContextValue | null>(null);
const CommandPaletteDialog = lazy(() => import("./CommandPaletteDialog"));
export function useCommandPalette() {
const context = useContext(CommandPaletteContext);
return context ?? { open: false, setOpen: () => undefined, toggle: () => undefined };
}
interface Props {
layout?: "app" | "admin" | "docs";
children: ReactNode;
actions?: ScopedCommandAction[];
}
export default function CommandPalette({ layout, children, actions }: Props) {
const [open, setOpen] = useState(false);
const contextValue = useMemo(
() => ({
open,
setOpen,
toggle: () => setOpen((value) => !value),
}),
[open]
);
useEffect(() => {
function onKeyDown(event: KeyboardEvent) {
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
event.preventDefault();
setOpen((value) => !value);
}
}
document.addEventListener("keydown", onKeyDown);
return () => document.removeEventListener("keydown", onKeyDown);
}, []);
return (
<CommandPaletteContext.Provider value={contextValue}>
{open ? (
<Suspense fallback={null}>
<CommandPaletteDialog actions={actions} layout={layout} open={open} setOpen={setOpen} />
</Suspense>
) : null}
{children}
</CommandPaletteContext.Provider>
);
}