Merge pull request #24427 from overleaf/mj-command-registry

[web] Editor redesign: Add command registry

GitOrigin-RevId: c3d78d052f7e6e067de3247da8fe04329d8822ff
This commit is contained in:
Mathias Jakobsen
2025-04-07 08:04:40 +00:00
committed by Copybot
parent 1d1bad23e3
commit 767ac1632e
11 changed files with 321 additions and 18 deletions
@@ -0,0 +1,59 @@
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
}
@@ -25,6 +25,7 @@ import { SplitTestProvider } from '@/shared/context/split-test-context'
import { UserProvider } from '@/shared/context/user-context'
import { UserSettingsProvider } from '@/shared/context/user-settings-context'
import { IdeRedesignSwitcherProvider } from './ide-redesign-switcher-context'
import { CommandRegistryProvider } from './command-registry-context'
export const ReactContextRoot: FC<{ providers?: Record<string, FC> }> = ({
children,
@@ -57,6 +58,7 @@ export const ReactContextRoot: FC<{ providers?: Record<string, FC> }> = ({
UserProvider,
UserSettingsProvider,
IdeRedesignSwitcherProvider,
CommandRegistryProvider,
...providers,
}
@@ -87,7 +89,9 @@ export const ReactContextRoot: FC<{ providers?: Record<string, FC> }> = ({
<Providers.OutlineProvider>
<Providers.RailProvider>
<Providers.IdeRedesignSwitcherProvider>
{children}
<Providers.CommandRegistryProvider>
{children}
</Providers.CommandRegistryProvider>
</Providers.IdeRedesignSwitcherProvider>
</Providers.RailProvider>
</Providers.OutlineProvider>