.calmui Reference
Source structure, bindings, directives, scripts, and component boundaries.
A .calmui file is a UTF-8 component source. It is compiled into a versioned
.cuipack; Unreal Shipping never parses component source.
Top-level sections
| Section | Cardinality | Purpose |
|---|---|---|
<import component="Name" from="./Name.calmui" /> | Zero or more | Import a project component by relative path. |
<template> | Exactly one | Declare the element and component tree. |
<style scoped> | Zero or one | CSS owned by this component type. |
<style> | Zero or one | Global CSS contributed by this component. |
<script lang="ts"> | Zero or one | Local, sandboxed view behaviour. |
<template>
<button :disabled="props.disabled" @click="activate">
<slot>{{ props.label }}</slot>
</button>
</template>
<style scoped>
button { color: var(--color-text); }
</style>
<script lang="ts">
import { defineComponent } from "@calmui/runtime";
export default defineComponent(({ emit }) => ({
activate: () => emit("activate"),
}));
</script>Bindings and events
:disabled="props.disabled"binds an attribute.{{ props.label }}binds text.@click="activate"calls a function returned by the script.@click="$emit('activate')"emits directly without a script function.@click="$action('MainMenu.Continue', { saveId: lastSaveId })"dispatches a declared Action Contract directly without a script forwarding function.<slot />and<slot name="header">fallback</slot>project caller content.
Template expressions are intentionally small: literals, props, returned
script bindings, loop variables, dotted paths, a ternary conditional, .length
on an array path, and $emit. They are not general JavaScript expressions.
Logical && and || select and return one of their operands, so
{{ title || "Untitled" }} remains text rather than becoming a boolean.
cond ? a : b (.cuipack 1.13+) short-circuits like JavaScript's - the
untaken branch never evaluates, so flag ? "ok" : props.mightBeMissing.length
is safe even when props.mightBeMissing is absent while flag is true - and
nests without parentheses on either side. items.length reads an array's
element count; see docs/calmui-component-format.md for the full profile,
including the .length-on-non-array diagnostic and the feature/format gate.
Structure and identity
| Directive | Meaning |
|---|---|
ui:if="expression" | Create or destroy the subtree. |
ui:show="expression" | Preserve the instance but suppress paint and hit testing. |
ui:for="item in props.items" | Repeat content. |
ui:virtual="fixed" | Window a keyed ui:for with fixed row height. |
ui:key="item.id" | Give repeated components stable domain identity. |
Every component repeated with ui:for requires a stable ui:key; list indexes
are not valid identity. This preserves focus and per-instance state across
insert, remove, and reorder operations.
Script boundary
Component TypeScript is for local UI behaviour. It can use state, computed,
watch, lifecycle hooks, timers, the read-only Store facade, and typed Actions.
It cannot read files, use the network, call system APIs, or access Unreal objects
directly. Gameplay state remains owned by the C++ Store.
See Components, TypeScript, and the
repository contract docs/calmui-component-format.md for compiler-level detail.