Files
hoppscotch/packages/hoppscotch-common/src/services/context-menu/index.ts
Nivedin 8970ff5c68 feat: context menu (#3180)
Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
2023-08-02 20:52:16 +05:30

110 lines
2.4 KiB
TypeScript

import { Service } from "dioc"
import { Component } from "vue"
/**
* Defines how to render the text in a Context Menu Search Result
*/
export type ContextMenuTextType<T extends object | Component = never> =
| {
type: "text"
text: string
}
| {
type: "custom"
/**
* The component to render in place of the text
*/
component: T
/**
* The props to pass to the component
*/
componentProps: T extends Component<infer Props> ? Props : never
}
/**
* Defines info about a context menu result so the UI can render it
*/
export interface ContextMenuResult {
/**
* The unique ID of the result
*/
id: string
/**
* The text to render in the result
*/
text: ContextMenuTextType<any>
/**
* The icon to render as the signifier of the result
*/
icon: object | Component
/**
* The action to perform when the result is selected
*/
action: () => void
/**
* Additional metadata about the result
*/
meta?: {
/**
* The keyboard shortcut to trigger the result
*/
keyboardShortcut?: string[]
}
}
/**
* Defines the state of a context menu
*/
export type ContextMenuState = {
results: ContextMenuResult[]
}
/**
* Defines a context menu
*/
export interface ContextMenu {
/**
* The unique ID of the context menu
* This is used to identify the context menu
*/
menuID: string
/**
* Gets the context menu for the given text
* @param text The text to get the context menu for
* @returns The context menu state
*/
getMenuFor: (text: string) => ContextMenuState
}
/**
* Defines the context menu service
* This service is used to register context menus and get context menus for text
* This service is used by the context menu UI
*/
export class ContextMenuService extends Service {
public static readonly ID = "CONTEXT_MENU_SERVICE"
private menus: Map<string, ContextMenu> = new Map()
/**
* Registers a menu with the context menu service
* @param menu The menu to register
*/
public registerMenu(menu: ContextMenu) {
this.menus.set(menu.menuID, menu)
}
/**
* Gets the context menu for the given text
* @param text The text to get the context menu for
*/
public getMenuFor(text: string): ContextMenuResult[] {
const menus = Array.from(this.menus.values()).map((x) => x.getMenuFor(text))
const result = menus.flatMap((x) => x.results)
return result
}
}