Files
hyperframes/packages/core/package-subpaths.json
T
Vance IngallsandClaude Sonnet 5.5 0559be0b13 feat(studio): link a video and its audio with data-link (6/8) (#4818)
* feat(core): add data-link media link helpers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(lint): warn on out-of-sync and orphaned linked clips

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(studio): select, drag and trim linked clips together

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(studio): detach, merge, link and unlink source transforms

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(studio): link-aware split, delete, alt-edit unlink and link edit actions

Split and delete fan out to link partners. Alt drag/trim edits one member
and unlinks it. onLinkEdit runs unlink, link, detach and merge as one undo
step each. Single-clip timing edits of a linked clip skip the SDK path so
its linked default cannot move the partner behind the store.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(studio-server): give split right halves of a linked pair their own link

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(studio): clip menu detach, unlink, link, merge back and delete-one items

Items live in clipMenuLinkItems.tsx with a one-line hook in ClipContextMenu;
the same resolver drives the Cmd+L, Opt+Shift+D and Opt+Delete shortcuts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(sdk): setTiming applies to data-link partners by default

{ linked: false } edits one member and unlinks it, matching Studio's Alt-edit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(skills): document data-link linked clips in hyperframes-core

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore(studio): keep comment share at or below base in link plumbing

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(studio): audio pill link follows data-link, not a shared file name

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(studio): alt-click selects one linked member even inside the pair selection

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(lint): drop the rule-list comment for the linked clip rules

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(sdk,lint): keep a link group inside its own composition

Link ids are minted per file, so lk-1 is normal in the root and in a child
composition. The SDK's linked-timing query descended into nested hosts and
addressed every match with the initiating scope, so moving a root clip moved
the child's pair too; lint grouped them into one drifting group. Both now
group only members of the same composition scope.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(studio): match linked media by full asset path, scope links, keep hidden sound silent

Merge and Link compared only a lowercased basename, so assets/one/talk.mp4
and assets/two/talk.mp4 enabled a destructive Merge. Clips now compare the
src resolved against each clip's own source file, and Merge re-checks the
two srcs in the source before it runs. Link membership in the timeline
(linked members, gesture expansion, unlink orphans) is scoped to a source
file. Detach and the keep-sound cutout carry a hidden video's data-hidden
to its audio, and Merge refuses when only one member is hidden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(studio): move the timeline move-edits handler into its adapter

App.tsx sat at 600 lines on this layer and 602 once merged with main.
useTimelineMoveEditsHandler now lives beside persistTimelineMoveEditsAtomically,
same callback and dependencies, bringing App.tsx to 592.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(sdk,studio,lint): keep link groups inside inline compositions

A link group now stays inside the nearest data-composition-id or
data-composition-file ancestor. The SDK used to recognise only file hosts,
and Studio compared only sourceFile, so an inline child composition that
reused a link id was edited together with the root group. core/media-link
linkScopeOf is the shared rule for the SDK and Studio. Lint cannot import
core, so it uses the same two attributes directly. Studio rows record their
compositionScope, and link and merge refuse pairs that cross it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(sdk): refuse a link edit whose partner address names another clip

A partner addressed in the caller's scope can resolve to a different element
when an inline composition reuses a root clip's data-hf-id. setTiming now
checks that each partner's address resolves back to that partner and throws
before mutating when it does not, instead of editing the root clip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(studio): a remote media url keeps its query when matching an asset

Two different videos at one remote path with different queries were treated as
the same file, so Merge could delete the audio and use the wrong video's
sound. Project-local srcs still drop query and hash.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(studio): keep a remote url's query exactly as written when matching assets

Decoding the whole url folded %26 into & so two different media urls matched.
Decode only the path; the query is compared as authored.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(studio): compare a remote url as serialized, decode only local paths

A remote pathname with an encoded reserved character (%3F) matched the same
path with a literal ?, though they can return different media. Remote urls
keep origin, path and query exactly; local srcs are still decoded and
stripped of query and hash.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 05:23:25 +00:00

487 lines
17 KiB
JSON

{
"package": "@hyperframes/core",
"localNodeRuntime": true,
"subpaths": {
".": {
"source": "./src/index.ts",
"runtime": "./dist/index.js",
"types": "./dist/index.d.ts",
"environments": ["bun", "node"]
},
"./package.json": {
"source": "./package.json",
"runtime": "./package.json",
"types": null,
"environments": ["browser", "bun", "node"]
},
"./canary": {
"source": "./src/canary.ts",
"runtime": "./dist/canary.js",
"types": "./dist/canary.d.ts",
"environments": ["browser", "bun", "node"]
},
"./canary-registry": {
"source": "./src/canaryRegistry.ts",
"runtime": "./dist/canaryRegistry.js",
"types": "./dist/canaryRegistry.d.ts",
"environments": ["browser", "bun", "node"]
},
"./beats": {
"source": "./src/beats/index.ts",
"runtime": "./dist/beats/index.js",
"types": "./dist/beats/index.d.ts",
"environments": ["browser", "bun", "node"]
},
"./html-attr-safety": {
"source": "./src/utils/htmlAttrSafety.ts",
"runtime": "./dist/utils/htmlAttrSafety.js",
"types": "./dist/utils/htmlAttrSafety.d.ts",
"environments": ["browser", "bun", "node"]
},
"./safe-path": {
"source": "./src/safePath.ts",
"runtime": "./dist/safePath.js",
"types": "./dist/safePath.d.ts",
"environments": ["bun", "node"]
},
"./atomic-file": {
"source": "./src/atomicFile.ts",
"runtime": "./dist/atomicFile.js",
"types": "./dist/atomicFile.d.ts",
"environments": ["bun", "node"]
},
"./asset-paths": {
"source": "./src/compiler/rewriteSubCompPaths.ts",
"runtime": "./dist/compiler/rewriteSubCompPaths.js",
"types": "./dist/compiler/rewriteSubCompPaths.d.ts",
"environments": ["bun", "node"]
},
"./runtime-script": {
"source": "./src/generated/runtime-inline.ts",
"runtime": "./dist/generated/runtime-inline.js",
"types": "./dist/generated/runtime-inline.d.ts",
"environments": ["browser", "bun", "node"]
},
"./rich-text-sanitize": {
"source": "./src/utils/richTextSanitize.ts",
"runtime": "./dist/utils/richTextSanitize.js",
"types": "./dist/utils/richTextSanitize.d.ts",
"environments": ["browser", "bun", "node"]
},
"./composition-contract": {
"source": "./src/compositionContract.ts",
"runtime": "./dist/compositionContract.js",
"types": "./dist/compositionContract.d.ts",
"environments": ["browser", "bun", "node"]
},
"./studio-preview-mark": {
"source": "./src/studioPreviewMark.ts",
"runtime": "./dist/studioPreviewMark.js",
"types": "./dist/studioPreviewMark.d.ts",
"environments": ["browser", "bun", "node"]
},
"./media-timing": {
"source": "./src/mediaTiming.ts",
"runtime": "./dist/mediaTiming.js",
"types": "./dist/mediaTiming.d.ts",
"environments": ["browser", "bun", "node"]
},
"./composition-readiness": {
"source": "./src/compositionReadiness.ts",
"runtime": "./dist/compositionReadiness.js",
"types": "./dist/compositionReadiness.d.ts",
"environments": ["browser", "bun", "node"]
},
"./editing": {
"source": "./src/editing/affordances.ts",
"runtime": "./dist/editing/affordances.js",
"types": "./dist/editing/affordances.d.ts",
"environments": ["browser", "bun", "node"]
},
"./editing/draft-markers": {
"source": "./src/editing/draftMarkers.ts",
"runtime": "./dist/editing/draftMarkers.js",
"types": "./dist/editing/draftMarkers.d.ts",
"environments": ["browser", "bun", "node"]
},
"./variables": {
"source": "./src/variables.ts",
"runtime": "./dist/variables.js",
"types": "./dist/variables.d.ts",
"environments": ["browser", "bun", "node"]
},
"./slideshow": {
"source": "./src/slideshow/index.ts",
"runtime": "./dist/slideshow/index.js",
"types": "./dist/slideshow/index.d.ts",
"environments": ["browser", "bun", "node"]
},
"./generators": {
"source": "./src/generators/hyperframes.ts",
"runtime": "./dist/generators/hyperframes.js",
"types": "./dist/generators/hyperframes.d.ts",
"environments": ["browser", "bun", "node"]
},
"./lint": {
"source": "./src/lint/index.ts",
"runtime": "./dist/lint/index.js",
"types": "./dist/lint/index.d.ts",
"environments": ["bun", "node"]
},
"./compiler": {
"source": "./src/compiler/index.ts",
"runtime": "./dist/compiler/index.js",
"types": "./dist/compiler/index.d.ts",
"environments": ["bun", "node"]
},
"./projects": {
"source": "./src/projects.ts",
"runtime": "./dist/projects.js",
"types": "./dist/projects.d.ts",
"environments": ["bun", "node"]
},
"./audio-fx": {
"source": "./src/audioFx.ts",
"runtime": "./dist/audioFx.js",
"types": "./dist/audioFx.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-fx-copy": {
"source": "./src/audioFxCopy.ts",
"runtime": "./dist/audioFxCopy.js",
"types": "./dist/audioFxCopy.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-fx-profiles": {
"source": "./src/audioFxProfiles.ts",
"runtime": "./dist/audioFxProfiles.js",
"types": "./dist/audioFxProfiles.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-fx-jobs": {
"source": "./src/audioFxJobs.ts",
"runtime": "./dist/audioFxJobs.js",
"types": "./dist/audioFxJobs.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-fx-eq": {
"source": "./src/audioFxEq.ts",
"runtime": "./dist/audioFxEq.js",
"types": "./dist/audioFxEq.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-leveller": {
"source": "./src/audioLeveller.ts",
"runtime": "./dist/audioLeveller.js",
"types": "./dist/audioLeveller.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-fx-presets": {
"source": "./src/audioFxPresets.ts",
"runtime": "./dist/audioFxPresets.js",
"types": "./dist/audioFxPresets.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-fx-tail": {
"source": "./src/audio/audioFxTail.ts",
"runtime": "./dist/audio/audioFxTail.js",
"types": "./dist/audio/audioFxTail.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-fx-runtime": {
"source": "./src/generated/audio-fx-runtime-inline.ts",
"runtime": "./dist/generated/audio-fx-runtime-inline.js",
"types": "./dist/generated/audio-fx-runtime-inline.d.ts",
"environments": ["bun", "node"]
},
"./audio-carve": {
"source": "./src/audioCarve.ts",
"runtime": "./dist/audioCarve.js",
"types": "./dist/audioCarve.d.ts",
"environments": ["browser", "bun", "node"]
},
"./media-link": {
"source": "./src/mediaLink.ts",
"runtime": "./dist/mediaLink.js",
"types": "./dist/mediaLink.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-groups": {
"source": "./src/audioGroups.ts",
"runtime": "./dist/audioGroups.js",
"types": "./dist/audioGroups.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-automation": {
"source": "./src/audioAutomation.ts",
"runtime": "./dist/audioAutomation.js",
"types": "./dist/audioAutomation.d.ts",
"environments": ["browser", "bun", "node"]
},
"./clip-facts": {
"source": "./src/clipFacts.ts",
"runtime": "./dist/clipFacts.js",
"types": "./dist/clipFacts.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audible-video": {
"source": "./src/audibleVideo.ts",
"runtime": "./dist/audibleVideo.js",
"types": "./dist/audibleVideo.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-gain": {
"source": "./src/audioGain.ts",
"runtime": "./dist/audioGain.js",
"types": "./dist/audioGain.d.ts",
"environments": ["browser", "bun", "node"]
},
"./audio-fade": {
"source": "./src/audioFade.ts",
"runtime": "./dist/audioFade.js",
"types": "./dist/audioFade.d.ts",
"environments": ["browser", "bun", "node"]
},
"./speed-ramp": {
"source": "./src/speedRamp.ts",
"runtime": "./dist/speedRamp.js",
"types": "./dist/speedRamp.d.ts",
"environments": ["browser", "bun", "node"]
},
"./color-grading": {
"source": "./src/colorGrading.ts",
"runtime": "./dist/colorGrading.js",
"types": "./dist/colorGrading.d.ts",
"environments": ["browser", "bun", "node"]
},
"./color-luts": {
"source": "./src/colorLuts.ts",
"runtime": "./dist/colorLuts.js",
"types": "./dist/colorLuts.d.ts",
"environments": ["browser", "bun", "node"]
},
"./media-grade-analyzer": {
"source": "./src/mediaGradeAnalyzer.ts",
"runtime": "./dist/mediaGradeAnalyzer.js",
"types": "./dist/mediaGradeAnalyzer.d.ts",
"environments": ["bun", "node"]
},
"./storyboard": {
"source": "./src/storyboard/index.ts",
"runtime": "./dist/storyboard/index.js",
"types": "./dist/storyboard/index.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime": {
"source": "./dist/hyperframe.runtime.iife.js",
"runtime": "./dist/hyperframe.runtime.iife.js",
"types": null,
"environments": ["browser"]
},
"./runtime/clipTree": {
"source": "./src/runtime/clipTree.ts",
"runtime": "./dist/runtime/clipTree.js",
"types": "./dist/runtime/clipTree.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime/custom-ease": {
"source": "./src/runtime/customEase.ts",
"runtime": "./dist/runtime/customEase.js",
"types": "./dist/runtime/customEase.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime/start-expression": {
"source": "./src/runtime/startExpression.ts",
"runtime": "./dist/runtime/startExpression.js",
"types": "./dist/runtime/startExpression.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime/start-resolver": {
"source": "./src/runtime/startResolver.ts",
"runtime": "./dist/runtime/startResolver.js",
"types": "./dist/runtime/startResolver.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime/protocol": {
"source": "./src/runtime/protocol.ts",
"runtime": "./dist/runtime/protocol.js",
"types": "./dist/runtime/protocol.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime/clip-window": {
"source": "./src/runtime/clipWindow.ts",
"runtime": "./dist/runtime/clipWindow.js",
"types": "./dist/runtime/clipWindow.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime/stacking-context": {
"source": "./src/runtime/stackingContext.ts",
"runtime": "./dist/runtime/stackingContext.js",
"types": "./dist/runtime/stackingContext.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime/web-audio-route": {
"source": "./src/runtime/webAudioRoute.ts",
"runtime": "./dist/runtime/webAudioRoute.js",
"types": "./dist/runtime/webAudioRoute.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime/levelTap": {
"source": "./src/runtime/levelTap.ts",
"runtime": "./dist/runtime/levelTap.js",
"types": "./dist/runtime/levelTap.d.ts",
"environments": ["browser", "bun", "node"]
},
"./compiler/html-document": {
"source": "./src/compiler/htmlDocument.ts",
"runtime": "./dist/compiler/htmlDocument.js",
"types": "./dist/compiler/htmlDocument.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime/position-edits": {
"source": "./src/runtime/positionEdits.ts",
"runtime": "./dist/runtime/positionEdits.js",
"types": "./dist/runtime/positionEdits.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime/position-edits-render": {
"source": "./src/generated/position-edits-render-inline.ts",
"runtime": "./dist/generated/position-edits-render-inline.js",
"types": "./dist/generated/position-edits-render-inline.d.ts",
"environments": ["browser", "bun", "node"]
},
"./runtime/lottie-readiness": {
"source": "./src/lottieReadiness.ts",
"runtime": "./dist/lottieReadiness.js",
"types": "./dist/lottieReadiness.d.ts",
"environments": ["browser", "bun", "node"]
},
"./studio-api": {
"source": "./src/studio-api/index.ts",
"runtime": "./dist/studio-api/index.js",
"types": "./dist/studio-api/index.d.ts",
"environments": ["bun", "node"]
},
"./studio-api/screenshot-clip": {
"source": "./src/studio-api/helpers/screenshotClip.ts",
"runtime": "./dist/studio-api/helpers/screenshotClip.js",
"types": "./dist/studio-api/helpers/screenshotClip.d.ts",
"environments": ["bun", "node"]
},
"./studio-api/manual-edits-render-script": {
"source": "./src/studio-api/helpers/manualEditsRenderScript.ts",
"runtime": "./dist/studio-api/helpers/manualEditsRenderScript.js",
"types": "./dist/studio-api/helpers/manualEditsRenderScript.d.ts",
"environments": ["bun", "node"]
},
"./studio-api/studio-motion-render-script": {
"source": "./src/studio-api/helpers/studioMotionRenderScript.ts",
"runtime": "./dist/studio-api/helpers/studioMotionRenderScript.js",
"types": "./dist/studio-api/helpers/studioMotionRenderScript.d.ts",
"environments": ["bun", "node"]
},
"./studio-api/draft-markers": {
"source": "./src/studio-api/helpers/draftMarkers.ts",
"runtime": "./dist/studio-api/helpers/draftMarkers.js",
"types": "./dist/studio-api/helpers/draftMarkers.d.ts",
"environments": ["browser", "bun", "node"]
},
"./studio-api/finite-mutation": {
"source": "./src/studio-api/helpers/finiteMutation.ts",
"runtime": "./dist/studio-api/helpers/finiteMutation.js",
"types": "./dist/studio-api/helpers/finiteMutation.d.ts",
"environments": ["bun", "node"]
},
"./text": {
"source": "./src/text/index.ts",
"runtime": "./dist/text/index.js",
"types": "./dist/text/index.d.ts",
"environments": ["browser", "bun", "node"]
},
"./registry": {
"source": "./src/registry/index.ts",
"runtime": "./dist/registry/index.js",
"types": "./dist/registry/index.d.ts",
"environments": ["browser", "bun", "node"]
},
"./media-volume-envelope": {
"source": "./src/runtime/mediaVolumeEnvelope.ts",
"runtime": "./dist/runtime/mediaVolumeEnvelope.js",
"types": "./dist/runtime/mediaVolumeEnvelope.d.ts",
"environments": ["browser", "bun", "node"]
},
"./hf-ids": {
"source": "./src/parsers/hfIds.ts",
"runtime": "./dist/parsers/hfIds.js",
"types": "./dist/parsers/hfIds.d.ts",
"environments": ["browser", "bun", "node"]
},
"./gsap-parser": {
"source": "./src/parsers/gsapParserExports.ts",
"runtime": "./dist/parsers/gsapParserExports.js",
"types": "./dist/parsers/gsapParserExports.d.ts",
"environments": ["browser", "bun", "node"]
},
"./gsap-parser-acorn": {
"source": "./src/parsers/gsapParserAcorn.ts",
"runtime": "./dist/parsers/gsapParserAcorn.js",
"types": "./dist/parsers/gsapParserAcorn.d.ts",
"environments": ["browser", "bun", "node"]
},
"./gsap-writer-acorn": {
"source": "./src/parsers/gsapWriterAcorn.ts",
"runtime": "./dist/parsers/gsapWriterAcorn.js",
"types": "./dist/parsers/gsapWriterAcorn.d.ts",
"environments": ["browser", "bun", "node"]
},
"./gsap-constants": {
"source": "./src/parsers/gsapConstants.ts",
"runtime": "./dist/parsers/gsapConstants.js",
"types": "./dist/parsers/gsapConstants.d.ts",
"environments": ["browser", "bun", "node"]
},
"./spring-ease": {
"source": "./src/parsers/springEase.ts",
"runtime": "./dist/parsers/springEase.js",
"types": "./dist/parsers/springEase.d.ts",
"environments": ["browser", "bun", "node"]
},
"./wiggle-ease": {
"source": "./src/runtime/wiggleEase.ts",
"runtime": "./dist/runtime/wiggleEase.js",
"types": "./dist/runtime/wiggleEase.d.ts",
"environments": ["browser", "bun", "node"]
},
"./fonts/aliases": {
"source": "./src/fonts/aliases.ts",
"runtime": "./dist/fonts/aliases.js",
"types": "./dist/fonts/aliases.d.ts",
"environments": ["browser", "bun", "node"]
},
"./fonts/system-locator": {
"source": "./src/fonts/systemFontLocator.ts",
"runtime": "./dist/fonts/systemFontLocator.js",
"types": "./dist/fonts/systemFontLocator.d.ts",
"environments": ["bun", "node"]
},
"./figma": {
"source": "./src/figma/index.ts",
"runtime": "./dist/figma/index.js",
"types": "./dist/figma/index.d.ts",
"environments": ["bun", "node"]
},
"./schemas/registry.json": {
"source": "./schemas/registry.json",
"runtime": "./schemas/registry.json",
"types": null,
"environments": ["browser", "bun", "node"]
},
"./schemas/registry-item.json": {
"source": "./schemas/registry-item.json",
"runtime": "./schemas/registry-item.json",
"types": null,
"environments": ["browser", "bun", "node"]
}
}
}