hyperframes 0.8.5 → 0.8.7
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/cli.js +759 -298
- package/dist/hyperframe-runtime.js +121 -29
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +121 -29
- package/dist/hyperframes-player.global.js +1 -1
- package/dist/studio/assets/{hyperframes-player-DcM3fVcp.js → hyperframes-player-bDcU464i.js} +1 -1
- package/dist/studio/assets/index-Ba9zbpT9.css +1 -0
- package/dist/studio/assets/index-CUXnyoIa.js +428 -0
- package/dist/studio/assets/{index-DgJrvYGf.js → index-FkAs3zRu.js} +1 -1
- package/dist/studio/assets/{index-Del6XWZj.js → index-MSOSP1-J.js} +1 -1
- package/dist/studio/index.d.ts +98 -17
- package/dist/studio/index.html +2 -2
- package/dist/studio/index.js +10337 -7200
- package/dist/studio/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/studio/assets/index-Cx_UrhoW.js +0 -428
- package/dist/studio/assets/index-DcF4s1PG.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as P}from"./index-
|
|
1
|
+
import{g as P}from"./index-CUXnyoIa.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/studio/index.d.ts
CHANGED
|
@@ -31,6 +31,10 @@ interface PlayerControlsProps {
|
|
|
31
31
|
disabled?: boolean;
|
|
32
32
|
isFullscreen?: boolean;
|
|
33
33
|
onToggleFullscreen?: () => void;
|
|
34
|
+
/** Needed to read the soloed clips' labels out of the preview document. */
|
|
35
|
+
previewIframeRef?: {
|
|
36
|
+
current: HTMLIFrameElement | null;
|
|
37
|
+
};
|
|
34
38
|
}
|
|
35
39
|
declare const PlayerControls: react.NamedExoticComponent<PlayerControlsProps>;
|
|
36
40
|
|
|
@@ -113,6 +117,12 @@ interface KeyframeSlice {
|
|
|
113
117
|
setClipExpanded: (id: string, expanded: boolean) => void;
|
|
114
118
|
/** Union-expand clips (keyframed clips are expanded by default on load). */
|
|
115
119
|
expandClips: (ids: readonly string[]) => void;
|
|
120
|
+
/** Groups whose member rows the caret has shown (structural, not lanes). */
|
|
121
|
+
expandedGroupIds: Set<string>;
|
|
122
|
+
toggleGroupExpanded: (id: string) => void;
|
|
123
|
+
/** Rows (clip id or group id) whose automation-lane rows the `∿` button opened. */
|
|
124
|
+
expandedLaneOwnerIds: Set<string>;
|
|
125
|
+
toggleLaneOwnerExpanded: (id: string) => void;
|
|
116
126
|
/**
|
|
117
127
|
* Project/session/element-scoped request. Its nonce is monotonic across store
|
|
118
128
|
* resets so a stale consumer can never collide with a later request.
|
|
@@ -177,6 +187,56 @@ interface ThumbnailSlice {
|
|
|
177
187
|
setThumbnailMode: (mode: ThumbnailMode) => void;
|
|
178
188
|
}
|
|
179
189
|
|
|
190
|
+
/**
|
|
191
|
+
* "Hear only this" — session-only monitoring override, never persisted.
|
|
192
|
+
*
|
|
193
|
+
* Holds clip ids and group ids (never track numbers, per the design doc: solo
|
|
194
|
+
* is a per-element/per-group concept, not a row-position one). Exclusive by
|
|
195
|
+
* default (a plain toggle replaces the set); ⌘/Ctrl-click adds/removes one
|
|
196
|
+
* member without disturbing the rest. Never written to any attribute or
|
|
197
|
+
* document — the export-safety guarantee this slice exists to hold.
|
|
198
|
+
*/
|
|
199
|
+
|
|
200
|
+
interface AudioSoloSlice {
|
|
201
|
+
soloed: ReadonlySet<string>;
|
|
202
|
+
toggleSolo: (id: string, options?: {
|
|
203
|
+
add?: boolean;
|
|
204
|
+
}) => void;
|
|
205
|
+
clearSolo: () => void;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* The two editing-mode toggles the timeline toolbar owns.
|
|
210
|
+
*
|
|
211
|
+
* A store slice rather than toolbar-local state because both are read far from
|
|
212
|
+
* where they are set: the motion-path arm is consumed by the canvas click
|
|
213
|
+
* handler and published by MotionPathOverlay, and the auto-keyframe flag
|
|
214
|
+
* decides what a drag/resize/rotate does inside the edit commit path.
|
|
215
|
+
*
|
|
216
|
+
* `motionPathArmed` is also cleared by playerStore on selection change — arming
|
|
217
|
+
* survives neither a new element nor a project switch, so those resets stay
|
|
218
|
+
* with the state they clear alongside.
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
interface EditingModeSlice {
|
|
222
|
+
/** Motion-path "set destination" mode. Armed from the preview toolbar
|
|
223
|
+
* (replaces the old double-click-on-canvas UX); while armed, one canvas
|
|
224
|
+
* click places the new path's destination. */
|
|
225
|
+
motionPathArmed: boolean;
|
|
226
|
+
setMotionPathArmed: (armed: boolean) => void;
|
|
227
|
+
/** Published by MotionPathOverlay so the toolbar shows the button only when
|
|
228
|
+
* the selected element can actually take a path. */
|
|
229
|
+
motionPathCreateAvailable: boolean;
|
|
230
|
+
setMotionPathCreateAvailable: (available: boolean) => void;
|
|
231
|
+
/** Global toggle for the "Add keyframe" diamond in the timeline toolbar
|
|
232
|
+
* (#1808). When false, a manual drag/resize/rotate edit on an element that
|
|
233
|
+
* already has a live tween shifts every keyframe by the edit's delta
|
|
234
|
+
* (preserving the animation's shape) instead of inserting/updating a
|
|
235
|
+
* keyframe at the playhead. */
|
|
236
|
+
autoKeyframeEnabled: boolean;
|
|
237
|
+
setAutoKeyframeEnabled: (enabled: boolean) => void;
|
|
238
|
+
}
|
|
239
|
+
|
|
180
240
|
type TimeListener = (time: number) => void;
|
|
181
241
|
declare const liveTime: {
|
|
182
242
|
notify: (time: number) => void;
|
|
@@ -250,6 +310,16 @@ interface TimelineElement {
|
|
|
250
310
|
hidden?: boolean;
|
|
251
311
|
/** Value of data-timeline-role attribute — used to identify music vs. voiceover. */
|
|
252
312
|
timelineRole?: string;
|
|
313
|
+
/** Verbatim `data-audio-group` — the id of the `<hf-audio-group>` this clip belongs to, when any. */
|
|
314
|
+
audioGroup?: string;
|
|
315
|
+
/** The owning group's `data-label` (falls back to its id) — resolved once per parse. */
|
|
316
|
+
audioGroupLabel?: string;
|
|
317
|
+
/** The owning group's `data-volume` (defaults to 1) — resolved once per parse. */
|
|
318
|
+
audioGroupVolume?: number;
|
|
319
|
+
/** The owning group's `data-hidden` (defaults to false) — resolved once per parse. */
|
|
320
|
+
audioGroupHidden?: boolean;
|
|
321
|
+
/** The owning group's serialized `data-fx-chain`, when set — resolved once per parse. */
|
|
322
|
+
audioGroupFxChain?: string;
|
|
253
323
|
/**
|
|
254
324
|
* Set by useExpandedTimelineElements on an inline-expanded sub-composition
|
|
255
325
|
* child: the absolute master-timeline start of the sub-comp host the child
|
|
@@ -265,7 +335,7 @@ type TimelineTool = "select" | "razor";
|
|
|
265
335
|
interface SelectElementOptions {
|
|
266
336
|
preserveSet?: boolean;
|
|
267
337
|
}
|
|
268
|
-
interface PlayerState extends KeyframeSlice, AutomationSelectionSlice, ThumbnailSlice {
|
|
338
|
+
interface PlayerState extends KeyframeSlice, AutomationSelectionSlice, ThumbnailSlice, AudioSoloSlice, EditingModeSlice {
|
|
269
339
|
isPlaying: boolean;
|
|
270
340
|
currentTime: number;
|
|
271
341
|
duration: number;
|
|
@@ -303,20 +373,6 @@ interface PlayerState extends KeyframeSlice, AutomationSelectionSlice, Thumbnail
|
|
|
303
373
|
* (drag, resize, rotate) target this instead of recomputing from playhead. */
|
|
304
374
|
activeKeyframePct: number | null;
|
|
305
375
|
setActiveKeyframePct: (pct: number | null) => void;
|
|
306
|
-
/** Motion-path "set destination" mode. Armed from the preview toolbar (replaces
|
|
307
|
-
* the old double-click-on-canvas UX); while armed, one canvas click places the
|
|
308
|
-
* new path's destination. `available` is published by MotionPathOverlay so the
|
|
309
|
-
* toolbar shows the button only when the selected element can take a path. */
|
|
310
|
-
motionPathArmed: boolean;
|
|
311
|
-
setMotionPathArmed: (armed: boolean) => void;
|
|
312
|
-
motionPathCreateAvailable: boolean;
|
|
313
|
-
setMotionPathCreateAvailable: (available: boolean) => void;
|
|
314
|
-
/** Global toggle for the "Add keyframe" diamond in the timeline toolbar (#1808).
|
|
315
|
-
* When false, a manual drag/resize/rotate edit on an element that already has
|
|
316
|
-
* a live tween shifts every keyframe by the edit's delta (preserving the
|
|
317
|
-
* animation's shape) instead of inserting/updating a keyframe at the playhead. */
|
|
318
|
-
autoKeyframeEnabled: boolean;
|
|
319
|
-
setAutoKeyframeEnabled: (enabled: boolean) => void;
|
|
320
376
|
/** Multi-select: additional selected elements beyond selectedElementId. */
|
|
321
377
|
selectedElementIds: Set<string>;
|
|
322
378
|
clearSelectedElementIds: () => void;
|
|
@@ -355,7 +411,7 @@ interface PlayerState extends KeyframeSlice, AutomationSelectionSlice, Thumbnail
|
|
|
355
411
|
setSelectedElementId: (id: string | null, options?: SelectElementOptions) => void;
|
|
356
412
|
/** Move the selection anchor within an active multi-selection without collapsing it. */
|
|
357
413
|
setSelectionAnchor: (id: string | null) => void;
|
|
358
|
-
updateElement: (elementId: string, updates: Partial<Pick<TimelineElement, "start" | "duration" | "track" | "zIndex" | "hasExplicitZIndex" | "playbackStart" | "hidden">>) => void;
|
|
414
|
+
updateElement: (elementId: string, updates: Partial<Pick<TimelineElement, "start" | "duration" | "track" | "zIndex" | "hasExplicitZIndex" | "playbackStart" | "hidden" | "audioGroup">>) => void;
|
|
359
415
|
setZoomMode: (mode: ZoomMode) => void;
|
|
360
416
|
setManualZoomPercent: (percent: number) => void;
|
|
361
417
|
bumpZEditVersion: () => void;
|
|
@@ -600,6 +656,18 @@ interface TimelineEditCallbacks {
|
|
|
600
656
|
coalesceKey?: string;
|
|
601
657
|
}) => Promise<void> | void;
|
|
602
658
|
onToggleTrackHidden?: (track: number, hidden: boolean) => Promise<void> | void;
|
|
659
|
+
/** B7's bus strip: live-write the group's own attribute while dragging. */
|
|
660
|
+
onSetAudioGroupAttributeLive?: (groupId: string, attr: string, value: string | null) => void;
|
|
661
|
+
/** ...and persist one undo entry on release. */
|
|
662
|
+
onSetAudioGroupAttributeQuiet?: (groupId: string, attr: string, value: string | null, label: string) => Promise<void>;
|
|
663
|
+
/** C1's ungrouped-track FX pointer: "Group these clips" — write
|
|
664
|
+
* `data-audio-group` on every one of them, atomically. Same shape B6's
|
|
665
|
+
* carve auto-grouping uses. */
|
|
666
|
+
onGroupClips?: (clipIds: readonly string[], groupId: string) => Promise<void>;
|
|
667
|
+
/** C1's single-clip FX write: addressed by the clip itself rather than the
|
|
668
|
+
* current selection, mirroring `onSetAudioGroupAttributeLive/Quiet`. */
|
|
669
|
+
onSetElementAttributeLive?: (element: TimelineElement, attr: string, value: string | null) => void;
|
|
670
|
+
onSetElementAttributeQuiet?: (element: TimelineElement, attr: string, value: string | null, label: string) => Promise<void>;
|
|
603
671
|
onBlockedEditAttempt?: (element: TimelineElement, intent: BlockedTimelineEditIntent) => void;
|
|
604
672
|
onSplitElement?: (element: TimelineElement, splitTime: number) => Promise<void> | void;
|
|
605
673
|
onRazorSplit?: (element: TimelineElement, splitTime: number) => Promise<void> | void;
|
|
@@ -759,10 +827,21 @@ interface TimelineEditCallbackDeps {
|
|
|
759
827
|
handleTimelineElementResize: (element: TimelineElement, updates: Pick<TimelineElement, "start" | "duration" | "playbackStart">) => Promise<void> | void;
|
|
760
828
|
handleTimelineGroupResize: NonNullable<TimelineEditCallbacks["onResizeElements"]>;
|
|
761
829
|
handleToggleTrackHidden: (track: number, hidden: boolean) => Promise<void> | void;
|
|
830
|
+
setAudioGroupAttribute: {
|
|
831
|
+
setLive: (groupId: string, attr: string, value: string | null) => void;
|
|
832
|
+
setQuiet: (groupId: string, attr: string, value: string | null, label: string) => Promise<void>;
|
|
833
|
+
};
|
|
762
834
|
handleBlockedTimelineEdit: (element: TimelineElement, intent: BlockedTimelineEditIntent) => void;
|
|
763
835
|
handleTimelineElementSplit: (element: TimelineElement, splitTime: number) => Promise<void> | void;
|
|
764
836
|
handleRazorSplit: (element: TimelineElement, splitTime: number) => Promise<void> | void;
|
|
765
837
|
handleRazorSplitAll: (splitTime: number) => Promise<void> | void;
|
|
838
|
+
/** C1's ungrouped-track FX pointer — same auto-grouping write B6's carve uses. */
|
|
839
|
+
handleGroupClips?: (clipIds: readonly string[], groupId: string) => Promise<void>;
|
|
840
|
+
/** C1's single-clip FX write, addressed by the clip itself. */
|
|
841
|
+
setElementFxAttribute?: {
|
|
842
|
+
setLive: (element: TimelineElement, attr: string, value: string | null) => void;
|
|
843
|
+
setQuiet: (element: TimelineElement, attr: string, value: string | null, label: string) => Promise<void>;
|
|
844
|
+
};
|
|
766
845
|
}
|
|
767
846
|
|
|
768
847
|
interface BlockPreviewInfo {
|
|
@@ -806,7 +885,7 @@ interface EditorShellProps extends TimelineEditCallbackDeps {
|
|
|
806
885
|
onToggleRecording?: () => void;
|
|
807
886
|
gestureOverlay?: ReactNode;
|
|
808
887
|
}
|
|
809
|
-
declare function EditorShell({ left, right, hidden, timelineToolbar, renderClipContent, handleTimelineElementDelete, handleTimelineAssetDrop, handleTimelineBlockDrop, handleTimelineCompositionDrop, handlePreviewBlockDrop, handleTimelineFileDrop, handleTimelineElementMove, handleTimelineElementsMove, handleTimelineElementResize, handleTimelineGroupResize, handleToggleTrackHidden, handleBlockedTimelineEdit, handleTimelineElementSplit, handleRazorSplit, handleRazorSplitAll, setCompIdToSrc, setCompositionLoading, shouldShowMotionPath, shouldShowSelectedDomBounds, isGestureRecording, recordingState, onToggleRecording, blockPreview, gestureOverlay, }: EditorShellProps): react_jsx_runtime.JSX.Element;
|
|
888
|
+
declare function EditorShell({ left, right, hidden, timelineToolbar, renderClipContent, handleTimelineElementDelete, handleTimelineAssetDrop, handleTimelineBlockDrop, handleTimelineCompositionDrop, handlePreviewBlockDrop, handleTimelineFileDrop, handleTimelineElementMove, handleTimelineElementsMove, handleTimelineElementResize, handleTimelineGroupResize, handleToggleTrackHidden, setAudioGroupAttribute, handleGroupClips, setElementFxAttribute, handleBlockedTimelineEdit, handleTimelineElementSplit, handleRazorSplit, handleRazorSplitAll, setCompIdToSrc, setCompositionLoading, shouldShowMotionPath, shouldShowSelectedDomBounds, isGestureRecording, recordingState, onToggleRecording, blockPreview, gestureOverlay, }: EditorShellProps): react_jsx_runtime.JSX.Element;
|
|
810
889
|
|
|
811
890
|
interface NLEPreviewProps {
|
|
812
891
|
projectId: string;
|
|
@@ -966,6 +1045,8 @@ interface PropertyPanelProps {
|
|
|
966
1045
|
onRemoveTextField: (fieldKey: string) => void;
|
|
967
1046
|
onAskAgent: () => void;
|
|
968
1047
|
onToggleElementHidden?: (elementKey: string, hidden: boolean) => void | Promise<void>;
|
|
1048
|
+
/** B6: group two or more picked voice clips, atomically, one undo entry. */
|
|
1049
|
+
onAutoGroupCarveSources?: (clipIds: readonly string[], groupId: string) => Promise<void>;
|
|
969
1050
|
onImportAssets?: (files: FileList, dir?: string) => Promise<string[]>;
|
|
970
1051
|
onAddMediaOverlay?: AddMediaOverlayHandler;
|
|
971
1052
|
fontAssets?: ImportedFontAsset[];
|
package/dist/studio/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-CUXnyoIa.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Ba9zbpT9.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div data-hf-id="hf-aph5" id="root"></div>
|