mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 07:19:52 +00:00
feat(sdk): ws-b variables/brand — object-valued font/image + B1 JSON model (#1569)
## WS-B — variables / brand, object-valued (end-to-end)
Part of the AI Studio (Pacific) SDK integration. **Base of the SDK-hotspot stack** (`main → ws-b → ws-c → ws-d → ws-3c → ws-3f`).
### Problem
The variable system was split-brained: SDK `setVariableValue` wrote a `--{id}` CSS custom prop, while the runtime `getVariables()` read a separate JSON model (`data-composition-variables` / `__hfVariables`). The two never connected, and there was no `--brand-*` convention. Variables were scalar-only.
### What this does
- **B1 — one source of truth.** `setVariableValue` now drives the runtime variable model (`data-composition-variables` / `__hfVariables`), with CSS compatibility emitted as explicit `stylePath`-based patches alongside the model patch. A brand kit is a variables JSON; a batch of `setVariableValue` re-skins in one frame.
- **B2 — object-valued variables.** The `CompositionVariable` union extends from scalar-only to typed objects: `font` (`{name, source}`) and `image` (`{url, …}`), end-to-end (core union → SDK op → runtime merge). Colors stay scalar (per §7 LOCKED decision).
### Implementation notes
CSS compatibility was moved out of `apply-patches.ts` (where it was incorrectly writing CSS props as a side-effect of model patches, breaking inverse/undo) and into explicit patches emitted in `mutate.ts`. Forward emits `[modelPatch, cssPatch]` for scalars; inverse correctly generates `patchRemove` for the CSS prop when there was no prior CSS prop. Font/image variables never become CSS props.
### Files (12 changed, +441 −32)
- `packages/core`: `core.types.ts`, `lint/rules/composition.ts`, `parsers/htmlParser.ts` (+test), `runtime/validateVariables.ts`
- `packages/sdk`: `engine/mutate.ts` (+test), `engine/apply-patches.ts`, `engine/patches.ts`, `index.ts`, `types.ts`
### Gates
- `bun run build` ✅
- `bun test` SDK 304/0 ✅ · `validateVariables.test.ts` 13/0 ✅
- `bunx oxlint` 0/0 ✅ · `bunx oxfmt --check` ✅
- `fallow audit --gate new-only` ✅ (complexity inherited only)
> The +8 new `htmlParser.test.ts` font/image tests fail under the pre-existing `DOMParser is not defined` happy-dom limitation (main already carries 425 such failures) — not a logic bug; the pure runtime logic is covered by `validateVariables.test.ts`.
### Deferred
Brand-kit picker UI and `batch(setVariableValue × N)` wiring are Pacific-side; per-composition variable scoping beyond `__hfVariablesByComp`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
@@ -14,8 +14,10 @@ import type {
|
||||
EditOp,
|
||||
ElementSnapshot,
|
||||
FindQuery,
|
||||
FontValue,
|
||||
GsapTweenSpec,
|
||||
HfId,
|
||||
ImageValue,
|
||||
JsonPatchOp,
|
||||
OverrideSet,
|
||||
PatchEvent,
|
||||
@@ -133,7 +135,7 @@ class CompositionImpl implements Composition {
|
||||
this.dispatch({ type: "removeElement", target: id });
|
||||
}
|
||||
|
||||
setVariableValue(id: string, value: string | number | boolean): void {
|
||||
setVariableValue(id: string, value: string | number | boolean | FontValue | ImageValue): void {
|
||||
this.dispatch({ type: "setVariableValue", id, value });
|
||||
}
|
||||
|
||||
@@ -269,7 +271,9 @@ class CompositionImpl implements Composition {
|
||||
const key = pathToKey(p.path);
|
||||
if (key !== null) {
|
||||
this.overrides[key] =
|
||||
p.op === "remove" ? null : (p.value as string | number | boolean | null);
|
||||
p.op === "remove"
|
||||
? null
|
||||
: (p.value as string | number | boolean | Record<string, unknown> | null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,7 +457,9 @@ class CompositionImpl implements Composition {
|
||||
const key = pathToKey(p.path);
|
||||
if (key !== null) {
|
||||
this.overrides[key] =
|
||||
p.op === "remove" ? null : (p.value as string | number | boolean | null);
|
||||
p.op === "remove"
|
||||
? null
|
||||
: (p.value as string | number | boolean | Record<string, unknown> | null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user