Component
The handle an embedded script uses to read its own component instance and the controls people set on it.
A component handle (per-instance PR). Control values read WIRE units: scalar number, text string, point [x, y], colour [r, g, b, a] in 0..1.
id
Type: string (field).
The definition id.
Worked example: The definition's stable id
The scene. A Badge component whose internal comp holds one blue face layer, exposed with a scalar Amount control, plus one Badge instance placed in the Host comp with Amount overridden to 65.
- The comp Host: 640 by 360 at 25 fps, 100 frames (4 seconds).
- The comp Badge internals: 200 by 200 at 25 fps, 100 frames (4 seconds).
- Badge face in Badge internals: a solid layer, at [100, 100], 120 by 120, filled 4d9de0.
- Badge in Host: a component instance, at [320, 180].
- The instance overrides the component's c_amount control to 65.
- The component Badge wraps Badge internals and exposes 1 control: Amount (scalar, default 20).
The script is EMBEDDED in the Badge component - add it from the component's own Scripts group, and it travels with the component wherever it is placed.
The script. Add a component script named Definition check and paste:
export const outputs = ["layer_1:transform.opacity"];
export function frame() {
return thisComponent.id === "component_1" ? 85 : 10;
}
Line by line:
- Line 4: A component definition carries a stable id like every other entity. This embedded script rides inside the Badge definition, so wherever a Badge is placed the check passes and the face renders at 85. Ids survive library publishing and importing - the imported copy is re-keyed consistently, scripts included.
What you see. The badge face renders at 85 percent opacity everywhere the component appears - in the definition editor and in every placed instance.
name
Type: string (field).
The definition name.
Worked example: Read the definition's name
The scene. A Badge component whose internal comp holds one blue face layer, exposed with a scalar Amount control, plus one Badge instance placed in the Host comp with Amount overridden to 65.
- The comp Host: 640 by 360 at 25 fps, 100 frames (4 seconds).
- The comp Badge internals: 200 by 200 at 25 fps, 100 frames (4 seconds).
- Badge face in Badge internals: a solid layer, at [100, 100], 120 by 120, filled 4d9de0.
- Badge in Host: a component instance, at [320, 180].
- The instance overrides the component's c_amount control to 65.
- The component Badge wraps Badge internals and exposes 1 control: Amount (scalar, default 20).
The script is EMBEDDED in the Badge component - add it from the component's own Scripts group, and it travels with the component wherever it is placed.
The script. Add a component script named Name seat and paste:
export const outputs = ["layer_1:transform.position"];
export function frame() {
return [value[0], 100 + thisComponent.name.length * 6];
}
Line by line:
- Line 4: name is the definition's display label - "Badge", five characters, dropping the face 30 pixels below its resting line. As everywhere, the name is data to read; the component's identity for references is its id.
What you see. The badge face sits at y 130 - six pixels of drop for each letter of the component's name.
instance
Type: string | null (field).
The instance layer id this evaluation belongs to; null under the definition context (the internal comp evaluated directly - defaults).
Worked example: Definition or placed instance
The scene. A Badge component whose internal comp holds one blue face layer, exposed with a scalar Amount control, plus one Badge instance placed in the Host comp with Amount overridden to 65.
- The comp Host: 640 by 360 at 25 fps, 100 frames (4 seconds).
- The comp Badge internals: 200 by 200 at 25 fps, 100 frames (4 seconds).
- Badge face in Badge internals: a solid layer, at [100, 100], 120 by 120, filled 4d9de0.
- Badge in Host: a component instance, at [320, 180].
- The instance overrides the component's c_amount control to 65.
- The component Badge wraps Badge internals and exposes 1 control: Amount (scalar, default 20).
The script is EMBEDDED in the Badge component - add it from the component's own Scripts group, and it travels with the component wherever it is placed.
The script. Add a component script named Context lamp and paste:
export const outputs = ["layer_1:transform.opacity"];
export function frame() {
return thisComponent.instance === null ? 40 : 70;
}
Line by line:
- Line 4: instance tells a component script WHERE it is running: null while the definition's own internal comp is being evaluated (the editing context, control defaults in force), or the placing layer's id when a real instance renders. Here the face rests at a hushed 40 in the definition editor and at 70 inside every placed Badge - one script, two honest contexts.
What you see. Editing the Badge definition shows its face at a hushed 40 percent; every placed instance in a comp renders it at 70 - the same script reading its context.
controls
Type: ComponentControl[] (field).
Every control in definition order with its effective value.
Worked example: Walk the exposed controls
The scene. A Badge component whose internal comp holds one blue face layer, exposed with a scalar Amount control, plus one Badge instance placed in the Host comp with Amount overridden to 65.
- The comp Host: 640 by 360 at 25 fps, 100 frames (4 seconds).
- The comp Badge internals: 200 by 200 at 25 fps, 100 frames (4 seconds).
- Badge face in Badge internals: a solid layer, at [100, 100], 120 by 120, filled 4d9de0.
- Badge in Host: a component instance, at [320, 180].
- The instance overrides the component's c_amount control to 65.
- The component Badge wraps Badge internals and exposes 1 control: Amount (scalar, default 20).
The script is EMBEDDED in the Badge component - add it from the component's own Scripts group, and it travels with the component wherever it is placed.
The script. Add a component script named Control census and paste:
export const outputs = ["layer_1:transform.scale"];
export function frame() {
const grown = 100 + thisComponent.controls.length * 20;
return [grown, grown];
}
Line by line:
- Line 4: controls lists every control the definition exposes, in definition order, each carrying its EFFECTIVE value for this context. The Badge exposes one (Amount), so the face renders at 120 percent. Iterate the array to make a component adapt to its own surface.
What you see. The badge face renders a fifth larger - 20 percent of growth for the component's one exposed control.
numControls
Type: number (field).
controls.length.
Worked example: The cheap census
The scene. A Badge component whose internal comp holds one blue face layer, exposed with a scalar Amount control, plus one Badge instance placed in the Host comp with Amount overridden to 65.
- The comp Host: 640 by 360 at 25 fps, 100 frames (4 seconds).
- The comp Badge internals: 200 by 200 at 25 fps, 100 frames (4 seconds).
- Badge face in Badge internals: a solid layer, at [100, 100], 120 by 120, filled 4d9de0.
- Badge in Host: a component instance, at [320, 180].
- The instance overrides the component's c_amount control to 65.
- The component Badge wraps Badge internals and exposes 1 control: Amount (scalar, default 20).
The script is EMBEDDED in the Badge component - add it from the component's own Scripts group, and it travels with the component wherever it is placed.
The script. Add a component script named Surface size and paste:
export const outputs = ["layer_1:transform.opacity"];
export function frame() {
return 60 + thisComponent.numControls * 10;
}
Line by line:
- Line 4: numControls is controls.length without building the array. One exposed control lifts the face to 70 percent; expose more and it brightens with the surface.
What you see. The badge face rests at 70 percent - sixty as the floor plus ten for its single exposed control.
control
control(id: string): ComponentControl | null
The control by id, or null.
Worked example: One control by id
The scene. A Badge component whose internal comp holds one blue face layer, exposed with a scalar Amount control, plus one Badge instance placed in the Host comp with Amount overridden to 65.
- The comp Host: 640 by 360 at 25 fps, 100 frames (4 seconds).
- The comp Badge internals: 200 by 200 at 25 fps, 100 frames (4 seconds).
- Badge face in Badge internals: a solid layer, at [100, 100], 120 by 120, filled 4d9de0.
- Badge in Host: a component instance, at [320, 180].
- The instance overrides the component's c_amount control to 65.
- The component Badge wraps Badge internals and exposes 1 control: Amount (scalar, default 20).
The script is EMBEDDED in the Badge component - add it from the component's own Scripts group, and it travels with the component wherever it is placed.
The script. Add a component script named Amount slide and paste:
export const outputs = ["layer_1:transform.position"];
export function frame() {
const amount = thisComponent.control("c_amount");
return [40 + amount.value, value[1]];
}
Line by line:
- Line 4: control(id) fetches one exposed control by its definition id, or null when no such control exists - the polite lookup, like layer.control().
- Line 5: The face slides right by the EFFECTIVE Amount: 20 (the default) while editing the definition, 65 inside the placed instance that overrides it. Same script, per-context values - this is how one component serves every instance differently.
What you see. In the definition editor the face sits at x 60; the placed Badge in the Host comp shows it at x 105, because that instance's Amount is overridden to 65.
controlByLabel
controlByLabel(label: string): ComponentControl | null
The first control with this label, or null.
Worked example: Find a control by its label
The scene. A Badge component whose internal comp holds one blue face layer, exposed with a scalar Amount control, plus one Badge instance placed in the Host comp with Amount overridden to 65.
- The comp Host: 640 by 360 at 25 fps, 100 frames (4 seconds).
- The comp Badge internals: 200 by 200 at 25 fps, 100 frames (4 seconds).
- Badge face in Badge internals: a solid layer, at [100, 100], 120 by 120, filled 4d9de0.
- Badge in Host: a component instance, at [320, 180].
- The instance overrides the component's c_amount control to 65.
- The component Badge wraps Badge internals and exposes 1 control: Amount (scalar, default 20).
The script is EMBEDDED in the Badge component - add it from the component's own Scripts group, and it travels with the component wherever it is placed.
The script. Add a component script named Label lookup and paste:
export const outputs = ["layer_1:transform.opacity"];
export function frame() {
const amount = thisComponent.controlByLabel("Amount");
return amount ? amount.value + 15 : 100;
}
Line by line:
- Line 4: controlByLabel() searches by the HUMAN label instead of the id, answering the first match or null. Labels can repeat and can be edited, so prefer control(id) in anything long-lived - the label form suits quick sketches and generic helper components.
- Line 5: The default Amount of 20 plus 15 rests the face at 35 percent in the definition context.
What you see. The badge face rests at 35 percent opacity in the definition editor - the Amount control found by its label, plus fifteen.