Menus and input
These commands and selectors manage the menu stack, the scope stack, and input bindings. For a walkthrough, see Menus and input.
Novel’s menus
Section titled “Novel’s menus”Novel labels its title menu title, its controls menu input, and its language menu language. Artists can use these labels to give each menu its own look.
Novel reads its shortcuts from the binding fields of the input menu.
Novel’s menus draw their interface over the .ui layer by default. If a menu doesn’t name a layer, or its artwork has no matching layer, the menu covers the whole canvas.
Commands
Section titled “Commands”pushMenu
Section titled “pushMenu”Adds a menu to the menu stack. If the menu’s schema has a scope, that scope is pushed too.
pushMenu(ctx: PushMenuContext): Promise<PushMenuResult>
interface PushMenuContext { name: MenuName; cleanupCallback?: () => void;}interface PushMenuResult { release: () => void;}name is keyof Menus. Call release to remove the menu, and its scope if it pushed one. cleanupCallback runs when you do.
Example
const { pushMenu } = getCommands();const { release } = await pushMenu({ name: "title" });pushScope
Section titled “pushScope”Adds a scope to the scope stack. Only bindings for the scope on top of the stack, or for "global", can run. See Scopes.
pushScope(ctx: PushScopeContext): Promise<PushScopeResult>
interface PushScopeContext { name: Scope; cleanupCallback?: () => void;}interface PushScopeResult { release: () => void;}name is keyof Scopes. Call release to remove the scope. cleanupCallback runs when you do.
Example
const { pushScope } = getCommands();const { release } = await pushScope({ name: "journal" });toggleMenu
Section titled “toggleMenu”Opens or closes menus.
toggleMenu(): Promise<void>If no menu is open, opens the "title" menu. Otherwise, closes the menu on top of the stack, whichever menu it is.
Example
const { toggleMenu } = getCommands();await toggleMenu();Selectors
Section titled “Selectors”getMenuSchema
Section titled “getMenuSchema”Returns a menu’s schema.
getMenuSchema(ctx: { name: MenuName }): { schema: MenuSchema }To add fields to a menu, decorate this selector and check ctx.name.
Example
const { getMenuSchema } = getSelectors();const { schema } = getMenuSchema({ name: "title" });getInputAction
Section titled “getInputAction”Returns the action bound to an input. Checks the scope on top of the scope stack first, then "global".
getInputAction(ctx: { inputs: string }): { action?: () => Promise<void> }inputs is a single input, in the input binding format.
Bindings come from the binding fields of the input menu. An input shared by two bindings in the same scope has no action. See getInputCollisions.
Example
const { getInputAction } = getSelectors();const { action } = getInputAction({ inputs: "space" });action?.();getInputCollisions
Section titled “getInputCollisions”Returns the inputs that more than one binding in the same scope uses. None of those bindings run.
getInputCollisions(): { collisions: Array<{ input: string; scope: Scope }> }Checks the binding fields of the input menu. A scoped binding that shares an input with a "global" binding isn’t a collision. The scoped one runs while its scope is on top.
Example
const { getInputCollisions } = getSelectors();const { collisions } = getInputCollisions();