@hyperframes/inspector 0.0.0-stage → 0.8.152

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +104 -2
  3. package/dist/inspection.js +2007 -0
  4. package/dist/live.js +1288 -0
  5. package/dist/service.js +63122 -0
  6. package/dist/types/core/src/audioAutomation.d.ts +202 -0
  7. package/dist/types/core/src/audioFx.d.ts +181 -0
  8. package/dist/types/core/src/audioGain.d.ts +44 -0
  9. package/dist/types/core/src/colorGrading.d.ts +1959 -0
  10. package/dist/types/core/src/colorGradingCurves.d.ts +8 -0
  11. package/dist/types/core/src/colorLuts.d.ts +24 -0
  12. package/dist/types/core/src/compiler/assetPaths.d.ts +1 -0
  13. package/dist/types/core/src/compiler/compositionAssembly.d.ts +144 -0
  14. package/dist/types/core/src/compiler/compositionScoping.d.ts +28 -0
  15. package/dist/types/core/src/compiler/externalScripts.d.ts +8 -0
  16. package/dist/types/core/src/compiler/htmlBundler.d.ts +74 -0
  17. package/dist/types/core/src/compiler/htmlCompiler.d.ts +18 -0
  18. package/dist/types/core/src/compiler/htmlDocument.d.ts +23 -0
  19. package/dist/types/core/src/compiler/importMaps.d.ts +18 -0
  20. package/dist/types/core/src/compiler/inlineSubCompositions.d.ts +151 -0
  21. package/dist/types/core/src/compiler/rewriteSubCompPaths.d.ts +1 -0
  22. package/dist/types/core/src/compiler/scriptRuns.d.ts +31 -0
  23. package/dist/types/core/src/compiler/selectorIdTokens.d.ts +70 -0
  24. package/dist/types/core/src/compiler/standaloneEntry.d.ts +2 -0
  25. package/dist/types/core/src/compiler/staticGuard.d.ts +7 -0
  26. package/dist/types/core/src/compiler/svgIdNamespacing.d.ts +80 -0
  27. package/dist/types/core/src/compiler/svgSelectorAliases.d.ts +30 -0
  28. package/dist/types/core/src/compiler/timingCompiler.d.ts +89 -0
  29. package/dist/types/core/src/generated/runtime-inline.d.ts +6 -0
  30. package/dist/types/core/src/generated/svg-selector-aliases-inline.d.ts +2 -0
  31. package/dist/types/core/src/inline-scripts/pickerApi.d.ts +32 -0
  32. package/dist/types/core/src/inline-scripts/runtimeContract.d.ts +13 -0
  33. package/dist/types/core/src/mediaTiming.d.ts +41 -0
  34. package/dist/types/core/src/playbackRateBounds.d.ts +1 -0
  35. package/dist/types/core/src/runtime/analytics.d.ts +18 -0
  36. package/dist/types/core/src/runtime/applyVariableBindings.d.ts +47 -0
  37. package/dist/types/core/src/runtime/audioAutomationVolume.d.ts +19 -0
  38. package/dist/types/core/src/runtime/authoredTiming.d.ts +16 -0
  39. package/dist/types/core/src/runtime/compositionDimension.d.ts +5 -0
  40. package/dist/types/core/src/runtime/diagnostics.d.ts +3 -0
  41. package/dist/types/core/src/runtime/domRealm.d.ts +67 -0
  42. package/dist/types/core/src/runtime/flattenedRoot.d.ts +9 -0
  43. package/dist/types/core/src/runtime/getVariables.d.ts +42 -0
  44. package/dist/types/core/src/runtime/globals.d.ts +11 -0
  45. package/dist/types/core/src/runtime/inspectionTypes.d.ts +68 -0
  46. package/dist/types/core/src/runtime/playbackRate.d.ts +26 -0
  47. package/dist/types/core/src/runtime/protocol.d.ts +30 -0
  48. package/dist/types/core/src/runtime/proxySrc.d.ts +3 -0
  49. package/dist/types/core/src/runtime/startExpression.d.ts +14 -0
  50. package/dist/types/core/src/runtime/startResolver.d.ts +21 -0
  51. package/dist/types/core/src/runtime/timelineDuration.d.ts +3 -0
  52. package/dist/types/core/src/runtime/timelineInspection.d.ts +46 -0
  53. package/dist/types/core/src/runtime/timelineValues.d.ts +15 -0
  54. package/dist/types/core/src/runtime/types.d.ts +335 -0
  55. package/dist/types/core/src/runtime/variableScope.d.ts +8 -0
  56. package/dist/types/core/src/safePath.d.ts +49 -0
  57. package/dist/types/core/src/sceneParts.d.ts +9 -0
  58. package/dist/types/core/src/speedRamp.d.ts +59 -0
  59. package/dist/types/core/src/tokenSlug.d.ts +12 -0
  60. package/dist/types/inspector/src/elementMap.d.ts +33 -0
  61. package/dist/types/inspector/src/engine.d.ts +35 -0
  62. package/dist/types/inspector/src/live.d.ts +18 -0
  63. package/dist/types/inspector/src/mapInspection.d.ts +76 -0
  64. package/dist/types/inspector/src/outputSchemas.d.ts +12 -0
  65. package/dist/types/inspector/src/pageQueries.d.ts +21 -0
  66. package/dist/types/inspector/src/pageServer.d.ts +2 -0
  67. package/dist/types/inspector/src/requests.d.ts +5 -0
  68. package/dist/types/inspector/src/service.d.ts +98 -0
  69. package/dist/types/inspector/src/sourceDependencies.d.ts +5 -0
  70. package/dist/types/inspector/src/sources.d.ts +49 -0
  71. package/dist/types/inspector/src/timelineReport.d.ts +28 -0
  72. package/dist/types/inspector/src/tools.d.ts +18 -0
  73. package/dist/types/inspector/src/types.d.ts +1 -0
  74. package/package.json +54 -3
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Native SVG url()/href references resolve by document order, bypassing JS scoping.
3
+ * Rename only colliding, natively referenced SVG ids; leave JS-only ids reachable
4
+ * by libraries that bypass the scoped selector shim. The first unrenamable element
5
+ * keeps the authored id (otherwise the first element does). Renamed elements retain
6
+ * data-hf-authored-id for script lookup compatibility.
7
+ */
8
+ import { type SvgReferenceAlias } from "./svgSelectorAliases.js";
9
+ /** Reused from `compositionScoping.ts`'s `AUTHORED_ROOT_ID_ATTR` in spirit —
10
+ * same purpose (let a renamed id still resolve by its authored name), now
11
+ * generalized from "the composition root" to any renamed descendant. */
12
+ export declare const SVG_AUTHORED_ID_ATTR = "data-hf-authored-id";
13
+ /** Structural shape both a linkedom/live-DOM `Element` and `Document`
14
+ * satisfy — mirrors the narrow-interface pattern `mediaRenderIds.ts` and
15
+ * `compositionAssembly.ts` already use so this module works unmodified
16
+ * across the preview bundler and the render compiler. */
17
+ interface SvgIdQueryable {
18
+ querySelectorAll(selector: string): Iterable<Element>;
19
+ }
20
+ /** One inlined composition instance, as seen in the ASSEMBLED document. */
21
+ export interface SvgIdScope {
22
+ /** The element whose subtree holds this instance's content (the host). */
23
+ root: Element;
24
+ /**
25
+ * Document-unique prefix for ids renamed in this scope — the instance's
26
+ * runtime composition id. An empty namespace freezes IDs while still repairing references:
27
+ * an anonymous host has no identity to prefix with, the same guard
28
+ * `scopeCssToComposition` and `wrapScopedCompositionScript` apply.
29
+ */
30
+ namespace: string;
31
+ /** Root document references follow document order; instances prefer local definitions. */
32
+ referenceTarget?: "document";
33
+ /**
34
+ * Nested composition hosts inside `root` whose content belongs to their
35
+ * OWN scope. Their subtrees are skipped both when collecting this scope's
36
+ * ids and when rewriting its references.
37
+ */
38
+ exclude?: readonly Element[];
39
+ /**
40
+ * This instance's extracted `<style>` text (already removed from the DOM
41
+ * by the inline pipeline). Scanned for `url(#id)` references so a filter
42
+ * that is only applied from a stylesheet still counts as natively
43
+ * referenced. The caller rewrites these strings afterwards via
44
+ * `rewriteSvgIdReferencesInCss` with the returned map.
45
+ */
46
+ cssTexts?: readonly string[];
47
+ }
48
+ /**
49
+ * Rename every colliding, natively-referenced SVG id across the inlined
50
+ * composition instances in `scopes` and rewrite each instance's attribute
51
+ * references (`href`/`xlink:href`, any `url(#id)` funcref — including inside
52
+ * a `style` attribute) to match.
53
+ *
54
+ * Returns one old-id -> new-id map per scope, in the same order, so the
55
+ * caller can apply the identical substitution to that instance's separately
56
+ * extracted `<style>` text via `rewriteSvgIdReferencesInCss`, which this
57
+ * function never sees. Maps include inherited references whose original target
58
+ * was renamed elsewhere; scopes with local definitions keep their own mapping.
59
+ *
60
+ * `document` must be the ASSEMBLED document every scope root lives in: the
61
+ * collision census covers the whole thing, including ids the top-level
62
+ * document declares itself, since those collide with an inlined instance's
63
+ * ids just as two instances collide with each other.
64
+ */
65
+ export declare function namespaceCollidingSvgIds(document: SvgIdQueryable, scopes: readonly SvgIdScope[], finalizedIds?: Set<Element>): Map<string, string>[];
66
+ /**
67
+ * Apply the same id substitution `namespaceCollidingSvgIds` computed to a
68
+ * composition's `<style>` text.
69
+ *
70
+ * `<style>` content is extracted from the DOM and carried around as a raw
71
+ * string by the inline pipeline (see `inlineSubCompositions`'s
72
+ * `scopeSubStyle`), so it is never visited by the attribute walk. Both a bare
73
+ * `#id` selector (`#clip rect { fill: red }`, already scoped to the right
74
+ * instance by #556's composition-box prefix, but still naming the PRE-rename
75
+ * id) and a `url(#id)` declaration value need rewriting here, or a
76
+ * same-composition stylesheet rule silently stops matching the element whose
77
+ * id this module just changed.
78
+ */
79
+ export declare function rewriteSvgIdReferencesInCss(css: string, idMap: ReadonlyMap<string, string>, references?: readonly SvgReferenceAlias[]): string;
80
+ export {};
@@ -0,0 +1,30 @@
1
+ export declare const SVG_REFERENCE_ALIASES_ATTR = "data-hf-svg-reference-aliases";
2
+ export interface SvgReferenceAlias {
3
+ name: string;
4
+ localName: string;
5
+ namespaceURI: string | null;
6
+ before: string;
7
+ after: string;
8
+ }
9
+ interface IdSelectorAlias {
10
+ id: string;
11
+ replacement: string;
12
+ }
13
+ /**
14
+ * With `namespaces` (a live sheet's bindings) only prefixed attribute selectors are
15
+ * rewritten; without it they stay as authored and everything else is rewritten.
16
+ */
17
+ export declare function rewriteSvgSelectors(selector: string, ids: readonly IdSelectorAlias[], references: readonly SvgReferenceAlias[], namespaces?: ReadonlyMap<string, string | null>): string;
18
+ /** Metadata records actual writes; selectors still match current native attribute values. */
19
+ export declare function readSvgReferenceAliases(root: {
20
+ querySelectorAll(selector: string): Iterable<Element>;
21
+ getAttribute?: (name: string) => string | null;
22
+ }, attribute: string, includeDescendants?: boolean): SvgReferenceAlias[];
23
+ export interface SvgSelectorAliases {
24
+ refresh(): void;
25
+ rewrite(selector: string, additional?: readonly IdSelectorAlias[]): string;
26
+ }
27
+ export declare function refreshSvgSelectorAliases(): void;
28
+ /** Compiled scene scripts install once; refreshes stay with the runtime's lifecycle. */
29
+ export declare function ensureSvgSelectorAliases(): void;
30
+ export {};
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Timing Compiler
3
+ *
4
+ * Shared, pure HTML compilation that normalizes timing attributes.
5
+ * Works in both Node.js and browser without a DOM.
6
+ *
7
+ * Guarantees every timed element gets:
8
+ * - id on media elements when missing
9
+ * - data-end (computed from data-start + data-duration when possible)
10
+ * - data-has-audio on <video> elements (false for muted visual-only videos)
11
+ *
12
+ * For elements without data-duration (e.g. videos relying on source duration),
13
+ * this compiler identifies them as "unresolved" so the caller can provide
14
+ * durations via an environment-specific resolver (ffprobe, el.duration, etc.)
15
+ * and call injectDurations() to complete the compilation.
16
+ *
17
+ * Relative `data-start` (`intro`, `intro + 0.5`) is not numeric — leave
18
+ * `data-end` off so extract can resolve the id-ref later.
19
+ */
20
+ import type { RateSpec } from "../speedRamp.js";
21
+ export interface UnresolvedElement {
22
+ id: string;
23
+ tagName: string;
24
+ src?: string;
25
+ start: number;
26
+ end?: number;
27
+ duration?: number;
28
+ mediaStart: number;
29
+ playbackRate: RateSpec;
30
+ compositionSrc?: string;
31
+ }
32
+ export interface ResolvedDuration {
33
+ id: string;
34
+ duration: number;
35
+ }
36
+ export interface ResolvedMediaElement {
37
+ id: string;
38
+ tagName: string;
39
+ src?: string;
40
+ start: number;
41
+ duration: number;
42
+ mediaStart: number;
43
+ playbackRate: RateSpec;
44
+ loop: boolean;
45
+ }
46
+ export interface CompilationResult {
47
+ html: string;
48
+ unresolved: UnresolvedElement[];
49
+ }
50
+ export declare const MEDIA_DURATION_CLAMP_EPSILON_SECONDS = 0.05;
51
+ export declare function shouldClampMediaDuration(declaredDuration: number, maxDuration: number): boolean;
52
+ /**
53
+ * Whether compilation should shorten an authored media slot to its source.
54
+ *
55
+ * Non-looping video intentionally keeps an explicit longer slot: browsers and
56
+ * the render frame injector hold its final frame until that authored slot ends.
57
+ * Audio has no frame to hold, so its slot remains bounded by playable source.
58
+ */
59
+ export declare function shouldClampResolvedMediaDuration(tagName: ResolvedMediaElement["tagName"], declaredDuration: number, maxDuration: number): boolean;
60
+ /**
61
+ * Compile timing attributes in HTML.
62
+ *
63
+ * Phase 1 (static): Adds data-end where data-duration exists,
64
+ * adds data-has-audio on videos.
65
+ *
66
+ * Returns the compiled HTML and a list of elements that could not be
67
+ * resolved statically (missing data-duration). The caller should resolve
68
+ * these via ffprobe / el.duration and call injectDurations().
69
+ */
70
+ export declare function compileTimingAttrs(html: string): CompilationResult;
71
+ /**
72
+ * Inject resolved durations into compiled HTML.
73
+ *
74
+ * For each resolved element, adds data-duration and data-end attributes.
75
+ * Call this after resolving durations via ffprobe, el.duration, or
76
+ * GSAP timeline queries.
77
+ */
78
+ export declare function injectDurations(html: string, resolutions: ResolvedDuration[]): string;
79
+ /**
80
+ * Extract video/audio elements that already have data-duration set.
81
+ * Used by callers to validate declared durations against actual source durations.
82
+ */
83
+ export declare function extractResolvedMedia(html: string): ResolvedMediaElement[];
84
+ /**
85
+ * Clamp existing data-duration and data-end on media elements.
86
+ * For each resolution, replaces the declared duration with the clamped value
87
+ * and recomputes data-end accordingly.
88
+ */
89
+ export declare function clampDurations(html: string, clamps: ResolvedDuration[]): string;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Returns the pre-built hyperframe runtime IIFE as a string constant.
3
+ * This is the production-safe path: no esbuild, no file I/O,
4
+ * no import.meta.url arithmetic.
5
+ */
6
+ export declare function getHyperframeRuntimeScript(): string;
@@ -0,0 +1,2 @@
1
+ /** Returns the pre-built SVG selector alias installer IIFE as a string constant. */
2
+ export declare function getSvgSelectorAliasesScript(): string;
@@ -0,0 +1,32 @@
1
+ export type HyperframePickerBoundingBox = {
2
+ x: number;
3
+ y: number;
4
+ width: number;
5
+ height: number;
6
+ };
7
+ export type HyperframePickerElementInfo = {
8
+ id: string | null;
9
+ tagName: string;
10
+ selector: string;
11
+ label: string;
12
+ boundingBox: HyperframePickerBoundingBox;
13
+ textContent: string | null;
14
+ src: string | null;
15
+ dataAttributes: Record<string, string>;
16
+ };
17
+ export type HyperframePickerApi = {
18
+ enable: () => void;
19
+ disable: () => void;
20
+ isActive: () => boolean;
21
+ getHovered: () => HyperframePickerElementInfo | null;
22
+ getSelected: () => HyperframePickerElementInfo | null;
23
+ getCandidatesAtPoint: (clientX: number, clientY: number, limit?: number) => HyperframePickerElementInfo[];
24
+ pickAtPoint: (clientX: number, clientY: number, index?: number) => HyperframePickerElementInfo | null;
25
+ pickManyAtPoint: (clientX: number, clientY: number, indexes?: number[]) => HyperframePickerElementInfo[];
26
+ describe?: (element: Element) => HyperframePickerElementInfo | null;
27
+ };
28
+ declare global {
29
+ interface Window {
30
+ __HF_PICKER_API?: HyperframePickerApi;
31
+ }
32
+ }
@@ -0,0 +1,13 @@
1
+ export declare const HYPERFRAME_RUNTIME_GLOBALS: {
2
+ readonly player: "__player";
3
+ readonly playerReady: "__playerReady";
4
+ readonly renderReady: "__renderReady";
5
+ readonly timelines: "__timelines";
6
+ readonly clipManifest: "__clipManifest";
7
+ };
8
+ export declare const HYPERFRAME_BRIDGE_SOURCES: {
9
+ readonly parent: "hf-parent";
10
+ readonly preview: "hf-preview";
11
+ };
12
+ export declare const HYPERFRAME_CONTROL_ACTIONS: readonly ["play", "pause", "seek", "set-muted", "set-playback-rate", "set-color-grading", "set-color-grading-compare", "enable-pick-mode", "disable-pick-mode"];
13
+ export type HyperframeControlAction = (typeof HYPERFRAME_CONTROL_ACTIONS)[number];
@@ -0,0 +1,41 @@
1
+ export declare const MEDIA_START_BASIS_ATTR = "data-hf-media-start-basis";
2
+ export type MediaStartBasis = "local" | "global";
3
+ export declare function readMediaStartBasis(value: string | null | undefined): MediaStartBasis;
4
+ /** Resolve authored media time onto the root timeline. Nested media is local
5
+ * by default; only an explicit compatibility marker preserves a legacy
6
+ * root-global value. */
7
+ export declare function resolveAbsoluteMediaStartSeconds(input: {
8
+ authoredStart: number;
9
+ hostStart: number;
10
+ basis?: string | null;
11
+ }): number;
12
+ /** The one rule for a media element's root-timeline start; the runtime and the CLI both call it.
13
+ * `hostStart` is the composition's origin. With no literal start, an auto-injected start, or an
14
+ * origin at 0 there is nothing for the basis to disambiguate, so ordinary resolution applies. */
15
+ export declare function resolveMediaStartSeconds(input: MediaStartInput & {
16
+ ordinaryStart: () => number;
17
+ }): number;
18
+ /** True when the authored start is already root time, so no host offset applies. */
19
+ export declare function isRootGlobalMediaStart(input: MediaStartInput): boolean;
20
+ export interface MediaStartInput {
21
+ authoredStart: number | null;
22
+ hostStart: number;
23
+ hasAutoStart: boolean;
24
+ basis?: string | null;
25
+ }
26
+ /** A composition host's in-point; only a host with one shifts or cuts what it holds. */
27
+ export declare function hostInPointSeconds(host: Pick<Element, "getAttribute">): number;
28
+ /** Main-timeline time of a sub-composition's local t=0: its host's start minus its in-point. */
29
+ export declare function compositionOriginSeconds(hostStart: number, host: Pick<Element, "getAttribute">): number;
30
+ export interface HostSlot {
31
+ start: number;
32
+ end: number;
33
+ }
34
+ /** Each in-point host cuts the span to its own window. */
35
+ export declare function cutToHostSlots(span: {
36
+ start: number;
37
+ end: number;
38
+ }, hosts: readonly HostSlot[]): {
39
+ start: number;
40
+ end: number;
41
+ };
@@ -0,0 +1 @@
1
+ export { MIN_PLAYBACK_RATE, MAX_PLAYBACK_RATE } from "@hyperframes/parsers/media-duration";
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Runtime analytics — vendor-agnostic event emission via postMessage.
3
+ *
4
+ * The host application decides what to do with events: forward to PostHog,
5
+ * Mixpanel, Amplitude, a custom logger, or nothing at all.
6
+ */
7
+ export type RuntimeAnalyticsEvent = "composition_loaded" | "composition_played" | "composition_paused" | "composition_seeked" | "composition_ended" | "element_picked" | "position_edit_fold_skipped" | "timeline_missing_pause" | "auto_marker_install_failed" | "custom_ease_install_failed" | "custom_ease_parse_failed" | "keyframe_ease_repair_failed";
8
+ export type RuntimeAnalyticsProperties = Record<string, string | number | boolean | null>;
9
+ /**
10
+ * Wire the analytics + performance bridge to the runtime's postMessage transport.
11
+ * Called once during runtime bootstrap from `init.ts`.
12
+ */
13
+ export declare function initRuntimeAnalytics(postMessage: (payload: unknown) => void): void;
14
+ /**
15
+ * Emit an analytics event through the bridge.
16
+ * The host app receives it via postMessage and forwards to its analytics provider.
17
+ */
18
+ export declare function emitAnalyticsEvent(event: RuntimeAnalyticsEvent, properties?: RuntimeAnalyticsProperties): void;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Declarative variable bindings — the no-script consumption channel for
3
+ * composition variables (values are fixed for the page's lifetime, so this is
4
+ * seek-safe and deterministic):
5
+ *
6
+ * - `data-var-src="id"` — sets the element's `src` from the variable value
7
+ * (a URL string or an image value `{url}`). Only allowed on media elements
8
+ * (img/video/audio/source) and only for safe URL protocols — a src on a
9
+ * script-executing tag or a `javascript:`/`data:text/html` value is refused.
10
+ * The authored src stays as the fallback when the variable resolves to nothing.
11
+ * - `data-var-text="id"` — sets the element's OWN text from a scalar variable
12
+ * value. Elements with element children keep them: only the direct text
13
+ * node is replaced, mirroring the SDK's setOwnText semantics — a text
14
+ * binding must never delete nested clips or animation targets.
15
+ * - Every scalar variable (and a font value's family name) is applied as a
16
+ * `--{id}` CSS custom property on its composition root, so CSS bindings
17
+ * like `color: var(--accent)` respond to render/preview overrides instead
18
+ * of only the persisted default.
19
+ *
20
+ * Values resolve against the element's owning composition — the same scope
21
+ * chain the color-grading runtime uses: `__hfVariablesByComp[compId]` for
22
+ * inlined sub-compositions, then the top-level merged `getVariables()`.
23
+ *
24
+ * Applied at init AND re-applied after the composition loader inlines
25
+ * external / template sub-compositions (their DOM and per-instance scoped
26
+ * values don't exist at init). Idempotent: re-applying writes the same
27
+ * values.
28
+ */
29
+ /**
30
+ * Strip characters that could smuggle additional declarations or markup out of
31
+ * a var() substitution site. A scalar value folded into `background: var(--x)`
32
+ * or `background-image: url(var(--x))` must not be able to close the declaration
33
+ * and inject a new one (`red; background: url(//evil?data=…)`) — none of these
34
+ * characters is legal in a scalar variable value (string, number, color, font
35
+ * family), so removing them is lossless for real inputs and neutralizes the
36
+ * declaration/URL-exfiltration channel.
37
+ *
38
+ * Exported because the static compiler bakes the same scalars into a stylesheet
39
+ * at build time and has to reach the same result: a value that the runtime
40
+ * strips but a compile-time emit passes through would make the rendered MP4
41
+ * differ from the preview, which is the more dangerous of the two directions.
42
+ */
43
+ export declare function sanitizeCssValue(value: string): string;
44
+ /** The src an element loads, preview proxy aside: its bound variable's value, else its attribute. */
45
+ export declare function unproxiedMediaSrc(el: Element): string | null;
46
+ /** Applies the bindings in `doc`, or only those inside `within` and `within` itself. */
47
+ export declare function applyVariableBindings(doc: Document, within?: Element): void;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The volume lane's gain for an element at a moment in its clip.
3
+ *
4
+ * Volume is not scheduled onto the gain AudioParam the way FX parameters are.
5
+ * The runtime rewrites that gain every tick from `data-volume` and the GSAP
6
+ * seeked value, which would erase a scheduled envelope within a frame — so the
7
+ * lane feeds the same per-tick path the probed `volumeKeyframes` already use,
8
+ * and the render still bakes it into the samples.
9
+ */
10
+ import { type HfAutomationLane } from "../audioAutomation.js";
11
+ /** The lane for `target` inside a `data-automation` value, or null when absent or unreadable. */
12
+ export declare function laneFromAttr(raw: string, target?: string): HfAutomationLane | null;
13
+ /**
14
+ * Gain the lane asks for at `relTime` clip-local seconds, or null when the
15
+ * element has no volume lane and the caller should fall back to its own rules.
16
+ */
17
+ export declare function elementVolumeLaneGain(el: {
18
+ getAttribute?(name: string): string | null;
19
+ }, relTime: number): number | null;
@@ -0,0 +1,16 @@
1
+ export type AuthoredTimingValue = string | number | null | undefined;
2
+ export declare const AUTHORED_DURATION_ATTR = "data-hf-authored-duration";
3
+ export declare const AUTHORED_END_ATTR = "data-hf-authored-end";
4
+ export interface RawAuthoredTiming {
5
+ start?: AuthoredTimingValue;
6
+ duration?: AuthoredTimingValue;
7
+ authoredDuration?: AuthoredTimingValue;
8
+ end?: AuthoredTimingValue;
9
+ authoredEnd?: AuthoredTimingValue;
10
+ }
11
+ export interface AuthoredTimingWindow {
12
+ start: number;
13
+ duration: number | null;
14
+ end: number | null;
15
+ }
16
+ export declare function resolveAuthoredTimingWindow(values: RawAuthoredTiming): AuthoredTimingWindow | null;
@@ -0,0 +1,5 @@
1
+ /** A `data-width`/`data-height` length in CSS px as the stage lays it out, fractions kept. */
2
+ export declare function parseLayoutDimension(value: string | null | undefined): number | null;
3
+ /** The size the runtime reports to its host: whole px, read with `parseInt` as the renderer does. */
4
+ export declare function parseCompositionDimension(value: string | null | undefined): number | null;
5
+ export declare function findRootCompositionElement(doc?: ParentNode): HTMLElement | null;
@@ -0,0 +1,3 @@
1
+ /** The named error readiness waits fail with once start-up or the render-ready publish throws; it stays set. */
2
+ export declare function recordStartupError(error: unknown): void;
3
+ export declare function swallow(label: string, error?: unknown): void;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Realm-independent "what kind of node is this" tests for composition DOM.
3
+ *
4
+ * THE INVARIANT: the runtime never assumes the composition DOM was built by the
5
+ * same JavaScript realm the runtime is running in. It asks what a node IS (node
6
+ * type, namespace, tag name), never which window's constructor made it.
7
+ *
8
+ * Why that matters. `node instanceof HTMLElement` compares against the
9
+ * `HTMLElement` of the realm this module was loaded into, so it answers "which
10
+ * window built this node", not "what is this node". One document can hold
11
+ * elements from several realms at once, and a node keeps the prototype chain of
12
+ * whichever realm created it however it got there.
13
+ *
14
+ * MEASURED, in the Studio preview, on some loads: `<html>`, `<head>` and
15
+ * `<script>` carry the preview frame's prototypes while `<body>` and every
16
+ * element under it carry the editor window's. Tagging each realm's
17
+ * `Element.prototype` before any page script ran and reading the tag back off
18
+ * the live nodes is how that was established. NOT established: how the nodes
19
+ * come to be there. No `adoptNode`, `importNode` or `document.write` call was
20
+ * caught doing it, and the frame is populated by `src`/`srcdoc`, so treat the
21
+ * mechanism as an open question and the mixed realms as a fact.
22
+ *
23
+ * Either way `instanceof` does not throw and does not warn. It just returns
24
+ * false, forever, for every element in the composition, and every guard written
25
+ * as `if (!(node instanceof HTMLElement)) continue;` silently skips the whole
26
+ * document. A whole pass goes dark with no error: the timed-element visibility
27
+ * pass stops writing, so every scene paints on top of every other.
28
+ *
29
+ * `doc.defaultView.HTMLElement` is not a sufficient repair, which is why this
30
+ * module replaced two hand-rolled attempts at it. It fixes the case where the
31
+ * nodes belong to the document's own realm and still fails when they belong to
32
+ * a third one. A structural test has no such case to get wrong.
33
+ *
34
+ * Scope of ownership: these predicates own the RUNTIME's answer to "what kind of
35
+ * node is this", for HTML and SVG, which is everything a composition contains.
36
+ * `packages/studio` still hand-rolls its own checks in several places and is not
37
+ * covered by this module or by the lint guard that keeps `src/runtime` clean
38
+ * (`scripts/lint-runtime-preview-guards.ts`).
39
+ */
40
+ /** Any element node, from any realm (HTML, SVG, MathML). Mirrors `instanceof Element`. */
41
+ export declare function isElementNode(value: unknown): value is Element;
42
+ /**
43
+ * An HTML element, from any realm. Mirrors `instanceof HTMLElement`, including
44
+ * its exclusion of SVG/MathML: "is an HTMLElement" and "is an element in the
45
+ * XHTML namespace" are the same set.
46
+ */
47
+ export declare function isHtmlElement(value: unknown): value is HTMLElement;
48
+ /** `<video>`, from any realm. Mirrors `instanceof HTMLVideoElement`. */
49
+ export declare function isVideoElement(value: unknown): value is HTMLVideoElement;
50
+ /** `<audio>`, from any realm. Mirrors `instanceof HTMLAudioElement`. */
51
+ export declare function isAudioElement(value: unknown): value is HTMLAudioElement;
52
+ /** `<video>` or `<audio>`, from any realm. Mirrors `instanceof HTMLMediaElement`. */
53
+ export declare function isMediaElement(value: unknown): value is HTMLMediaElement;
54
+ /** `<img>`, from any realm. Mirrors `instanceof HTMLImageElement`. */
55
+ export declare function isImageElement(value: unknown): value is HTMLImageElement;
56
+ /** `<canvas>`, from any realm. Mirrors `instanceof HTMLCanvasElement`. */
57
+ export declare function isCanvasElement(value: unknown): value is HTMLCanvasElement;
58
+ /** `<style>`, from any realm. Mirrors `instanceof HTMLStyleElement`. */
59
+ export declare function isStyleElement(value: unknown): value is HTMLStyleElement;
60
+ /** `<link>`, from any realm. Mirrors `instanceof HTMLLinkElement`. */
61
+ export declare function isLinkElement(value: unknown): value is HTMLLinkElement;
62
+ /**
63
+ * An element that carries a CSS `style` map: HTML **or** SVG. Position edits and
64
+ * transform writes apply to both (authored SVG `<text>`/shapes honour the CSS
65
+ * `translate` longhand exactly as HTML does).
66
+ */
67
+ export declare function isStylableElement(value: unknown): value is HTMLElement | SVGElement;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Shared between the build-time bundler (htmlBundler) and the runtime
3
+ * composition loader: when a sub-composition's inner root is flattened into
4
+ * its host, these timing/identity attributes must be stripped and the
5
+ * authored id preserved as data — identical semantics in both worlds.
6
+ */
7
+ export declare const FLATTENED_INNER_ROOT_STRIP_ATTRS: string[];
8
+ /** Strip timing attrs, demote the authored id, and mark the flattened root. */
9
+ export declare function markFlattenedInnerRoot(prepared: Element): void;
@@ -0,0 +1,42 @@
1
+ export declare function getVariables<T extends Record<string, unknown> = Record<string, unknown>>(): Partial<T>;
2
+ export declare function warnUnknownEnumValues(declarer: Element | null | undefined, resolved: Record<string, unknown>, compositionId?: string): void;
3
+ /** Test-only: clear the per-page dedupe set. */
4
+ export declare function resetUnknownEnumWarnings(): void;
5
+ /**
6
+ * Extract `{id: default}` map from an element's `data-composition-variables`
7
+ * attribute. Returns an empty object when the attribute is missing, the JSON
8
+ * is unparseable, or the payload isn't an array. Exported so the
9
+ * compositionLoader can compute the same defaults map for sub-comp instances.
10
+ */
11
+ export declare function readDeclaredDefaults(root: Element | null): Record<string, unknown>;
12
+ /**
13
+ * Define primitive-valued variables as CSS custom properties on `target`,
14
+ * recording the applied names so re-init/unmount can clear them. Empty
15
+ * strings are skipped — CSSOM setProperty("", …) REMOVES the property, and a
16
+ * blank default has no CSS meaning anyway.
17
+ */
18
+ export declare function applyCssVariables(target: Element, variables: Record<string, unknown>): void;
19
+ /** Keep only variables whose CSS custom property is not already defined. */
20
+ export declare function filterVariablesIfAbsent(target: Element, variables: Record<string, unknown>, view: Window | null): Record<string, unknown>;
21
+ /** Remove custom properties a previous applyCssVariables call defined. */
22
+ export declare function clearAppliedCssVariables(target: Element): void;
23
+ /**
24
+ * Imported figma components reference brand tokens as `var(--slug, literal)`.
25
+ * Define each declaring element's composition variables as CSS custom
26
+ * properties ON THAT ELEMENT — scoping by the cascade, so two compositions
27
+ * on one page can't clobber each other and a flattened sub-composition root
28
+ * correctly styles only its own subtree.
29
+ *
30
+ * Declared DEFAULTS are define-if-absent: a value the author already styled
31
+ * (stylesheet `:root` rule, compile-time emission, hand-written inline) wins
32
+ * over the declared default, preserving pre-existing conventions where a
33
+ * variable id coincides with an authored custom property. Render-time
34
+ * overrides (`--variables` → `window.__hfVariables`) always win — that's
35
+ * explicit user intent.
36
+ */
37
+ export declare function injectCompositionCssVariables(doc: Document): void;
38
+ /** Parse a host element's `data-variable-values` JSON attribute (per-instance
39
+ * sub-composition overrides). Shared by the runtime loader and the bundler. */
40
+ export declare function parseHostVariableValues(host: Element): Record<string, unknown>;
41
+ /** Render-time variable overrides (`hyperframes render --variables`). */
42
+ export declare function readRenderOverrides(): Record<string, unknown>;
@@ -0,0 +1,11 @@
1
+ export interface HFDebugSurface {
2
+ __hfDebug?: boolean;
3
+ __HYPERFRAMES_DEBUG?: boolean;
4
+ __hf?: {
5
+ onSwallowed?: (event: {
6
+ label: string;
7
+ error: unknown;
8
+ }) => void;
9
+ };
10
+ }
11
+ export declare function getDebugSurface(): HFDebugSurface;
@@ -0,0 +1,68 @@
1
+ export type Target = {
2
+ selector: string;
3
+ within?: string;
4
+ } | {
5
+ hfId: string;
6
+ within?: string;
7
+ } | {
8
+ ref: string;
9
+ };
10
+ export interface InspectRequest {
11
+ targets: Target[];
12
+ descendants?: boolean;
13
+ maxBytes?: number;
14
+ time?: number;
15
+ snippets?: string[];
16
+ offset?: number;
17
+ generation?: string;
18
+ debug?: boolean;
19
+ }
20
+ export interface ElementRef {
21
+ ref: string;
22
+ tag: string;
23
+ id: string;
24
+ hfId: string | null;
25
+ classes: string[];
26
+ composition: string | null;
27
+ }
28
+ export interface RuntimeAnimation {
29
+ stack: string | null;
30
+ properties: string[];
31
+ targets: ElementRef[];
32
+ localStart: number;
33
+ duration: number;
34
+ attachmentStacks: string[];
35
+ }
36
+ export interface RuntimeResult {
37
+ target: Target;
38
+ status: "found" | "missing" | "ambiguous" | "stale-ref" | "invalid-selector";
39
+ candidates: ElementRef[];
40
+ animations: RuntimeAnimation[];
41
+ elements: ElementRef[];
42
+ css: string[];
43
+ truncated: boolean;
44
+ }
45
+ export interface RuntimeQuery {
46
+ targets: Target[];
47
+ descendants: boolean;
48
+ cssRules: {
49
+ id: string;
50
+ selector: string;
51
+ }[];
52
+ }
53
+ export interface RuntimeResponse {
54
+ results: RuntimeResult[];
55
+ recorded: number;
56
+ recordLimitReached: boolean;
57
+ hooked: boolean;
58
+ }
59
+ export interface Snippet {
60
+ id: string;
61
+ file: string;
62
+ startLine: number;
63
+ endLine: number;
64
+ kind: string[];
65
+ targets: number[];
66
+ code: string;
67
+ uniqueInFile: boolean;
68
+ }
@@ -0,0 +1,26 @@
1
+ import { clampPlaybackRate } from "@hyperframes/parsers/media-duration";
2
+ import { type RateSpec } from "../speedRamp.js";
3
+ export declare const normalizePlaybackRate: typeof clampPlaybackRate;
4
+ /** Parse a literal numeric timing attribute without accepting trailing units or garbage. */
5
+ export declare function parseStrictFiniteTimingNumber(raw: string | null | undefined): number | null;
6
+ export declare function readElementPlaybackRate(el: Pick<Element, "getAttribute">): number;
7
+ /** A constant rate clamped to the shared range; a lane is already normalised by its parser. */
8
+ export declare function normalizeRateSpec(spec: RateSpec | undefined): RateSpec;
9
+ /** The clip's rate: its `rate` lane when present, otherwise the constant rate. */
10
+ export declare function readElementRateSpec(el: Pick<Element, "getAttribute">): RateSpec;
11
+ export declare function readMediaStart(el: Pick<Element, "getAttribute">): number;
12
+ export declare function resolveNaturalMediaTimelineDuration(el: Pick<Element, "getAttribute">, sourceDuration: number): number | null;
13
+ /**
14
+ * How long a media element occupies the timeline: an authored `data-duration` trim, otherwise
15
+ * the source's natural length adjusted for playback start and rate (lane-aware). `null` while
16
+ * the source has not reported a duration yet. The authored/pending decision is the shared
17
+ * parsers resolver's; only a `rate` lane's arithmetic stays here, because lanes live in core.
18
+ */
19
+ export declare function resolveMediaElementDurationSeconds(el: Pick<Element, "getAttribute"> & {
20
+ duration: number;
21
+ }): number | null;
22
+ /** A timed `<img>` (`data-start` or `data-track-index`) gets the dropped-image default unless
23
+ * trimmed by `data-duration` or `data-end`; a bare `<img>` is a static layer. `null` otherwise. */
24
+ export declare function resolveTimedImageDurationSeconds(el: Element, startSeconds?: number): number | null;
25
+ /** A constant rate goes through the shared arithmetic; a `rate` lane integrates over its points. */
26
+ export declare function resolveNaturalMediaTimelineDurationFromValues(sourceDuration: number, mediaStart: number, playbackRate: RateSpec): number | null;