mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-10 22:20:14 +00:00
feat(core): scope getVariables() per sub-comp instance
Building on PR 1's getVariables() helper, this PR routes per-instance values into the correct sub-composition. Same composition source can now be embedded N times with different content via data-variable-values on each host element. How it works: - compositionLoader, before injecting wrapped scripts, layers the host element's data-variable-values JSON over the sub-comp's declared defaults (its own data-composition-variables) and writes the merged object to window.__hfVariablesByComp[compositionId]. Skipped when both sides are empty so the table only grows for instances that actually carry values. - compositionScoping's wrapper IIFE now takes a fourth parameter __hyperframes alongside the existing scoped document/gsap/window. The scoped __hyperframes shadows getVariables() to read from __hfVariablesByComp[__hfCompId], returning a fresh object each call so script mutations don't leak into the shared table. - Top-level scripts (not wrapped by compositionScoping) keep using the unscoped window.__hyperframes.getVariables(), which reads data-composition-variables defaults plus the CLI override (window.__hfVariables) — same path as PR 1. - readDeclaredDefaults is exported from getVariables.ts so the loader reuses the exact same defaults-extraction logic the helper uses for the top-level path. Inline templates (no separate <html> document root) get host overrides only — no declared defaults — since there's no separate <html> to read data-composition-variables from. External sub-comps fetched via data-composition-src get the full declared defaults + host overrides merge. Tests: 3 new compositionScoping tests covering scoped getVariables invocation, missing-entry fallback, and mutation isolation. 5 new compositionLoader tests covering merge order, declared-only path, empty-skip, invalid-host-JSON resilience, and per-instance scoping across two hosts sharing a source. 3 new getVariables tests covering the newly-public readDeclaredDefaults. All 622 core tests green. Docs: docs/concepts/compositions.mdx switched its sub-comp example from hand-rolled JSON.parse(host.dataset.variableValues) to the new __hyperframes.getVariables() pattern. data-attributes.mdx clarifies per-instance scoping behavior. This is PR 2 of a 4-PR stack. PR 3 adds schema validation + lint; PR 4 ships skill / scaffold updates. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
James Russo
co-authored by
Claude Opus 4.7
parent
03b82e6ff8
commit
484ab54442
@@ -1,10 +1,17 @@
|
||||
/**
|
||||
* Reads the resolved variables for the current composition.
|
||||
*
|
||||
* Resolves to declared defaults from `<html data-composition-variables="...">`
|
||||
* Top-level path: declared defaults from `<html data-composition-variables="...">`
|
||||
* merged with `window.__hfVariables` (set at render time by the engine when
|
||||
* the user passes `hyperframes render --variables '<json>'`).
|
||||
*
|
||||
* Sub-comp path (per-instance scoping): when called inside a sub-composition
|
||||
* script wrapped by `compositionScoping.ts`, the wrapper shadows
|
||||
* `__hyperframes.getVariables` with a scoped variant that returns the
|
||||
* pre-merged values from `window.__hfVariablesByComp[compositionId]`. The
|
||||
* loader populates that table before running scripts, layering the host
|
||||
* element's `data-variable-values` over the sub-comp's declared defaults.
|
||||
*
|
||||
* Returns `Partial<T>` because not every declared variable is guaranteed to
|
||||
* have a default, and not every key in `__hfVariables` is guaranteed to be
|
||||
* declared. Callers are expected to destructure with their own fallbacks
|
||||
@@ -23,7 +30,13 @@ export function getVariables<
|
||||
return { ...declaredDefaults, ...overrides } as Partial<T>;
|
||||
}
|
||||
|
||||
function readDeclaredDefaults(root: Element | null): Record<string, unknown> {
|
||||
/**
|
||||
* Extract `{id: default}` map from an element's `data-composition-variables`
|
||||
* attribute. Returns an empty object when the attribute is missing, the JSON
|
||||
* is unparseable, or the payload isn't an array. Exported so the
|
||||
* compositionLoader can compute the same defaults map for sub-comp instances.
|
||||
*/
|
||||
export function readDeclaredDefaults(root: Element | null): Record<string, unknown> {
|
||||
if (!root) return {};
|
||||
const raw = root.getAttribute("data-composition-variables");
|
||||
if (!raw) return {};
|
||||
|
||||
Reference in New Issue
Block a user