docs(sdk): document attachSync, variable CRUD, and getRootElements/getAllAnimationIds

These SDK reference docs were behind the API surface: PR #2100's attachSync
had zero documentation, and PR #2098/#2092's declareVariable, removeVariable,
getVariableValue, listVariables, and getRootElements were all missing from
composition.mdx despite being real public Composition methods. getAllAnimationIds
was also undocumented (pre-existing gap, unrelated to this stack).

- composition.mdx: adds getVariableValue, listVariables, declareVariable,
  removeVariable (Typed edit methods), getRootElements, getAllAnimationIds
  (Query section)
- adapters.mdx: adds attachSync to the PreviewAdapter interface + a
  ParamField documenting its contract (immediate sync, ongoing patch
  mirroring, script-patch exclusion, detach semantics)
- edit-operations.mdx: adds declareVariable/removeVariable rows + examples
  to the Variables op table
This commit is contained in:
Vance Ingalls
2026-07-09 11:52:14 -07:00
parent c94de6034e
commit 91cc67a007
3 changed files with 116 additions and 1 deletions
+16
View File
@@ -92,6 +92,7 @@ interface PreviewAdapter {
cancelPreview(): void;
select(ids: string[], opts?: { additive?: boolean }): void;
on(event: "selection", handler: (ids: string[]) => void): () => void;
attachSync(comp: Composition): () => void;
}
```
@@ -119,6 +120,21 @@ interface PreviewAdapter {
Fired when the preview host changes the selection (for example, the user clicks an element). Returns an unsubscribe function. In the current release, callers listen to the session's own `selectionchange` event instead — this hook is wired in a future stage.
</ParamField>
<ParamField path="attachSync" type="(comp: Composition) => () => void">
Mirrors a composition's edits onto the adapter's own live document: an immediate full sync of the composition's current overrides, then a subscription that replays every future `patch` event — including undo/redo, since both fire through the same event with forward or inverse patches. Calling `attachSync` again while already attached detaches the previous subscription first. Returns an unsubscribe function.
Script-tag patches (`/script/gsap` and any future `/script/*` path) are never mirrored — rewriting a live `<script>` tag's content doesn't re-execute it, and re-running GSAP setup from scratch would conflict with running timeline state. Every other patch kind (style, text, attribute, timing, hold, element add/remove, stylesheet, variable value, variable declaration) mirrors as-is.
```typescript
const adapter = createIframePreviewAdapter(iframe, dispatch);
const comp = await openComposition(html, { preview: adapter });
const detach = adapter.attachSync(comp);
// later, if the host tears down the preview:
detach();
```
</ParamField>
### ElementAtPointResult
```typescript
+83
View File
@@ -110,6 +110,65 @@ comp.setVariableValue("brandFont", { name: "Inter", source: "https://fonts.googl
comp.setVariableValue("heroImage", { url: "/assets/hero.jpg", fit: "cover" });
```
<Note>
`setVariableValue` only updates a variable's current value — it refuses to create an undeclared variable. Use `declareVariable` to create one.
</Note>
### `getVariableValue`
```typescript
getVariableValue(id: string): string | number | boolean | FontValue | ImageValue | undefined
```
Return a declared variable's current `default` value, or `undefined` if the id is undeclared or has no value set.
```typescript
const color = comp.getVariableValue("brandColor"); // "#6C5CE7"
```
### `listVariables`
```typescript
listVariables(): CompositionVariable[]
```
Return every declared variable's full schema — `id`, `type`, `label`, `default`, and any type-specific fields (`min`/`max`/`step` for numbers, `options` for enums, `source` for fonts, etc). Returns `[]` when the composition declares no variables.
```typescript
for (const v of comp.listVariables()) {
console.log(v.id, v.type, v.default);
}
```
### `declareVariable`
```typescript
declareVariable(decl: CompositionVariable): void
```
Create a new variable declaration, or fully replace an existing one (type, label, default, and all other schema fields — not just the value). This is the only path that creates the schema entry from scratch; `setVariableValue` intentionally refuses to.
```typescript
comp.declareVariable({
id: "brandColor",
type: "color",
label: "Brand color",
default: "#6C5CE7",
});
```
### `removeVariable`
```typescript
removeVariable(id: string): void
```
Remove a variable's declaration entirely. Any live `var.{id}` overrides and `data-var-*` DOM references are left untouched — this only removes the schema entry.
```typescript
comp.removeVariable("brandColor");
```
### `getElementTimings`
```typescript
@@ -300,6 +359,18 @@ const images = elements.filter((el) => el.tag === "img");
For elements inside inlined sub-compositions, use `scopedId` (e.g. `"hf-host/hf-leaf"`) as the dispatch target, not `id`. Top-level elements have `scopedId === id`.
</Note>
### `getRootElements`
```typescript
getRootElements(): ElementSnapshot[]
```
Return only top-level elements, each carrying its full subtree — no id appears twice (unlike `getElements`, which flattens every nested element into the same array). Use this when you need one entry per top-level clip rather than every element in the tree.
```typescript
const roots = comp.getRootElements();
```
### `getElement`
```typescript
@@ -337,6 +408,18 @@ const allImages = comp.find({ tag: "img" });
const track1Ids = comp.find({ track: 1 });
```
### `getAllAnimationIds`
```typescript
getAllAnimationIds(): Set<string>
```
Return every GSAP tween id parsed from the composition's script, regardless of whether its target selector currently matches a live DOM element. This differs from a given `ElementSnapshot`'s own `animationIds` field, which only lists tweens whose selector resolves to that specific element.
```typescript
const allIds = comp.getAllAnimationIds();
```
---
## Selection
+17 -1
View File
@@ -263,7 +263,9 @@ comp.dispatch({
| `type` | Key fields | What it does |
|--------|-----------|--------------|
| `setVariableValue` | `id`, `value` | Sets a composition variable by id. Value may be a string, number, boolean, `FontValue`, or `ImageValue`. |
| `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
@@ -293,6 +295,20 @@ comp.dispatch({
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" });
```
---