import React, {useState, useEffect, useMemo} from 'react' import { KBarProvider, KBarPortal, KBarPositioner, KBarAnimator, KBarSearch, KBarResults, useMatches, useRegisterActions, useKBar, createAction } from "kbar"; import classNames from 'classnames'; const searchStyle = { padding: "12px 16px", fontSize: "16px", width: "100%", boxSizing: "border-box", outline: "none" }; const animatorStyle = { maxWidth: "600px", width: "100%", borderRadius: "8px", overflow: "hidden" }; const groupNameStyle = { padding: "8px 16px", fontSize: "10px", textTransform: "uppercase", opacity: 0.75, }; function RenderResults() { const { results, rootActionId } = useMatches(); return ( typeof item === "string" ? (
{item}
) : ( ) } /> ); } const ResultItem = React.forwardRef( ( { action, active, currentRootActionId, }, ref ) => { const ancestors = React.useMemo(() => { if (!currentRootActionId) return action.ancestors; const index = action.ancestors.findIndex( (ancestor) => ancestor.id === currentRootActionId ); // +1 removes the currentRootAction; e.g. // if we are on the "Set theme" parent action, // the UI should not display "Set themeā€¦ > Dark" // but rather just "Dark" return action.ancestors.slice(index + 1); }, [action.ancestors, currentRootActionId]); return (
{action.icon && action.icon}
{ancestors.length > 0 && ancestors.map((ancestor) => ( {ancestor.name} ))} {action.name}
{action.subtitle && ( {action.subtitle} )}
{action.shortcut?.length ? (
{action.shortcut.map((sc) => ( {sc} ))}
) : null}
); } ); const staticActions = [ { id: "user", name: "User", shortcut: ["u"], keywords: "profile", perform: () => (window.location.pathname = "user"), }, { id: "user.edit", name: "Edit User", shortcut: ["u e"], keywords: "profile edit settings", perform: () => (window.location.pathname = "user/settings"), }, { id: "admin", name: "Admin", shortcut: ["a"], keywords: "home", perform: () => (window.location.pathname = "admin"), }, { id: "notes", name: "Notes", shortcut: ["n"], keywords: "posts", perform: () => (window.location.pathname = "admin/notes"), }, { id: "notes.new", name: "New Note", shortcut: ["n n"], keywords: "create new", perform: () => (window.location.pathname = "admin/notes/new"), }, { id: "channels", name: "Channels", shortcut: ["c"], keywords: "channels", perform: () => (window.location.pathname = "admin/channels"), }, { id: "channels.new", name: "New Channel", shortcut: ["n c"], keywords: "create new", perform: () => (window.location.pathname = "admin/channels/new"), }, { id: "identities", name: "Identities", shortcut: ["i"], keywords: "identities", perform: () => (window.location.pathname = "admin/identities"), }, { id: "identities.new", name: "New Identity", shortcut: ["n i"], keywords: "create new", perform: () => (window.location.pathname = "admin/identities/new"), }, { id: "settings", name: "Settings", shortcut: ["s"], keywords: "settings", perform: () => (window.location.pathname = "admin/settings"), }, { id: "settings.edit", name: "Edit Settings", shortcut: ["s e"], keywords: "settings edit", perform: () => (window.location.pathname = "admin/settings/edit"), } ].map(function(a) { return {...a, section: "Pages"} }) function DynamicResultsProvider() { const [actions, setActions] = useState([]) const [notes, setNotes] = useState([]) const [rerender, setRerender] = useState(true) useEffect(() => { fetch("/api/admin/notes") .then(resp => resp.json()) .then(json => setNotes(json.notes)) }, [rerender]) const noteActions = useMemo(() => notes.map(note => createAction({ id: note.slug, name: note.name, subtitle: note.channels.map(c => c.name).join(", "), section: "Notes", keywords: note.channels.map(c => c.name), perform: () => (window.location.pathname = `/admin/notes/${note.id}`), })), [notes]) useRegisterActions([...staticActions, ...noteActions], [noteActions]) } export default function KBar() { return ( ) }