Selectors
You can’t import Web UI’s components and hooks directly. Use these selectors to get them instead.
getComponents
Section titled “getComponents”getComponents returns Web UI’s React components.
getComponents(): ComponentsUse the components to build your own interface, or decorate this selector to replace one with your own.
Example
const { getComponents } = getSelectors();const { App, InkCanvas } = getComponents();getControllerType
Section titled “getControllerType”getControllerType returns the kind of game controller the reader has connected.
getControllerType(): { type: ControllerType }
type ControllerType = null | "generic" | "nintendo" | "playstation" | "xbox";type is null when no controller is connected, and "generic" for a controller Web UI doesn’t recognize.
Example
const { getControllerType } = getSelectors();const { type } = getControllerType();getHooks
Section titled “getHooks”getHooks returns Web UI’s React hooks.
getHooks(): HooksExample
const { getHooks } = getSelectors();const { useLayers } = getHooks();getI18nValue
Section titled “getI18nValue”getI18nValue returns the interface text for a key, in the reader’s text language.
getI18nValue(context: { key: string; values?: Record<string, number | string>;}): { value: string }It looks up the key in Web UI’s own translations, first for the reader’s text locale, then for en-US. If a key has no entry, you get the key back as written, so a plain sentence works as its own key.
Each {{name}} in the text is replaced with values[name]. A placeholder with no value is left as written.
Example
const { getI18nValue } = getSelectors();const { value } = getI18nValue({ key: "button", values: { index: 20 } });// "Button 20"getMenuComponent
Section titled “getMenuComponent”getMenuComponent returns the component that wraps a menu. By default, it returns MenuPanel for every menu.
getMenuComponent(context: { schema: MenuSchema }): { component: unknown }Decorate it to use your own component for a menu.
Example
decorateSelector("getMenuComponent", (context, next) => { if (context.schema.name !== "journal") return next(context); return { component: JournalMenu };});getMenuFieldComponent
Section titled “getMenuFieldComponent”getMenuFieldComponent returns the component for a menu field. By default, Web UI provides a component for each field type.
getMenuFieldComponent(context: { field: MenuField }): { component: unknown }The component receives props built from the field. Every field gets name, and label: the field’s text in the reader’s language. The other props depend on the field’s type:
| Field type | Props |
|---|---|
boolean | value: boolean, setValue(newValue: boolean) |
number | value: number, setValue(newValue: number), minimum?, maximum?, step? |
string | value: string, setValue(newValue: string) |
enum | value: string, setValue(newValue: string), options: Array<{ label: string; value: string }> |
button | action(): Promise<void> |
bookmark | bookmark: null | Bookmark, locale: string, action(): Promise<void> |
separator | Only name and label |
value is always current. The prop types are exported from @inkweaverdev/plugin-web-ui/plugin as MenuBooleanFieldProps, MenuEnumFieldProps, and so on.
For bookmark, locale is the reader’s text language.
Example
function Toggle({ label, setValue, value }) { return ( <button onClick={() => setValue(!value)} type="button"> {label}: {value ? "On" : "Off"} </button> );}
decorateSelector("getMenuFieldComponent", (context, next) => { if (context.field.type !== "boolean") return next(context); return { component: Toggle };});getRenderStats
Section titled “getRenderStats”getRenderStats returns timings for the scene’s last twenty renders.
getRenderStats(): { renders: Array<RenderStats> }
type RenderStats = { duration: number; firstFrame: null | number; frameCount: number; frameInterval: null | { average: number; max: number }; frameTime: null | { average: number; max: number }; load: null | number; outcome: "failed" | "interrupted" | "settled"; startedAt: number;};A render starts when the scene changes, and ends when its animations settle, a newer render replaces it, or it fails. Times are in milliseconds.
| Field | Description |
|---|---|
duration | From the start of the render to its end. |
firstFrame | From the start of the render until its first frame is on screen. |
frameCount | How many frames were drawn. |
frameInterval | The time between one frame and the next. |
frameTime | The time spent drawing each frame. |
load | The time spent loading images and shaders. |
outcome | How the render ended. |
startedAt | When the render started, as a Date.now() timestamp. |
firstFrame, frameInterval, frameTime, and load are null when the render ended before reaching them.
Example
const { getRenderStats } = getSelectors();const { renders } = getRenderStats();console.table( renders.map(({ firstFrame, frameInterval }) => ({ firstFrame, slowestFrame: frameInterval?.max, })),);