Files
overleaf-cep/services/web/frontend/js/features/ide-react/context/command-registry-context.tsx
Mathias Jakobsen 767ac1632e Merge pull request #24427 from overleaf/mj-command-registry
[web] Editor redesign: Add command registry

GitOrigin-RevId: c3d78d052f7e6e067de3247da8fe04329d8822ff
2025-04-07 08:04:40 +00:00

60 lines
1.5 KiB
TypeScript

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 = ({ 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
}