Commit Graph

16 Commits

Author SHA1 Message Date
ukimsanov 8e658bd6c9 docs(sdk): fix dispatch/can contract, second stale GSAP site, media-start layers
- edit-operations: dispatch() does not consult can() (session.ts:608 -> applyOp
  with no validation; a no-timeline addGsapTween/addLabel is a no-op but a missing
  target still writes via selector fallback). Use Rames's wording: call can() first
  and skip on failure — no false 'applies nothing' guarantee.
- timing-and-animation: the second E_NO_GSAP_TIMELINE site — gated setGsapTween on
  an error it cannot return and called shipped parser code 'a later phase'. Rewrote
  to gate addGsapTween (which can return it); dropped the stale can() comment in
  types.ts:595.
- html-schema: data-playback-start is read by runtime, Studio and CLI (Studio also
  writes it, timelineEditingHelpers.ts); only the compile path is media-start only.
  Document the layered precedence instead of calling it runtime-only.

Round-2 findings from Magi (#2/#3/#4) and Rames.
2026-08-05 10:13:17 -07:00
ukimsanov 0f6259d461 docs: correct three source-contradiction findings from review
- edit-operations: E_NO_GSAP_TIMELINE is raised only by addGsapTween and addLabel
  (mutate.ts:1747), not the set/remove tween ops; drop the false 'dispatch() still
  applies structurally' claim (mutate.gsap.test.ts verifies zero patches); add the
  requirement to the Labels section where addLabel lives.
- html-schema: data-media-start is read by parser + timing compiler + runtime;
  data-playback-start is a runtime-only alias, so a lone playback-start doesn't
  shift trim/split. Document the surfaces instead of claiming one universal value.
- testing-local-changes: bun unlink cleanup used a relative cd that resolves under
  the video project; use an absolute checkout path.

Flagged by Magi (P1 #2/#3, P2 #7) and Rames.
2026-08-05 05:43:35 -07:00
ukimsanov d3331aad28 docs: E_NO_GSAP_TIMELINE is not a missing feature
Five places across two SDK pages said this error means the GSAP parser engine "is
not yet available" / "ships in a later phase" / "until it ships". The parser is
shipped — sdk/src/document.ts:13 and engine/mutate.ts:58 both import and call
parseGsapScriptAcornForWrite.

What the code actually returns (mutate.ts:1745-1751):

  "No gsap.timeline() declaration found in the GSAP script."
  hint: "addGsapTween / addLabel require a timeline variable
         (e.g. var tl = gsap.timeline(...))."

It is a fixable authoring problem in the reader's own composition, and the fix is
one line. Told it is an unshipped feature, a reader waits instead — and the Note
listing six ops as unavailable made a working part of the SDK look absent.

All five sites now say what the error means and how to clear it, including the
code comment in the guide's example.
2026-08-04 14:46:04 -07:00
ukimsanov af5ebf09ce docs: four more the source contradicts, one of them mine
**`declareVariable`'s field is `declaration`, not `decl`.** Documented wrong in
three places across two SDK reference pages. This one fails *silently* — the
handler reads `op.declaration`, gets undefined, and returns EMPTY at
sdk/src/engine/mutate.ts:991. No throw, no patch, no error. A reader copies the
example and nothing happens. types.mdx opens by claiming it was verified against
types.ts, which is where the correct name is (line 134).

**Colour grading says eighteen presets; the Grade panel has thirteen.** Eighteen
is the combined total. The other five carry effects and live in the Effects
panel — colorGrading.ts derives GRADE_PRESETS by filtering EFFECT_PRESETS out,
and colorGrading.test.ts:25 asserts VHS Playback is *not* in Grade. I wrote that
sentence today and used VHS Playback as the example, so the page sent a reader to
Grade looking for something that is not there. The visual brief further down had
the same error baked in; fixed before anyone shoots it.

**`hyperframes render` on a slideshow does not fail — it lies.** The page said
export "is not currently supported", which reads like the command errors. The
skill is emphatic: a deck has no master root composition, so render resolves only
the first slide and writes a silently truncated MP4 — six seconds of a
forty-second deck, no warning. That is now a Warning saying exactly that.

I also swept every documented edit-operation field against sdk/src/types.ts.
Six looked wrong and five were my regex not stripping the `?` optional marker;
`easeEach` and `resolvedSelector` are real, at types.ts:178-179. One genuine
error out of that sweep, the one above.
2026-08-04 14:27:52 -07:00
ukimsanov a99ad218f7 docs: fix the types page subtitle to match its softened claim
Rames' residual on #2974. I softened the body sentence last round and left the
frontmatter saying "All exported types from @hyperframes/sdk". Mintlify renders
description as both the page subtitle and the meta description, so the page went
on promising complete coverage in the two places a reader meets first — and the
one a search engine quotes.

Pre-existing on main, and he did not hold the stamp for it, but leaving it makes
the body fix cosmetic.
2026-08-04 02:45:21 -07:00
ukimsanov 7a91b93dd6 docs: correct four developer-reference claims the source contradicts
Miguel's three P2s and Rames' one finding on #2974, all verified in source
before changing anything.

**`render --json` is not a progress stream.** It prints exactly one
`batch-complete` document at the end (`batchRender.ts:408-418`), asserted as a
single `console.log` in `batchRender.test.ts`. Described as a final result now.

**The iframe drag example never captured the pointer.** `event.target` comes
from `iframe.contentDocument`, so `instanceof Element` against this window's
constructor is always false for a cross-realm node and `setPointerCapture()`
never ran — a pointer leaving the frame then loses `pointerup` and drag state
sticks. Structural feature detection instead, with the reason in a comment so it
does not get "simplified" back.

**The preview adapter example did not compile under strict TypeScript.** `comp`
was captured by the callback before definite assignment (TS2454). Optional, with
`comp?.dispatch(op)`.

**`ORIGIN_APPLY_PATCHES` was imported in a fence that did not use it and used in
fences that did not import it.** Imports do not cross fences, so both examples
were wrong in opposite directions. Rames found the pair in
`open-composition.mdx`; the same shape is in `composition.mdx:630`, which he did
not name. All three fences are self-contained now.

**And `types.mdx` claimed coverage it does not have.** It promised "every type
exported from `@hyperframes/sdk`" while omitting 13 of 42. Eleven are documented
on sibling pages, so the sentence now points at those instead of overclaiming.
The two with no home anywhere — `CompositionVariableType` and
`VariableUsageScan`, both re-exported from the barrel — have entries. The second
is worth having written down: `scanIncomplete` means `usedIds` is a lower bound,
so an id missing from it is unknown rather than unused.
2026-08-04 02:45:21 -07:00
ukimsanov bebaf679d9 docs: rebuild developer and rendering reference 2026-08-04 02:45:21 -07:00
Vance Ingalls 4682da14f1 fix(sdk): attachSync re-syncs the override snapshot on iframe load 2026-07-15 14:50:41 -07:00
Vance Ingalls db5e062211 feat(sdk): getVariableValue({ base: true }) reads pre-override declared defaults 2026-07-15 14:50:33 -07:00
James 8de80bf369 feat(sdk,studio): editable template sub-compositions + promote sub-comp element properties 2026-07-09 13:31:04 -07:00
James 010d49327e feat(studio): render with preview variables + template handoff + docs
Sixth PR of the template-variables Studio stack — closing the loop from
preview to render to developer handoff.

- renders started from the Renders tab now carry the active preview
  variable overrides (StartRenderOptions.variables → POST /render →
  RenderConfig.variables), so "render" produces exactly what the user is
  previewing.
- Variables panel "Use this template" footer: copy the effective values
  (defaults merged with overrides) as JSON, or as a ready-to-run
  `npx hyperframes render <comp> --variables '<json>'` command.
- gitignore: negate the renders/ output rule for the tracked
  src/components/renders/ source dir — without it, pre-commit's format
  re-stage (`git add {staged_files}`) hard-fails on any change to those
  files.
- docs: the Studio panel docs/concepts/variables.mdx described was
  aspirational — replace with the real Variables-in-Studio section
  (declare/edit, render-truthful preview, render-with-values, handoff,
  usage badges); document the new SDK variable APIs in
  docs/sdk/reference/composition.mdx (declaration ops, read APIs,
  setPreviewVariables).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 13:31:03 -07:00
Vance Ingalls f169d5fad6 docs(sdk): document CompositionVariable, id/variable utilities, and attachSync in canvas guide
Follow-up to the previous commit in this PR — found while auditing whether
any SDK-surface documentation gaps existed beyond this stack:

- types.mdx: EditOp's own union listing was missing declareVariable/
  removeVariable (present in edit-operations.mdx's table but not mirrored
  here). Adds a full CompositionVariable reference section (base fields +
  all 7 variants) since composition.mdx's new declareVariable/listVariables
  docs reference it without it being defined anywhere in the type reference.
- utilities.mdx: documents 6 exported functions with zero prior docs —
  resolveScoped, findById, bareId, escapeHfId, isNewHostBoundary (Id & Scope
  Utilities) and readVariableDefault (Variable Utilities). Pre-existing gaps,
  unrelated to this stack.
- canvas-integration.mdx: adds a "Keeping the preview in sync" section
  covering attachSync right where the guide already sets up preview + comp —
  previously the guide never mentioned it despite being exactly the answer
  to "how do I keep the iframe in sync with edits."
2026-07-09 11:52:14 -07:00
Vance Ingalls 91cc67a007 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
2026-07-09 11:52:14 -07:00
Vance Ingalls 74faa4b2a4 fix(sdk): moveElement survives GSAP animation per-axis via runtime delta translate (#1875)
* fix(sdk): moveElement survives GSAP animation per-axis via runtime delta translate

A committed moveElement wrote data-x/data-y but nothing rendered them:
hosts shimmed CSS translate, which GSAP folds into the cached transform
at first parse and then discards on the animated axis at every seek —
dragging an animated element kept only the un-animated axis.

Spike-proven on GSAP 3.15: a translate set AFTER GSAP's first parse is
never read, folded, or cleared across seeks and composes natively with
the animated transform. So:

- moveElement captures the pre-edit baseline once (data-hf-edit-base-x/y)
- the runtime (new core runtime/positionEdits.ts, applied at timeline
  bind — after GSAP parse) renders translate = (data-x − base), a pure
  delta that composes with GSAP tweens, tl.set positions, and CSS alike
- applyDraft now drives the drag preview through the same translate
  channel (the --hf-studio-dx/dy vars had no consumer outside authored
  Studio bridges), and commitPreview mirrors the committed move onto
  the live element so it holds without an srcdoc reload

Acceptance: packages/engine/scripts/test-runtime-position-edits-browser.ts
(real Chrome + GSAP + runtime IIFE, no Studio shell) — X-animated,
Y-animated, and static elements hold both edited axes across the full
seek range. New subpath export @hyperframes/core/runtime/position-edits.

Known limitation (documented): a tween created lazily at runtime that
first-parses a marked element after apply folds the edit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(sdk): harden position-edit rendering and the drag draft channel

Fixes six issues from adversarial review of the moveElement stack:

- Runtime: apply position edits at init as well as at timeline bind, so
  committed moves render in compositions with no usable GSAP timeline
  (CSS/WAAPI-animated or fully static) — previously the apply was
  unreachable outside the boundDuration > 0 bind branch and the edit
  silently vanished from reloads and renders.
- Runtime: guard bind-path re-apply against post-fold double-apply — if
  the previously written translate was consumed externally (a lazily
  created tween folding it into GSAP's cached transform), skip instead
  of re-setting it on top ({force} escape hatch for editor commits).
- Adapter: stop writing the --hf-studio-dx/dy custom properties during
  drags — compositions with the documented var-consuming drag-bridge
  CSS moved by twice the pointer delta (var transform + new inline
  translate). The inline translate is now the only draft channel;
  deltas accumulate in adapter fields. Docs updated to match.
- Adapter: switching applyDraft to a new id reverts the abandoned
  element's draft translate instead of leaving it displaced with no op.
- Adapter: cancelPreview restores the raw inline translate (removing it
  when there was none), so a stylesheet-authored translate is never
  promoted to a permanent inline style.
- Adapter: commitPreview reverts the draft and clears state when
  dispatch throws, instead of leaving the element shifted by an
  uncommitted draft.

Cleanups: reuse readCurrentTranslate from the core module (was a
verbatim copy), drop the dead __hfApplyPositionEdits window hook.
Browser acceptance test now also covers the GSAP-free composition path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(core): prime GSAP transform cache before position-edit apply; add fold-loss telemetry

Addresses PR #1875 review feedback (Rames, Miga):

- Prime the element's GSAP transform parse (gsap.getProperty) before the
  first translate apply — positioned tl.set()s and tweens that first
  RENDER after the apply now reuse the cache instead of folding the edit.
  This closes the lazy-first-parse fold-loss for any page where GSAP is
  loaded at apply time; the residual limitation is GSAP itself loading
  after the apply. Proven by the extended browser acceptance test.
- Emit position_edit_fold_skipped analytics at the fold-guard skip site
  so the residual degradation is observable instead of silent.
- Browser acceptance test: add a both-axis-animated element (the shape
  that originated the per-axis loss) and a positioned tl.set() element,
  asserted across the full seek range.
- Simplify the num() null guard (review nit).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 20:44:27 -07:00
Vance Ingalls bd27ea31ad docs(sdk): republish SDK tab pages (Mintlify incremental deploy skipped the new files)
The #1817 deploy added 15 pages but Mintlify only published changed files
incrementally; the 14 unmodified pages 404'd on production while
editing-affordances (touched in 9140ee51b) deployed fine. Trailing-newline
touch forces Mintlify to re-emit all SDK pages.
2026-06-30 15:57:56 -07:00
Vance Ingalls 26e9283f6b docs(sdk): comprehensive SDK reference + guides (#1817)
* docs(sdk): comprehensive SDK reference + guides

Adds a dedicated SDK tab to the Mintlify docs documenting the entire
@hyperframes/sdk surface, verified against source:

Reference (6 pages):
- openComposition + OpenCompositionOptions
- Composition (every typed method, query, selection, dispatch/batch/can,
  events, serialize, override mode, lifecycle)
- Edit Operations (all 33 EditOp variants for dispatch/can/batch)
- Types (every exported type + constants)
- Adapters (PersistAdapter/PreviewAdapter + memory/fs/headless/iframe factories)
- Utilities & Constants (history, persist-queue, document utils, origins, errors)

Guides (7) + Overview + Quickstart:
- querying-and-editing, timing-and-animation, undo-redo-and-patches,
  persistence, embedded-override-mode, canvas-integration, editing-affordances

The existing packages/sdk.mdx stays as the package card and now links the
new SDK tab. editing-affordances documents the @hyperframes/sdk/editing
subpath shipping in #1814 (flagged with a version Note).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(sdk): address PR review feedback

Correctness fixes from PR #1817 review (Miga + Rames):
- types.mdx: FindQuery.text is a substring match (String.includes), not exact
- persistence.mdx: import PersistAdapter/PersistVersionEntry/PersistErrorEvent
  from @hyperframes/sdk (no @hyperframes/sdk/adapters/types export exists)
- open-composition.mdx: createHeadlessAdapter is a PreviewAdapter, not a persist
  adapter; PersistAdapter is exported from @hyperframes/sdk (no /adapters subpath)
- types.mdx / adapters.mdx: note KeyframeSpec, ElementAtPointResult, DraftProps
  are structural shapes, not barrel exports (no import to copy)
- overview.mdx: drop leaked authoring meta-comment
- timing-and-animation.mdx: getElementTimings is keyed by scopedId
- embedded-override-mode.mdx: history is already off by default in embedded mode
- editing-affordances.mdx: /editing subpath is merged; soften the version note
- querying-and-editing.mdx: bare id only resolves top-level; use find() for
  sub-composition leaves
- canvas-integration.mdx + persistence.mdx: explain the comp closure forward-ref
  and the fs-adapter subpath (tree-shaking) asymmetry

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 14:45:54 -07:00