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.
@@ -1 +1 @@
1
- import{g as P}from"./index-Cx_UrhoW.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};
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};
@@ -1,4 +1,4 @@
1
- import{n as Qi}from"./index-Cx_UrhoW.js";/*!
1
+ import{n as Qi}from"./index-CUXnyoIa.js";/*!
2
2
  * Copyright (c) 2026-present, Vanilagy and contributors
3
3
  *
4
4
  * This Source Code Form is subject to the terms of the Mozilla Public
@@ -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[];
@@ -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-Cx_UrhoW.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-DcF4s1PG.css">
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>