mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 14:43:46 +01:00
Merge pull request #24427 from overleaf/mj-command-registry
[web] Editor redesign: Add command registry GitOrigin-RevId: c3d78d052f7e6e067de3247da8fe04329d8822ff
This commit is contained in:
committed by
Copybot
parent
1d1bad23e3
commit
767ac1632e
@@ -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>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { DependencyList, useEffect } from 'react'
|
||||
import {
|
||||
Command,
|
||||
useCommandRegistry,
|
||||
} from '../context/command-registry-context'
|
||||
|
||||
export const useCommandProvider = (
|
||||
generateElements: () => Command[] | undefined,
|
||||
dependencies: DependencyList
|
||||
) => {
|
||||
const { register, unregister } = useCommandRegistry()
|
||||
useEffect(() => {
|
||||
const elements = generateElements()
|
||||
if (!elements) return
|
||||
register(...elements)
|
||||
return () => {
|
||||
unregister(...elements.map(element => element.id))
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, dependencies)
|
||||
}
|
||||
Reference in New Issue
Block a user