@difizen/mana-core
Version:
143 lines (128 loc) • 4.08 kB
text/typescript
import type { CommandHandler } from '../command/command-protocol';
import type {
DefaultActionMenuItem,
DefaultGeneralMenuItem,
} from './default-menu-node';
export type ActionMenuItem = DefaultActionMenuItem;
export type GeneralMenuItem = DefaultGeneralMenuItem;
export type MenuPath = string[];
export namespace MenuSymbol {
export const MenuNodeSymbol = Symbol('MenuNodeSymbol');
export const ActionMenuNodeSymbol = Symbol('ActionMenuNodeSymbol');
export const ParentPathSymbol = Symbol('ParentPathSymbol');
}
/**
* Factory for instantiating menu item.
*/
export const GeneralMenuItemFactory = Symbol('GeneralMenuItemFactory');
export interface GeneralMenuItemFactory {
(item: MenuNode, menuPath: MenuPath): GeneralMenuItem;
}
/**
* Factory for instantiating menu item.
*/
export const ActionMenuItemFactory = Symbol('ActionMenuItemFactory');
export interface ActionMenuItemFactory {
(item: ActionMenuNode, menuPath: MenuPath): ActionMenuItem;
}
/**
* Base interface of the nodes used in the menu tree structure.
*/
export interface MenuNode {
/**
* The unique ID of the menu node.
*/
label?: React.ReactNode | React.FC;
/**
* technical identifier.
*/
readonly id: string;
/**
* The order to display menu node.
*/
order?: string;
/**
* Optional icon for the menu item
*/
icon?: React.ReactNode | React.FC;
}
export namespace MenuNode {
export function is(arg: any): arg is MenuNode {
return !!arg && typeof arg === 'object' && 'id' in arg;
}
}
export interface CommandMenuNode extends MenuNode {
/**
* The command to execute.
*/
command: string;
/**
* In addition to the mandatory command property, an alternative command can be defined.
* It will be shown and invoked when pressing Alt while opening a menu.
*/
alt?: string;
}
export namespace CommandMenuNode {
/* Determine whether object is a MenuAction */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function is(arg: any): arg is CommandMenuNode {
return MenuNode.is(arg) && 'command' in arg;
}
}
export interface ExecutableMenuNode extends MenuNode, CommandHandler {
command?: string;
/**
* In addition to the mandatory command property, an alternative command can be defined.
* It will be shown and invoked when pressing Alt while opening a menu.
*/
alt?: string;
}
export namespace ExecutableMenuNode {
/* Determine whether object is a MenuAction */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function is(arg: any): arg is ExecutableMenuNode {
return MenuNode.is(arg) && 'execute' in arg;
}
}
export type ActionMenuNode = CommandMenuNode | ExecutableMenuNode;
export namespace ActionMenuNode {
/* Determine whether object is a MenuAction */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function is(arg: any): arg is ActionMenuNode {
return CommandMenuNode.is(arg) || ExecutableMenuNode.is(arg);
}
}
export type MenuOptions = Omit<MenuNode, 'id'>;
export namespace MenuItem {
/* Determine whether object is a MenuAction */
export function isGeneralMenuItem(arg: any): arg is GeneralMenuItem {
return (
MenuNode.is(arg) && 'children' in arg && ('addNode' in arg || 'removeNode' in arg)
);
}
/* Determine whether object is a MenuAction */
export function isActionMenuItem(arg: any): arg is ActionMenuItem {
return ActionMenuNode.is(arg) && 'command' in arg && 'onDisposed' in arg;
}
}
export namespace ActionMenuItem {
/**
* @deprecated use MenuItem.isActionMenuItem instead
* @param arg
* @returns arg is ActionMenuItem
*/
export function is(arg: any): arg is ActionMenuItem {
return MenuItem.isActionMenuItem(arg);
}
}
export namespace GeneralMenuItem {
/**
* @deprecated use MenuItem.isGeneralMenuItem instead
* @param arg
* @returns arg is GeneralMenuItem
*/
export function is(arg: any): arg is GeneralMenuItem {
return MenuItem.isGeneralMenuItem(arg);
}
}
export type MenuItem = ActionMenuItem | GeneralMenuItem;