85453da49f
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
558 lines
18 KiB
Plaintext
558 lines
18 KiB
Plaintext
---
|
||
title: "Edit Operations"
|
||
description: "The complete EditOp catalog for dispatch(), can(), and batch()."
|
||
---
|
||
|
||
Every mutation in the SDK is expressed as an `EditOp` — a plain data object with a discriminated `type` field. You can submit ops individually through `dispatch()`, validate them with `can()`, or group them into a single undo/persist step with `batch()`.
|
||
|
||
<Tip>
|
||
Every element op requires an explicit `target` (an `HfId` string or `HfId[]` array). There is no selection-implicit mutation — the SDK never reads the current selection to decide what to edit. The typed methods on `Composition` (such as `comp.setText()` and `comp.setStyle()`) are convenience sugar that construct and dispatch these same ops.
|
||
</Tip>
|
||
|
||
## dispatch, batch, and can
|
||
|
||
### dispatch
|
||
|
||
```typescript
|
||
comp.dispatch(op: EditOp, opts?: { origin?: unknown }): void
|
||
```
|
||
|
||
Applies `op` immediately. Emits a `patch` event, persists if an adapter is attached, and records a history entry. The optional `origin` is forwarded verbatim in the resulting `PatchEvent`; use it to label the source of the change (e.g. `"user"`, `"agent"`, or your own string constant).
|
||
|
||
```typescript
|
||
comp.dispatch(
|
||
{ type: "setStyle", target: "hf-title", styles: { color: "#FFD60A" } },
|
||
{ origin: "agent" },
|
||
);
|
||
```
|
||
|
||
### batch
|
||
|
||
```typescript
|
||
comp.batch(fn: () => void, opts?: { origin?: unknown }): void
|
||
```
|
||
|
||
Groups all `dispatch()` calls made inside `fn` into a single undo step, a single persist write, and a single `patch` event. Use `batch()` when several mutations belong together logically.
|
||
|
||
```typescript
|
||
comp.batch(() => {
|
||
comp.dispatch({ type: "setText", target: "hf-title", value: "Launch Day" });
|
||
comp.dispatch({ type: "setStyle", target: "hf-title", styles: { fontSize: "96px" } });
|
||
comp.dispatch({ type: "setTiming", target: "hf-title", start: 0.5, duration: 3 });
|
||
});
|
||
```
|
||
|
||
### can
|
||
|
||
```typescript
|
||
comp.can(op: EditOp): CanResult
|
||
```
|
||
|
||
Dry-runs `op` without mutating the document. Returns `{ ok: true }` when `dispatch(op)` would succeed, or `{ ok: false; code: string; message: string; hint?: string }` when it would be a no-op or error.
|
||
|
||
Use `can()` as a feature-detection gate before rendering controls or applying optional operations:
|
||
|
||
```typescript
|
||
const result = comp.can({
|
||
type: "setGsapTween",
|
||
animationId: "anim-1",
|
||
properties: { ease: "power3.out" },
|
||
});
|
||
|
||
if (result.ok) {
|
||
comp.setGsapTween("anim-1", { ease: "power3.out" });
|
||
} else {
|
||
console.warn(result.code, result.message);
|
||
}
|
||
```
|
||
|
||
Stable `code` values for `ok: false`:
|
||
|
||
| Code | Meaning |
|
||
|------|---------|
|
||
| `E_TARGET_NOT_FOUND` | The `target` hf-id does not exist in the document. |
|
||
| `E_NO_ROOT` | The document has no root element (empty HTML). |
|
||
| `E_NO_GSAP_TIMELINE` | Op requires a parsed GSAP timeline; parser engine not yet active. |
|
||
| `E_NO_GSAP_SCRIPT` | Op requires a GSAP `<script>` block; none found in the document. |
|
||
|
||
<Note>
|
||
Several Phase-3b GSAP ops (`addGsapTween`, `setGsapTween`, `removeGsapTween`, `addGsapKeyframe`, `setGsapKeyframe`, `removeGsapKeyframe`, etc.) return `{ ok: false, code: 'E_NO_GSAP_TIMELINE' }` from `can()` until the parser engine ships. `dispatch()` still applies those ops structurally even when `can()` returns false.
|
||
</Note>
|
||
|
||
See also: [`Composition`](/sdk/reference/composition) for the typed-method wrappers, [`Types`](/sdk/reference/types) for `CanResult` and `EditOp`.
|
||
|
||
---
|
||
|
||
## Element edits
|
||
|
||
These ops target one or more elements by explicit hf-id. `target` accepts a single `HfId` string or an `HfId[]` array; when an array is given the op is applied to each id individually within a single batch.
|
||
|
||
| `type` | Key fields | What it does |
|
||
|--------|-----------|--------------|
|
||
| `setStyle` | `target`, `styles` | Merges CSS inline styles. `null` values remove that property. |
|
||
| `setText` | `target`, `value` | Replaces the element's direct text content. |
|
||
| `setAttribute` | `target`, `name`, `value` | Sets or removes an HTML attribute. `null` removes it. Does not touch `style`, `class`, or `data-hf-*`. |
|
||
| `setTiming` | `target`, `start?`, `duration?`, `trackIndex?` | Updates one or more timing attributes (`data-start`, `data-duration`, `data-track`). Omitted fields are unchanged. |
|
||
| `setHold` | `target`, `hold` | Sets an elastic hold window; see `ElasticHold` shape below. |
|
||
| `moveElement` | `target`, `x`, `y` | Repositions the element by setting `data-x` / `data-y` (not CSS `left`/`top`). |
|
||
| `removeElement` | `target` | Removes the element and all its children from the document. Inverse of `addElement`. |
|
||
|
||
### setStyle
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "setStyle",
|
||
target: "hf-card",
|
||
styles: {
|
||
borderRadius: "24px",
|
||
backgroundColor: "#1A1A1A",
|
||
color: null, // removes the color property
|
||
},
|
||
});
|
||
```
|
||
|
||
`styles` keys are camelCase property names, matching `CSSStyleDeclaration` convention.
|
||
|
||
### setText
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "setText",
|
||
target: ["hf-headline", "hf-sub"],
|
||
value: "Coming soon",
|
||
});
|
||
```
|
||
|
||
### setAttribute
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "setAttribute",
|
||
target: "hf-logo",
|
||
name: "src",
|
||
value: "/assets/logo-v2.png",
|
||
});
|
||
|
||
// Remove an attribute:
|
||
comp.dispatch({
|
||
type: "setAttribute",
|
||
target: "hf-video",
|
||
name: "autoplay",
|
||
value: null,
|
||
});
|
||
```
|
||
|
||
### setTiming
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "setTiming",
|
||
target: "hf-title",
|
||
start: 1.5,
|
||
duration: 3,
|
||
trackIndex: 0,
|
||
});
|
||
```
|
||
|
||
### setHold
|
||
|
||
`hold` is an `ElasticHold` object:
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "setHold",
|
||
target: "hf-badge",
|
||
hold: {
|
||
start: 2,
|
||
end: 5,
|
||
fill: "freeze", // "freeze" | "loop"
|
||
},
|
||
});
|
||
```
|
||
|
||
### moveElement
|
||
|
||
Sets the element's position via `data-x` / `data-y` attributes. Coordinates are in composition-space pixels.
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "moveElement",
|
||
target: "hf-logo",
|
||
x: 120,
|
||
y: 48,
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
## Structure
|
||
|
||
These ops mutate document structure (add/remove/reorder elements, apply class-level styles, or change composition metadata). They do **not** take a `target` field in the same form as element edits.
|
||
|
||
| `type` | Key fields | What it does |
|
||
|--------|-----------|--------------|
|
||
| `addElement` | `parent`, `index`, `html` | Inserts an HTML fragment. Returns the minted hf-id via the typed `comp.addElement()` method. |
|
||
| `reorderElements` | `entries` | Sets inline `z-index` on one or more elements to reorder their stacking. |
|
||
| `setClassStyle` | `selector`, `styles` | Merges CSS rule styles for a class selector. `null` values remove properties. |
|
||
| `deleteAllForSelector` | `selector` | Removes all elements matching the CSS selector from the document. |
|
||
| `setCompositionMetadata` | `width?`, `height?`, `duration?` | Updates top-level composition dimensions and/or total duration. |
|
||
|
||
### addElement
|
||
|
||
`parent` is the hf-id of the parent element, or `null` to insert at the document body root. `index` is the zero-based sibling index (append if `>= childCount`). `html` must be a single-root HTML fragment and must not contain `<script>`.
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "addElement",
|
||
parent: "hf-scene-1",
|
||
index: 2,
|
||
html: '<div class="clip" data-start="3" data-duration="2">New layer</div>',
|
||
});
|
||
```
|
||
|
||
Use the typed `comp.addElement(parent, index, html)` method to get back the minted hf-id.
|
||
|
||
### reorderElements
|
||
|
||
Each entry sets `z-index` on one element. Elements must be non-statically positioned for `z-index` to take effect — the caller must ensure `position` is set.
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "reorderElements",
|
||
entries: [
|
||
{ target: "hf-bg", zIndex: 0 },
|
||
{ target: "hf-logo", zIndex: 10 },
|
||
{ target: "hf-text", zIndex: 20 },
|
||
],
|
||
});
|
||
```
|
||
|
||
### setClassStyle
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "setClassStyle",
|
||
selector: ".caption",
|
||
styles: { fontSize: "14px", fontWeight: "600" },
|
||
});
|
||
```
|
||
|
||
### deleteAllForSelector
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "deleteAllForSelector",
|
||
selector: ".debug-overlay",
|
||
});
|
||
```
|
||
|
||
### setCompositionMetadata
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "setCompositionMetadata",
|
||
width: 1920,
|
||
height: 1080,
|
||
duration: 30,
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
## Variables
|
||
|
||
| `type` | Key fields | What it does |
|
||
|--------|-----------|--------------|
|
||
| `setVariableValue` | `id`, `value` | Sets a composition variable's current value by id. Value may be a string, number, boolean, `FontValue`, or `ImageValue`. Refuses to create an undeclared variable. |
|
||
| `declareVariable` | `decl` | Creates a new variable declaration, or fully replaces an existing one (type, label, default, and all other schema fields — not just the value). The only op that creates the schema entry from scratch. |
|
||
| `removeVariable` | `id` | Removes a variable's declaration entirely. Live `var.{id}` overrides and `data-var-*` DOM references are left untouched. |
|
||
|
||
```typescript
|
||
// Scalar variable
|
||
comp.dispatch({
|
||
type: "setVariableValue",
|
||
id: "brandColor",
|
||
value: "#6C5CE7",
|
||
});
|
||
|
||
// Font variable (object-valued — never a CSS string)
|
||
comp.dispatch({
|
||
type: "setVariableValue",
|
||
id: "brand-font",
|
||
value: {
|
||
name: "Inter",
|
||
source: "https://fonts.googleapis.com/css2?family=Inter:wght@400;700",
|
||
},
|
||
});
|
||
|
||
// Image variable (object-valued)
|
||
comp.dispatch({
|
||
type: "setVariableValue",
|
||
id: "hero-image",
|
||
value: {
|
||
url: "/assets/hero.jpg",
|
||
alt: "Product hero",
|
||
fit: "cover",
|
||
},
|
||
});
|
||
|
||
// Create a new variable declaration
|
||
comp.dispatch({
|
||
type: "declareVariable",
|
||
decl: {
|
||
id: "brandColor",
|
||
type: "color",
|
||
label: "Brand color",
|
||
default: "#6C5CE7",
|
||
},
|
||
});
|
||
|
||
// Remove a variable's declaration
|
||
comp.dispatch({ type: "removeVariable", id: "brandColor" });
|
||
```
|
||
|
||
---
|
||
|
||
## GSAP tweens
|
||
|
||
These ops add, edit, and remove GSAP tween entries in the composition's GSAP script block. They operate by `animationId` — a stable string identifier minted when a tween is created. Use `comp.addGsapTween()` or `addWithKeyframes` to mint a new id; the typed wrapper returns it directly.
|
||
|
||
<Note>
|
||
Several GSAP ops require the parser engine to be active. Until it ships, `can()` returns `{ ok: false, code: 'E_NO_GSAP_TIMELINE' }` for these ops. `dispatch()` still applies the op structurally.
|
||
</Note>
|
||
|
||
| `type` | Key fields | What it does |
|
||
|--------|-----------|--------------|
|
||
| `addGsapTween` | `target`, `tween` | Adds a new tween for a target hf-id. Returns the minted `animationId` via the typed method. |
|
||
| `setGsapTween` | `animationId`, `properties` | Partially updates an existing tween's `GsapTweenSpec` fields. |
|
||
| `removeGsapTween` | `animationId` | Removes the tween entirely. |
|
||
| `removeGsapProperty` | `animationId`, `property`, `from?` | Removes one animated property from a tween. `from: true` removes from `fromProperties`; otherwise removes from `toProperties` / `properties`. |
|
||
|
||
### addGsapTween
|
||
|
||
`tween` is a `GsapTweenSpec` object:
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "addGsapTween",
|
||
target: "hf-title",
|
||
tween: {
|
||
method: "from",
|
||
position: 0,
|
||
duration: 0.8,
|
||
ease: "power3.out",
|
||
fromProperties: { opacity: 0, y: 40 },
|
||
},
|
||
});
|
||
```
|
||
|
||
`GsapTweenSpec` fields:
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `method` | `"from" \| "to" \| "fromTo" \| "set"` | GSAP tween method. |
|
||
| `position` | `number \| string` | Timeline position. Accepts numbers (seconds) or label-relative strings (`"intro+=0.5"`). |
|
||
| `duration` | `number` | Tween duration in seconds. |
|
||
| `ease` | `string` | GSAP ease string (e.g. `"power3.out"`). |
|
||
| `fromProperties` | `Record<string, unknown>` | Start-state properties (used by `from` and `fromTo`). |
|
||
| `toProperties` | `Record<string, unknown>` | End-state properties (used by `fromTo`). |
|
||
| `properties` | `Record<string, unknown>` | Animated properties for `to` tweens. |
|
||
| `repeat` | `number` | Repeat count (`-1` = infinite). |
|
||
| `yoyo` | `boolean` | Reverse on alternating repeats. |
|
||
| `stagger` | `number \| Record<string, unknown>` | Stagger config for multi-target tweens. |
|
||
|
||
### setGsapTween
|
||
|
||
Only the fields you supply are changed; omit any field to leave it unchanged.
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "setGsapTween",
|
||
animationId: "anim-1",
|
||
properties: { ease: "elastic.out(1, 0.3)", duration: 1.2 },
|
||
});
|
||
```
|
||
|
||
### removeGsapProperty
|
||
|
||
```typescript
|
||
// Remove 'scale' from the to-properties of an existing tween
|
||
comp.dispatch({
|
||
type: "removeGsapProperty",
|
||
animationId: "anim-1",
|
||
property: "scale",
|
||
});
|
||
|
||
// Remove 'opacity' from the from-properties
|
||
comp.dispatch({
|
||
type: "removeGsapProperty",
|
||
animationId: "anim-2",
|
||
property: "opacity",
|
||
from: true,
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
## Keyframes
|
||
|
||
Keyframe ops work with tweens that use CSS `@keyframes`-style percentage arrays rather than a single `fromProperties`/`toProperties` shape.
|
||
|
||
| `type` | Key fields | What it does |
|
||
|--------|-----------|--------------|
|
||
| `setGsapKeyframe` | `animationId`, `keyframeIndex`, `position?`, `value?`, `ease?` | Updates one keyframe by index inside an existing keyframed tween. |
|
||
| `addGsapKeyframe` | `animationId`, `position`, `value` | Appends a new keyframe at a given percentage position. |
|
||
| `removeGsapKeyframe` | `animationId`, `percentage` | Removes the keyframe at a specific percentage. |
|
||
| `removeAllKeyframes` | `animationId` | Clears all keyframes from a tween, leaving the tween shell intact. |
|
||
| `convertToKeyframes` | `animationId`, `resolvedFromValues?` | Converts a `from`/`to`/`fromTo` tween into keyframe form. `resolvedFromValues` provides live computed values for the 0% stop. |
|
||
| `materializeKeyframes` | `animationId`, `keyframes`, `easeEach?`, `resolvedSelector?` | Writes a complete keyframe set to an existing tween, replacing any previous keyframes. |
|
||
| `addWithKeyframes` | `targetSelector`, `position`, `duration`, `keyframes`, `ease?` | Creates a new keyframed tween for the given CSS selector. Returns minted `animationId` via typed method. |
|
||
| `replaceWithKeyframes` | `animationId`, `targetSelector`, `position`, `duration`, `keyframes`, `ease?` | Atomically removes an existing tween and inserts a new keyframed tween. |
|
||
| `splitIntoPropertyGroups` | `animationId` | Splits a multi-property keyframed tween into one tween per animated property. |
|
||
| `splitAnimations` | `originalId`, `newId`, `splitTime`, `elementStart`, `elementDuration` | Splits one tween into two at `splitTime`. The second half gets `newId`. |
|
||
| `unrollDynamicAnimations` | `animationId`, `elements` | Converts a selector-targeted tween that matches multiple elements into per-element keyframe tweens. |
|
||
|
||
### materializeKeyframes
|
||
|
||
`keyframes` is an array of `{ percentage, properties, ease? }` objects:
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "materializeKeyframes",
|
||
animationId: "anim-3",
|
||
keyframes: [
|
||
{ percentage: 0, properties: { opacity: 0, y: 30 } },
|
||
{ percentage: 100, properties: { opacity: 1, y: 0 }, ease: "power2.out" },
|
||
],
|
||
easeEach: "none",
|
||
resolvedSelector: "#hf-title",
|
||
});
|
||
```
|
||
|
||
### addWithKeyframes / replaceWithKeyframes
|
||
|
||
`position` is a number (seconds) — unlike `GsapTweenSpec.position`, label-relative strings are not accepted here.
|
||
|
||
```typescript
|
||
// Create a new keyframed tween:
|
||
comp.dispatch({
|
||
type: "addWithKeyframes",
|
||
targetSelector: "#hf-card",
|
||
position: 1.5,
|
||
duration: 0.6,
|
||
keyframes: [
|
||
{ percentage: 0, properties: { scale: 0.8, opacity: 0 } },
|
||
{ percentage: 100, properties: { scale: 1, opacity: 1 } },
|
||
],
|
||
ease: "back.out(1.7)",
|
||
});
|
||
|
||
// Replace an existing tween atomically:
|
||
comp.dispatch({
|
||
type: "replaceWithKeyframes",
|
||
animationId: "anim-4",
|
||
targetSelector: "#hf-card",
|
||
position: 1.5,
|
||
duration: 0.6,
|
||
keyframes: [
|
||
{ percentage: 0, properties: { scale: 0.9 } },
|
||
{ percentage: 100, properties: { scale: 1 } },
|
||
],
|
||
});
|
||
```
|
||
|
||
<Note>
|
||
After `replaceWithKeyframes`, position-derived tween IDs renumber. Re-query `comp.getElement(id).animationIds` to discover the new ID rather than assuming it matches the old one.
|
||
</Note>
|
||
|
||
`KeyframeSpec` fields:
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `percentage` | `number` | Keyframe stop position (0–100). |
|
||
| `properties` | `Record<string, number \| string>` | CSS / GSAP properties at this stop. |
|
||
| `ease` | `string` | Ease applied from this stop to the next. |
|
||
| `auto` | `boolean` | GSAP endpoint flag — emitted as numeric `_auto: 1`. |
|
||
|
||
---
|
||
|
||
## Labels
|
||
|
||
GSAP timeline labels mark named positions (in seconds) in the master timeline. Labels are referenced in `GsapTweenSpec.position` as strings like `"intro"` or `"intro+=0.5"`.
|
||
|
||
| `type` | Key fields | What it does |
|
||
|--------|-----------|--------------|
|
||
| `addLabel` | `name`, `position` | Adds a named label at a timeline position (seconds). |
|
||
| `removeLabel` | `name` | Removes a named label. |
|
||
|
||
```typescript
|
||
comp.dispatch({ type: "addLabel", name: "intro", position: 0 });
|
||
comp.dispatch({ type: "addLabel", name: "outro", position: 8 });
|
||
|
||
// Tween positioned relative to a label:
|
||
comp.dispatch({
|
||
type: "addGsapTween",
|
||
target: "hf-cta",
|
||
tween: {
|
||
method: "from",
|
||
position: "outro-=0.5",
|
||
duration: 0.4,
|
||
fromProperties: { opacity: 0 },
|
||
},
|
||
});
|
||
|
||
comp.dispatch({ type: "removeLabel", name: "intro" });
|
||
```
|
||
|
||
---
|
||
|
||
## Arc paths
|
||
|
||
Arc path ops control the motion path of a GSAP tween — the curve along which an element travels.
|
||
|
||
| `type` | Key fields | What it does |
|
||
|--------|-----------|--------------|
|
||
| `setArcPath` | `animationId`, `config` | Creates or replaces the arc-path config on a tween. |
|
||
| `updateArcSegment` | `animationId`, `segmentIndex`, `update` | Updates one segment's curviness or control points. |
|
||
| `removeArcPath` | `animationId` | Removes the arc-path from a tween, reverting to a straight-line path. |
|
||
|
||
### setArcPath
|
||
|
||
`config` shape:
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "setArcPath",
|
||
animationId: "anim-5",
|
||
config: {
|
||
enabled: true,
|
||
autoRotate: true, // boolean, or a number (degrees offset)
|
||
segments: [
|
||
{
|
||
curviness: 1.5,
|
||
cp1: { x: 200, y: -80 }, // first control point
|
||
cp2: { x: 400, y: 20 }, // second control point
|
||
},
|
||
],
|
||
},
|
||
});
|
||
```
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `enabled` | `boolean` | Whether the arc path is active. |
|
||
| `autoRotate` | `boolean \| number` | `true` = auto-rotate to follow path tangent; a number offsets the rotation by that many degrees. |
|
||
| `segments` | `Array<{ curviness?, cp1?, cp2? }>` | Per-segment path definition. `curviness` is a GSAP Bezier curviness value; `cp1`/`cp2` are control-point coordinates in composition space. |
|
||
|
||
### updateArcSegment
|
||
|
||
```typescript
|
||
comp.dispatch({
|
||
type: "updateArcSegment",
|
||
animationId: "anim-5",
|
||
segmentIndex: 0,
|
||
update: { curviness: 2, cp1: { x: 220, y: -100 } },
|
||
});
|
||
```
|
||
|