Structure and hosting
One hosting model — slots are named positions, child declarations are their occupants.
MotionActor has a single hosting relationship. There is no structural/mounted split and no second mechanism to learn.
- A slot is a named hosting region: where a child can go.
- A child declaration is a named occupant: who is there.
child(...)uses the slot matching its field name.hostInSlot(...)adds an occupant during compilation using the same relationship.
const phoneSlots = defineSlots({
statusBar: slot({ accepts: StatusBar }),
app: slot(),
});
class Phone extends LayoutActor<typeof phoneSlots> {
static slots = phoneSlots;
statusBar = child(StatusBar); // occupies "statusBar"
app = child(MailApp); // occupies "app"
}Which form to use
Declare a field. Always-owned children that exist for the actor's whole life belong in the class body, where the type system can see them.
class Phone extends LayoutActor<typeof phoneSlots> {
static slots = phoneSlots;
statusBar = child(StatusBar);
}Do not use onSpawn to wire fixed bindings
Falling back to onSpawn() just to pass parent state to a fixed child is the common
mistake. Use an owner-aware factory
instead — it keeps the child a declared field and the binding live.
Use it for
- Actors that expose stable child regions: shells, panes, phones, windows.
- Any host that should be able to accept content it does not itself define.
Resolved structure
Hosting shows up on every ResolvedActor as parentId, slotName and slotChildren, so
a renderer can place children without knowing the actor family:
const phone = state.findActor(Phone);
phone.slotChildren.app; // ["mail-app-1"]