@hyperframes/studio 0.8.46 → 0.8.48
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.
- package/dist/assets/hyperframes-player-CtVX6jL_.js +464 -0
- package/dist/assets/{index-CbchRscN.js → index-B3-orIjW.js} +1 -1
- package/dist/assets/index-B9LfWNyM.css +1 -0
- package/dist/assets/index-C9gJKpqQ.js +441 -0
- package/dist/assets/{index-BywY2OM3.js → index-D_j-0PD3.js} +1 -1
- package/dist/index.d.ts +83 -26
- package/dist/index.html +2 -2
- package/dist/index.js +1118 -661
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/App.tsx +17 -26
- package/src/components/AskAgentModal.tsx +9 -7
- package/src/components/TimelineToolbar.tsx +26 -1
- package/src/components/editor/PropertyPanelFlat.tsx +8 -8
- package/src/components/editor/domEditing.ts +7 -1
- package/src/components/editor/domEditingAgentPrompt.test.ts +199 -0
- package/src/components/editor/domEditingAgentPrompt.ts +136 -34
- package/src/components/editor/manualEditingAvailability.test.ts +19 -0
- package/src/components/editor/manualEditingAvailability.ts +9 -5
- package/src/components/editor/propertyPanelAutomation.test.ts +82 -1
- package/src/components/editor/propertyPanelAutomation.ts +15 -0
- package/src/components/editor/propertyPanelFlatMediaSection.test.tsx +35 -0
- package/src/components/editor/propertyPanelFlatMediaSection.tsx +23 -9
- package/src/components/editor/useVolumeAutomation.test.tsx +81 -10
- package/src/components/editor/useVolumeAutomation.ts +23 -2
- package/src/components/panels/VariablesPanel.tsx +5 -8
- package/src/components/sidebar/CompositionsTab.rootBadge.test.tsx +59 -0
- package/src/components/sidebar/CompositionsTab.tsx +15 -0
- package/src/components/sidebar/LeftSidebar.masterComposition.test.tsx +47 -0
- package/src/components/sidebar/LeftSidebar.tsx +7 -0
- package/src/contexts/FileManagerContext.tsx +0 -3
- package/src/hooks/appHotkeysDispatch.ts +256 -0
- package/src/hooks/domEditDeleteMembers.test.ts +30 -0
- package/src/hooks/domEditDeleteMembers.ts +19 -0
- package/src/hooks/useActiveComposition.ts +69 -0
- package/src/hooks/useAppHotkeys.test.ts +23 -1
- package/src/hooks/useAppHotkeys.ts +6 -239
- package/src/hooks/useAutoOpenRootComposition.test.tsx +151 -0
- package/src/hooks/useAutoOpenRootComposition.ts +33 -0
- package/src/hooks/useDomEditCommits.ts +13 -15
- package/src/hooks/useDomEditSession.test.tsx +90 -1
- package/src/hooks/useDomEditSession.ts +31 -34
- package/src/hooks/useDomSelectionTypes.ts +7 -2
- package/src/hooks/useElementLifecycleOps.ts +0 -8
- package/src/hooks/useFileManager.projectOwnership.test.tsx +0 -1
- package/src/hooks/useFileManager.ts +0 -2
- package/src/hooks/useFileTree.test.tsx +214 -0
- package/src/hooks/useFileTree.ts +66 -24
- package/src/hooks/useGroupCommits.test.ts +98 -0
- package/src/hooks/useGroupCommits.ts +66 -9
- package/src/hooks/useResetSelectionOnProjectSwitch.test.tsx +234 -0
- package/src/hooks/useResetSelectionOnProjectSwitch.ts +34 -0
- package/src/hooks/useSdkSession.lifecycle.test.tsx +76 -0
- package/src/hooks/useSdkSession.ts +21 -3
- package/src/hooks/useTimelineAssetDropOps.test.tsx +72 -0
- package/src/hooks/useTimelineAssetDropOps.ts +20 -16
- package/src/hooks/useTimelineDeleteOps.test.tsx +119 -0
- package/src/hooks/useTimelineDeleteOps.ts +103 -9
- package/src/hooks/useTimelineEditing.ts +1 -0
- package/src/hooks/useTimelineGroupEditing.test.tsx +74 -0
- package/src/hooks/useTimelineGroupEditing.ts +19 -5
- package/src/index.ts +10 -0
- package/src/player/components/Timeline.test.ts +0 -4
- package/src/player/components/Timeline.tsx +0 -1
- package/src/player/components/TimelineAutomationLaneSlot.tsx +4 -2
- package/src/player/components/TimelineClipDiamonds.test.tsx +13 -1
- package/src/player/components/TimelineDiamondConnectors.test.ts +16 -0
- package/src/player/components/TimelineDiamondConnectors.tsx +17 -1
- package/src/player/components/TimelinePropertyLanes.test.tsx +1 -1
- package/src/player/components/automationLaneData.test.ts +11 -3
- package/src/player/components/automationLaneData.ts +5 -4
- package/src/player/components/automationLaneGeometry.ts +15 -0
- package/src/player/components/timelineDragDrop.test.tsx +21 -4
- package/src/player/components/timelineDragDrop.ts +9 -25
- package/src/player/components/timelineGapCommit.test.ts +96 -0
- package/src/player/components/timelineGapCommit.ts +56 -11
- package/src/player/components/timelineGaps.ts +2 -2
- package/src/player/components/timelineLayout.test.ts +0 -1
- package/src/player/components/timelineLayout.ts +1 -6
- package/src/player/components/timelineZones.test.ts +20 -1
- package/src/player/components/timelineZones.ts +10 -3
- package/src/player/components/useAutomationLaneGestures.ts +2 -10
- package/src/player/components/useTimelineTrackLayout.ts +7 -6
- package/src/player/hooks/usePlaybackKeyboard.test.ts +34 -0
- package/src/player/hooks/usePlaybackKeyboard.ts +13 -0
- package/src/player/hooks/useTimelinePlayer.ts +9 -4
- package/src/player/hooks/useTimelineSyncCallbacks.ts +7 -4
- package/src/player/lib/timelineIframeHelpers.test.ts +22 -0
- package/src/player/lib/timelineIframeHelpers.ts +1 -0
- package/src/player/store/playerStore.test.ts +42 -0
- package/src/player/store/playerStore.ts +25 -28
- package/src/player/store/readinessSlice.ts +42 -0
- package/src/utils/razorSplitTransaction.test.ts +10 -0
- package/src/utils/razorSplitTransaction.ts +5 -0
- package/src/utils/sdkCutover.gate.test.ts +5 -4
- package/src/utils/sdkCutover.test.ts +93 -0
- package/src/utils/sdkCutover.ts +46 -25
- package/src/utils/sdkCutoverEligibility.ts +21 -0
- package/src/utils/sdkCutoverPolicy.test.ts +11 -2
- package/src/utils/sdkCutoverPolicy.ts +5 -3
- package/src/utils/sdkEditTransaction.decline.test.ts +46 -0
- package/src/utils/sdkEditTransaction.ts +22 -1
- package/src/utils/sdkResolverShadow.ts +10 -1
- package/src/utils/studioHelpers.test.ts +18 -0
- package/src/utils/studioHelpers.ts +41 -5
- package/src/utils/studioUiPreferences.test.ts +14 -0
- package/src/utils/studioUiPreferences.ts +6 -0
- package/src/utils/studioUrlState.ts +15 -7
- package/src/utils/timelineInspector.ts +10 -0
- package/dist/assets/hyperframes-player-CsV2rywT.js +0 -464
- package/dist/assets/index-DCblmTX3.js +0 -441
- package/dist/assets/index-DnRfAiK2.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as P}from"./index-
|
|
1
|
+
import{g as P}from"./index-C9gJKpqQ.js";function j(c,d){for(var s=0;s<d.length;s++){const a=d[s];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in c)){const l=Object.getOwnPropertyDescriptor(a,i);l&&Object.defineProperty(c,i,l.get?l:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}))}var v={},w;function k(){if(w)return v;w=1,Object.defineProperty(v,"__esModule",{value:!0}),v.default=d;var c=window.OfflineAudioContext||window.webkitOfflineAudioContext;function d(e){var r=a(e);return r.start(0),[i,y,O(e.sampleRate),s].reduce(function(t,o){return o(t)},r.buffer.getChannelData(0))}function s(e){return e.sort(function(r,t){return t.count-r.count}).splice(0,5)[0].tempo}function a(e){var r=e.length,t=e.numberOfChannels,o=e.sampleRate,n=new c(t,r,o),u=n.createBufferSource();u.buffer=e;var f=n.createBiquadFilter();return f.type="lowpass",u.connect(f),f.connect(n.destination),u}function i(e){for(var r=[],t=.9,o=.3,n=15;r.length<n&&t>=o;)r=l(e,t),t-=.05;if(r.length<n)throw new Error("Could not find enough samples for a reliable detection.");return r}function l(e,r){for(var t=[],o=0,n=e.length;o<n;o+=1)e[o]>r&&(t.push(o),o+=1e4);return t}function y(e){var r=[];return e.forEach(function(t,o){for(var n=function(x){var g=e[o+x]-t,_=r.some(function(h){if(h.interval===g)return h.count+=1});_||r.push({interval:g,count:1})},u=0;u<10;u+=1)n(u)}),r}function O(e){return function(r){var t=[];return r.forEach(function(o){if(o.interval!==0){for(var n=60/(o.interval/e);n<90;)n*=2;for(;n>180;)n/=2;n=Math.round(n);var u=t.some(function(f){if(f.tempo===n)return f.count+=o.count});u||t.push({tempo:n,count:o.count})}}),t}}return v}var p,b;function q(){return b||(b=1,p=k().default),p}var m=q();const A=P(m),D=j({__proto__:null,default:A},[m]);export{D as i};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode, RefObject } from 'react';
|
|
4
|
-
import { RuntimeTimelineClipIdentity } from '@hyperframes/core';
|
|
4
|
+
import { RuntimeTimelineClipIdentity, HyperframePickerElementInfo } from '@hyperframes/core';
|
|
5
5
|
import { GsapAnimation, PropertyGroupName } from '@hyperframes/core/gsap-parser';
|
|
6
6
|
import * as zustand from 'zustand';
|
|
7
|
+
import { StoreApi } from 'zustand';
|
|
7
8
|
import { MusicBeatAnalysis } from '@hyperframes/core/beats';
|
|
8
9
|
import { GsapAnimation as GsapAnimation$1, ArcPathSegment } from '@hyperframes/parsers/gsap-parser';
|
|
9
10
|
|
|
@@ -250,6 +251,20 @@ interface ThumbnailSlice {
|
|
|
250
251
|
bumpThumbnailContentRevision: () => void;
|
|
251
252
|
}
|
|
252
253
|
|
|
254
|
+
/** Gates `timelineReady` on the composition's declared readiness inputs
|
|
255
|
+
* (media, for now) instead of just a known duration. The generation counter
|
|
256
|
+
* is module-scope, not store state: it guards an in-flight settlement, not
|
|
257
|
+
* something a component reads, so bumping it shouldn't trigger a render. */
|
|
258
|
+
|
|
259
|
+
interface PlaybackReadinessSlice {
|
|
260
|
+
timelineReady: boolean;
|
|
261
|
+
setTimelineReady: (ready: boolean) => void;
|
|
262
|
+
/** Sets timelineReady once doc's readiness inputs settle, or immediately
|
|
263
|
+
* if doc is null. A wait a later call supersedes never wins the race. */
|
|
264
|
+
requestTimelineReady: (doc: Document | null) => void;
|
|
265
|
+
}
|
|
266
|
+
declare function createPlaybackReadinessSlice(set: StoreApi<PlaybackReadinessSlice>["setState"]): PlaybackReadinessSlice;
|
|
267
|
+
|
|
253
268
|
type TimeListener = (time: number) => void;
|
|
254
269
|
declare const liveTime: {
|
|
255
270
|
notify: (time: number) => void;
|
|
@@ -382,11 +397,11 @@ type TimelineTool = "select" | "razor";
|
|
|
382
397
|
interface SelectElementOptions {
|
|
383
398
|
preserveSet?: boolean;
|
|
384
399
|
}
|
|
385
|
-
|
|
400
|
+
type PlayerStoreSlices = KeyframeSlice & AutomationSelectionSlice & ThumbnailSlice & EditingModeSlice & ReturnType<typeof createPlaybackReadinessSlice>;
|
|
401
|
+
interface PlayerState extends PlayerStoreSlices {
|
|
386
402
|
isPlaying: boolean;
|
|
387
403
|
currentTime: number;
|
|
388
404
|
duration: number;
|
|
389
|
-
timelineReady: boolean;
|
|
390
405
|
/** Increments exactly once when the Studio switches to a different project. */
|
|
391
406
|
timelineSessionEpoch: number;
|
|
392
407
|
/** Project owning the current timeline session; null outside a project-scoped reset. */
|
|
@@ -428,14 +443,14 @@ interface PlayerState extends KeyframeSlice, AutomationSelectionSlice, Thumbnail
|
|
|
428
443
|
/** Timeline magnet toggle — when false, clip drags/trims/drops never snap. */
|
|
429
444
|
timelineSnapEnabled: boolean;
|
|
430
445
|
setTimelineSnapEnabled: (enabled: boolean) => void;
|
|
446
|
+
/** Keeps the main track gapless on delete; distinct from the magnet above. */
|
|
447
|
+
rippleEditEnabled: boolean;
|
|
448
|
+
setRippleEditEnabled: (enabled: boolean) => void;
|
|
431
449
|
/** Transport + ruler readout: timecode ("time") or frame number ("frame"). */
|
|
432
450
|
timeDisplayMode: TimelineTimeDisplayMode;
|
|
433
451
|
setTimeDisplayMode: (mode: TimelineTimeDisplayMode) => void;
|
|
434
|
-
/**
|
|
435
|
-
*
|
|
436
|
-
* edit, so a subsequent duration change (which recomputes fit-pps) stops
|
|
437
|
-
* rescaling every clip. No-op once already pinned (mode is "manual").
|
|
438
|
-
*/
|
|
452
|
+
/** Pin the timeline zoom to its current scale before a duration change, so
|
|
453
|
+
* it stops rescaling every clip. No-op once already pinned. */
|
|
439
454
|
pinTimelineZoom: (currentPixelsPerSecond: number, fitPixelsPerSecond: number) => void;
|
|
440
455
|
/** The timeline's live pixels-per-second + fit basis, published by <Timeline>. */
|
|
441
456
|
timelinePps: number;
|
|
@@ -452,7 +467,6 @@ interface PlayerState extends KeyframeSlice, AutomationSelectionSlice, Thumbnail
|
|
|
452
467
|
setAudioMuted: (muted: boolean) => void;
|
|
453
468
|
setAudioVolume: (volume: number) => void;
|
|
454
469
|
setLoopEnabled: (enabled: boolean) => void;
|
|
455
|
-
setTimelineReady: (ready: boolean) => void;
|
|
456
470
|
setBeatDragging: (dragging: boolean) => void;
|
|
457
471
|
setElements: (elements: TimelineElement[]) => void;
|
|
458
472
|
setSelectedElementId: (id: string | null, options?: SelectElementOptions) => void;
|
|
@@ -468,25 +482,15 @@ interface PlayerState extends KeyframeSlice, AutomationSelectionSlice, Thumbnail
|
|
|
468
482
|
beginTimelineSession: (projectId: string) => void;
|
|
469
483
|
/** Clears project data without creating a new hard-project session. */
|
|
470
484
|
reset: () => void;
|
|
471
|
-
/**
|
|
472
|
-
*
|
|
473
|
-
* useTimelinePlayer subscribes and calls adapter.seek() + liveTime.notify().
|
|
474
|
-
*/
|
|
485
|
+
/** Request a seek from outside the player loop (e.g. Layers panel);
|
|
486
|
+
* useTimelinePlayer subscribes and calls adapter.seek() + liveTime.notify(). */
|
|
475
487
|
requestedSeekTime: number | null;
|
|
476
488
|
requestSeek: (time: number) => void;
|
|
477
489
|
clearSeekRequest: () => void;
|
|
478
|
-
/**
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
* silent while the transport is paused — so hovering one has to start
|
|
483
|
-
* playback, and leaving has to put the playhead back where it was. Hovering is
|
|
484
|
-
* not an edit and must not cost the author their place.
|
|
485
|
-
*
|
|
486
|
-
* A nonce rather than a bare boolean: two hovers in a row both want play, and
|
|
487
|
-
* without it the second request is indistinguishable from the first having
|
|
488
|
-
* already been served.
|
|
489
|
-
*/
|
|
490
|
+
/** Request the transport start or stop from outside the player loop: the FX
|
|
491
|
+
* rack starts playback to audition a preset (silent while paused) and
|
|
492
|
+
* restores the playhead on leave, without costing the author their place.
|
|
493
|
+
* A nonce, not a bare boolean, so two hovers in a row both register. */
|
|
490
494
|
playbackRequest: {
|
|
491
495
|
playing: boolean;
|
|
492
496
|
returnTo: number | null;
|
|
@@ -661,6 +665,45 @@ interface DomEditSelection extends PatchTarget {
|
|
|
661
665
|
gsapAnimations?: GsapAnimation$1[];
|
|
662
666
|
}
|
|
663
667
|
|
|
668
|
+
/**
|
|
669
|
+
* Agent prompt builder for HyperFrames element edit requests.
|
|
670
|
+
*/
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* The subset of an element selection shared by the Studio DOM editor (`DomEditSelection`) and the
|
|
674
|
+
* runtime picker (`HyperframePickerElementInfo`); a field absent from a caller's type is simply omitted.
|
|
675
|
+
*/
|
|
676
|
+
interface AgentPromptElementInfo {
|
|
677
|
+
id: string | null;
|
|
678
|
+
selector?: string | null;
|
|
679
|
+
/** Disambiguates duplicate selectors in `DomEditSelection`. The picker
|
|
680
|
+
* payload has no such concept (one picked node, not a candidate list), so
|
|
681
|
+
* a picker-built prompt always prints index 0 — expected, not a gap. */
|
|
682
|
+
selectorIndex?: number;
|
|
683
|
+
tagName: string;
|
|
684
|
+
label?: string;
|
|
685
|
+
boundingBox: {
|
|
686
|
+
x: number;
|
|
687
|
+
y: number;
|
|
688
|
+
width: number;
|
|
689
|
+
height: number;
|
|
690
|
+
};
|
|
691
|
+
textContent: string | null;
|
|
692
|
+
src?: string | null;
|
|
693
|
+
textFields?: DomEditTextField[];
|
|
694
|
+
inlineStyles?: Record<string, string>;
|
|
695
|
+
computedStyles?: Record<string, string>;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Same convention as `buildElementAgentPrompt`, for a host app embedding only the player: built from
|
|
699
|
+
* the runtime picker's own payload, not `DomEditSelection`. Null selection yields a bare prompt, no guardrails.
|
|
700
|
+
*/
|
|
701
|
+
declare function buildPickerAgentPrompt({ selection, userInstruction, }: {
|
|
702
|
+
selection: HyperframePickerElementInfo | null;
|
|
703
|
+
userInstruction?: string;
|
|
704
|
+
}): string;
|
|
705
|
+
declare function buildPickerAgentContextPreview(selection: HyperframePickerElementInfo | null): string;
|
|
706
|
+
|
|
664
707
|
type BlockedTimelineEditIntent = "move" | "resize-start" | "resize-end";
|
|
665
708
|
|
|
666
709
|
type TimelineMoveOperation = "timing" | "lane-reorder" | "track-insert";
|
|
@@ -1202,6 +1245,20 @@ declare const FileTree: react.NamedExoticComponent<FileTreeProps>;
|
|
|
1202
1245
|
|
|
1203
1246
|
declare function StudioApp(): react_jsx_runtime.JSX.Element;
|
|
1204
1247
|
|
|
1248
|
+
interface AgentModalAnchorPoint {
|
|
1249
|
+
x: number;
|
|
1250
|
+
y: number;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
interface AskAgentModalProps {
|
|
1254
|
+
selectionLabel: string;
|
|
1255
|
+
contextPreview?: string;
|
|
1256
|
+
anchorPoint?: AgentModalAnchorPoint | null;
|
|
1257
|
+
onSubmit: (instruction: string) => void;
|
|
1258
|
+
onClose: () => void;
|
|
1259
|
+
}
|
|
1260
|
+
declare function AskAgentModal({ selectionLabel, contextPreview, anchorPoint, onSubmit, onClose, }: AskAgentModalProps): react_jsx_runtime.JSX.Element;
|
|
1261
|
+
|
|
1205
1262
|
interface PickedElement {
|
|
1206
1263
|
id: string | null;
|
|
1207
1264
|
tagName: string;
|
|
@@ -1277,4 +1334,4 @@ declare function findElementBlock(html: string, elementId: string): {
|
|
|
1277
1334
|
isSelfClosing: boolean;
|
|
1278
1335
|
} | null;
|
|
1279
1336
|
|
|
1280
|
-
export { CompositionBreadcrumb, type CompositionLevel, CompositionThumbnail, EditorShell, FileTree, NLEPreview, type PatchOperation, type PickedElement, Player, PlayerControls, PropertyPanel, SourceEditor, StudioApp, Timeline, type TimelineElement, VideoThumbnail, applyPatch, findElementBlock, formatTime, liveTime, mergeStyleIntoTag, parseStyleString, resolveIframe, resolveSourceFile, useElementPicker, usePlayerStore, useTimelinePlayer };
|
|
1337
|
+
export { type AgentModalAnchorPoint, type AgentPromptElementInfo, AskAgentModal, type AskAgentModalProps, CompositionBreadcrumb, type CompositionLevel, CompositionThumbnail, EditorShell, FileTree, NLEPreview, type PatchOperation, type PickedElement, Player, PlayerControls, PropertyPanel, SourceEditor, StudioApp, Timeline, type TimelineElement, VideoThumbnail, applyPatch, buildPickerAgentContextPreview, buildPickerAgentPrompt, findElementBlock, formatTime, liveTime, mergeStyleIntoTag, parseStyleString, resolveIframe, resolveSourceFile, useElementPicker, usePlayerStore, useTimelinePlayer };
|
package/dist/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
7
7
|
<title>HyperFrames Studio</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-C9gJKpqQ.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-B9LfWNyM.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div data-hf-id="hf-aph5" id="root"></div>
|