| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- import { createContext, useCallback, useContext, useState } from 'react'
- type CommandInvocationContext = {
- location?: string
- }
- export type Command = {
- label: string
- id: string
- handler?: (context: CommandInvocationContext) => void
- href?: string
- disabled?: boolean
- // TODO: Keybinding?
- }
- const CommandRegistryContext = createContext<CommandRegistry | undefined>(
- undefined
- )
- type CommandRegistry = {
- registry: Map<string, Command>
- register: (...elements: Command[]) => void
- unregister: (...id: string[]) => void
- }
- export const CommandRegistryProvider: React.FC<React.PropsWithChildren> = ({
- children,
- }) => {
- const [registry, setRegistry] = useState(new Map<string, Command>())
- const register = useCallback((...elements: Command[]) => {
- setRegistry(
- registry =>
- new Map([
- ...registry,
- ...elements.map(element => [element.id, element] as const),
- ])
- )
- }, [])
- const unregister = useCallback((...ids: string[]) => {
- setRegistry(
- registry => new Map([...registry].filter(([key]) => !ids.includes(key)))
- )
- }, [])
- return (
- <CommandRegistryContext.Provider value={{ registry, register, unregister }}>
- {children}
- </CommandRegistryContext.Provider>
- )
- }
- export const useCommandRegistry = (): CommandRegistry => {
- const context = useContext(CommandRegistryContext)
- if (!context) {
- throw new Error(
- 'useCommandRegistry must be used within a CommandRegistryProvider'
- )
- }
- return context
- }
|