CalmUI
TypeScript

Component Scripts

Add local UI behavior and read game values with TypeScript.

You can make a button send an action to Blueprint without a script. Add TypeScript when a component needs local behavior, such as expanding details, selecting a tab, or combining game values for display.

Start with Keep a local toggle. It contains a complete component that you can save and click in Preview.

Make names available to the template

Write code in one <script lang="ts"> section and return the values and functions that the template uses. A function that is declared but not returned cannot be called by @click.

FunctionWhat it does
stateHolds a value private to this component copy
computedCalculates a value from other values and updates it when they change
watchRuns a callback when the watched value changes; returns a stop function
onMount / onUnmountRuns code when a component is created or removed
onShow / onHideRuns code when visibility changes
timers.setTimeout / timers.setIntervalSchedules local UI work

Read a game value

First define the field in Store. In the script, type /, choose Store → Read field, and select your field. Studio adds the @calmui/store import if needed.

Use the generated field path in a computed value and return it for the template. For example, after defining a string field player.name:

import { defineComponent, computed } from "@calmui/runtime";
import { store } from "@calmui/store";

export default defineComponent<Record<string, unknown>, unknown>(() => {
  const playerName = computed(() => store.player.name);
  return { playerName };
});

The template can display {{ playerName }}. In Studio, supply a preview preset; in the game, write the field from Blueprint.

Localize text in a script

Template text uses $loc('Table::Key', 'Default'), but it cannot fill in a value at runtime. When a localized string needs a runtime value - a count, a player name - import loc from @calmui/runtime instead:

import { computed, defineComponent, loc } from "@calmui/runtime";
import { store } from "@calmui/store";

export default defineComponent<Record<string, unknown>, unknown>(() => {
  const greeting = computed(() =>
    loc("GameUI::Welcome", "Welcome back, {name}!", { name: store.player.name })
  );
  return { greeting };
});

loc(key, fallback, params?) takes the same literal key and literal default $loc does - Studio's Languages panel lists a script loc() key exactly like a template $loc key, and the two share the same conflict check if they ever disagree on a default for the same key. params is an object of {name} values substituted into the resolved (or fallback) text after translation - {{ and }} write a literal {/}, and a name missing from params is left as {name} and logged as a Problem in Development. Numbers convert the same way they do everywhere else in CalmUI; loc() does not format numbers or dates per-culture.

Bind the returned value in the template ({{ greeting }}) the same way you bind any other computed. Save the component again after a culture or translation changes in Preview to see the new text - the same reload Studio already performs for a Store or prop change.

Keep gameplay in Unreal

Scripts cannot read files, use the network, or access Unreal objects directly. Send an action when gameplay must change. Save errors appear in Problems with their source location. See script limits.

On this page