@hyperframes/studio 0.7.55 → 0.7.57

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.
Files changed (274) hide show
  1. package/dist/assets/hyperframes-player--Z69cEkE.js +459 -0
  2. package/dist/assets/{index-CPetwHFV.js → index-Bf1x1y8H.js} +1 -1
  3. package/dist/assets/index-DfmYkU44.js +423 -0
  4. package/dist/assets/{index-BXaqaVKt.js → index-KsfE1bUu.js} +1 -1
  5. package/dist/assets/index-_pqzyxB1.css +1 -0
  6. package/dist/{chunk-SOTCF4DF.js → chunk-5QSIMBEJ.js} +2 -1
  7. package/dist/chunk-5QSIMBEJ.js.map +1 -0
  8. package/dist/{domEditingLayers-2ECJK24D.js → domEditingLayers-6LQGKPOI.js} +2 -2
  9. package/dist/index.d.ts +172 -144
  10. package/dist/index.html +2 -2
  11. package/dist/index.js +43613 -40346
  12. package/dist/index.js.map +1 -1
  13. package/package.json +7 -7
  14. package/src/App.tsx +106 -96
  15. package/src/components/EditorShell.tsx +253 -0
  16. package/src/components/StudioGlobalDragOverlay.tsx +1 -3
  17. package/src/components/StudioLeftSidebar.tsx +13 -3
  18. package/src/components/StudioRightPanel.tsx +8 -3
  19. package/src/components/TimelineToolbar.test.tsx +2 -2
  20. package/src/components/TimelineToolbar.tsx +179 -121
  21. package/src/components/editor/CanvasContextMenu.test.tsx +152 -1
  22. package/src/components/editor/CanvasContextMenu.tsx +33 -18
  23. package/src/components/editor/DomEditCropHandles.test.tsx +74 -3
  24. package/src/components/editor/DomEditCropHandles.tsx +64 -29
  25. package/src/components/editor/DomEditOverlay.test.ts +245 -279
  26. package/src/components/editor/DomEditOverlay.tsx +126 -125
  27. package/src/components/editor/DomEditOverlayHover.test.tsx +90 -0
  28. package/src/components/editor/DomEditRotateHandle.tsx +38 -18
  29. package/src/components/editor/DomEditSelectionChrome.test.tsx +80 -0
  30. package/src/components/editor/DomEditSelectionChrome.tsx +257 -0
  31. package/src/components/editor/LayersPanel.test.ts +66 -2
  32. package/src/components/editor/LayersPanel.tsx +53 -2
  33. package/src/components/editor/OffCanvasIndicators.test.tsx +34 -0
  34. package/src/components/editor/OffCanvasIndicators.tsx +49 -10
  35. package/src/components/editor/SnapGuideOverlay.tsx +28 -23
  36. package/src/components/editor/SnapToolbar.test.tsx +0 -1
  37. package/src/components/editor/anchoredResizeCommitFeedsOffset.test.ts +214 -0
  38. package/src/components/editor/anchoredResizeReleaseShift.test.ts +106 -10
  39. package/src/components/editor/canvasContextMenuZOrder.test.ts +186 -2
  40. package/src/components/editor/canvasContextMenuZOrder.ts +144 -22
  41. package/src/components/editor/domEditNudge.test.ts +80 -0
  42. package/src/components/editor/domEditNudge.ts +44 -0
  43. package/src/components/editor/domEditOverlayGeometry.test.ts +167 -1
  44. package/src/components/editor/domEditOverlayGeometry.ts +280 -20
  45. package/src/components/editor/domEditOverlayGestures.ts +44 -41
  46. package/src/components/editor/domEditOverlayStartGesture.ts +62 -2
  47. package/src/components/editor/domEditResizeLocal.test.ts +131 -0
  48. package/src/components/editor/domEditResizeLocal.ts +125 -0
  49. package/src/components/editor/domEditingDom.ts +1 -1
  50. package/src/components/editor/manualEditsDomPatches.test.ts +47 -0
  51. package/src/components/editor/manualOffsetDrag.ts +55 -12
  52. package/src/components/editor/offCanvasIndicatorGeometry.ts +31 -10
  53. package/src/components/editor/offCanvasIndicatorRefresh.test.tsx +25 -1
  54. package/src/components/editor/propertyPanelColorGradingSection.tsx +15 -21
  55. package/src/components/editor/resizeDraft.ts +108 -0
  56. package/src/components/editor/snapEngine.test.ts +12 -78
  57. package/src/components/editor/snapEngine.ts +13 -53
  58. package/src/components/editor/useCanvasContextMenuState.ts +92 -0
  59. package/src/components/editor/useDomEditNudge.test.tsx +228 -0
  60. package/src/components/editor/useDomEditNudge.ts +254 -0
  61. package/src/components/editor/useDomEditOverlayGestures.ts +115 -116
  62. package/src/components/editor/useDomEditOverlayRects.ts +9 -2
  63. package/src/components/editor/useZOrderCrossedFlash.tsx +68 -0
  64. package/src/components/nle/AssetPreviewOverlay.test.tsx +106 -0
  65. package/src/components/nle/AssetPreviewOverlay.tsx +171 -0
  66. package/src/components/nle/NLEContext.test.ts +144 -0
  67. package/src/components/nle/NLEContext.tsx +328 -0
  68. package/src/components/nle/NLEPreview.tsx +1 -1
  69. package/src/components/nle/PreviewOverlays.tsx +260 -0
  70. package/src/components/nle/PreviewPane.tsx +163 -0
  71. package/src/components/nle/TimelinePane.test.ts +60 -0
  72. package/src/components/nle/TimelinePane.tsx +293 -0
  73. package/src/components/nle/TimelineResizeDivider.tsx +8 -2
  74. package/src/components/nle/useCompositionStack.test.tsx +44 -0
  75. package/src/components/nle/useCompositionStack.ts +17 -9
  76. package/src/components/nle/useTimelineEditCallbacks.ts +217 -0
  77. package/src/components/sidebar/AssetCard.test.tsx +106 -0
  78. package/src/components/sidebar/AssetCard.tsx +343 -0
  79. package/src/components/sidebar/AssetContextMenu.tsx +15 -30
  80. package/src/components/sidebar/AssetsTab.test.ts +96 -0
  81. package/src/components/sidebar/AssetsTab.tsx +71 -206
  82. package/src/components/sidebar/AudioRow.tsx +56 -2
  83. package/src/components/sidebar/BlocksTab.tsx +8 -1
  84. package/src/components/sidebar/LeftSidebar.tsx +4 -1
  85. package/src/components/sidebar/assetHelpers.ts +29 -0
  86. package/src/contexts/DomEditContext.tsx +9 -0
  87. package/src/contexts/StudioContext.tsx +9 -8
  88. package/src/contexts/TimelineEditContext.tsx +3 -7
  89. package/src/hooks/deleteSelectedKeyframes.ts +35 -0
  90. package/src/hooks/domEditCommitTypes.ts +23 -1
  91. package/src/hooks/domSelectionTestHarness.ts +14 -0
  92. package/src/hooks/gestureTransaction.test.ts +311 -0
  93. package/src/hooks/gestureTransaction.ts +199 -0
  94. package/src/hooks/gsapDragCommit.test.ts +141 -41
  95. package/src/hooks/gsapDragCommit.ts +64 -74
  96. package/src/hooks/gsapDragStaticSetHelpers.ts +9 -21
  97. package/src/hooks/gsapResizeIntercept.test.ts +69 -0
  98. package/src/hooks/gsapResizeIntercept.ts +38 -10
  99. package/src/hooks/gsapRuntimeBridge.test.ts +49 -13
  100. package/src/hooks/gsapRuntimeBridge.ts +4 -4
  101. package/src/hooks/gsapScriptCommitTypes.ts +16 -5
  102. package/src/hooks/gsapShared.test.ts +19 -1
  103. package/src/hooks/gsapShared.ts +14 -0
  104. package/src/hooks/patchDocumentRootDuration.test.ts +71 -0
  105. package/src/hooks/timelineEditingGsap.ts +14 -0
  106. package/src/hooks/timelineEditingHelpers.test.ts +125 -1
  107. package/src/hooks/timelineEditingHelpers.ts +53 -292
  108. package/src/hooks/timelineMoveAdapter.test.ts +81 -0
  109. package/src/hooks/timelineMoveAdapter.ts +39 -0
  110. package/src/hooks/timelineTimingSync.test.ts +150 -0
  111. package/src/hooks/timelineTimingSync.ts +412 -0
  112. package/src/hooks/useAnimatedPropertyCommit.test.tsx +36 -8
  113. package/src/hooks/useAnimatedPropertyCommit.ts +31 -26
  114. package/src/hooks/useAppHotkeys.ts +16 -25
  115. package/src/hooks/useBlockHandlers.ts +55 -27
  116. package/src/hooks/useCaptionDetection.ts +2 -0
  117. package/src/hooks/useCompositionDimensions.ts +32 -5
  118. package/src/hooks/useContextMenuDismiss.ts +31 -7
  119. package/src/hooks/useDomEditCommits.test.tsx +245 -1
  120. package/src/hooks/useDomEditCommits.ts +162 -3
  121. package/src/hooks/useDomEditPositionPatchCommit.ts +2 -0
  122. package/src/hooks/useDomEditSession.ts +2 -2
  123. package/src/hooks/useDomEditTextCommits.test.tsx +135 -0
  124. package/src/hooks/useDomEditTextCommits.ts +8 -3
  125. package/src/hooks/useDomEditWiring.ts +7 -9
  126. package/src/hooks/useDomGeometryCommits.ts +17 -2
  127. package/src/hooks/useDomSelection.test.ts +2 -36
  128. package/src/hooks/useDomSelection.ts +81 -51
  129. package/src/hooks/useDomSelectionSelectionGuards.test.ts +276 -0
  130. package/src/hooks/useElementLifecycleOps.test.tsx +423 -0
  131. package/src/hooks/useElementLifecycleOps.ts +53 -71
  132. package/src/hooks/useElementPicker.ts +7 -8
  133. package/src/hooks/useEnableKeyframes.test.ts +142 -1
  134. package/src/hooks/useEnableKeyframes.ts +73 -29
  135. package/src/hooks/useGestureCommit.test.tsx +130 -0
  136. package/src/hooks/useGestureCommit.ts +32 -8
  137. package/src/hooks/useGroupCommits.ts +7 -28
  138. package/src/hooks/useGsapAwareEditing.test.tsx +239 -0
  139. package/src/hooks/useGsapAwareEditing.ts +115 -20
  140. package/src/hooks/useGsapKeyframeOps.test.tsx +59 -0
  141. package/src/hooks/useGsapKeyframeOps.ts +38 -10
  142. package/src/hooks/useGsapScriptCommits.test.tsx +40 -1
  143. package/src/hooks/useGsapScriptCommits.ts +134 -50
  144. package/src/hooks/useGsapSelectionHandlers.ts +49 -16
  145. package/src/hooks/useMusicBeatAnalysis.ts +72 -36
  146. package/src/hooks/usePersistentEditHistory.test.ts +33 -0
  147. package/src/hooks/usePersistentEditHistory.ts +92 -58
  148. package/src/hooks/usePreviewPersistence.ts +25 -7
  149. package/src/hooks/useRazorSplit.history.test.tsx +148 -18
  150. package/src/hooks/useRazorSplit.test.ts +269 -0
  151. package/src/hooks/useRazorSplit.testHelpers.ts +64 -0
  152. package/src/hooks/useRazorSplit.ts +107 -36
  153. package/src/hooks/useRenderClipContent.ts +24 -6
  154. package/src/hooks/useStudioContextValue.ts +15 -5
  155. package/src/hooks/useStudioUrlState.ts +2 -4
  156. package/src/hooks/useTimelineAssetDropOps.ts +175 -0
  157. package/src/hooks/useTimelineEditing.test.tsx +398 -241
  158. package/src/hooks/useTimelineEditing.ts +181 -265
  159. package/src/hooks/useTimelineEditingTypes.ts +6 -0
  160. package/src/hooks/useTimelineGroupEditing.ts +167 -132
  161. package/src/index.ts +1 -1
  162. package/src/player/components/ImageThumbnail.test.tsx +173 -0
  163. package/src/player/components/ImageThumbnail.tsx +160 -0
  164. package/src/player/components/PlayerControls.tsx +5 -5
  165. package/src/player/components/PlayheadIndicator.tsx +55 -5
  166. package/src/player/components/Timeline.test.ts +183 -23
  167. package/src/player/components/Timeline.tsx +194 -194
  168. package/src/player/components/TimelineCanvas.tsx +218 -523
  169. package/src/player/components/TimelineClip.tsx +4 -1
  170. package/src/player/components/TimelineClipDiamonds.tsx +9 -40
  171. package/src/player/components/TimelineEmptyState.tsx +3 -1
  172. package/src/player/components/TimelineLanes.tsx +487 -0
  173. package/src/player/components/TimelineOverlays.tsx +122 -0
  174. package/src/player/components/TimelineRuler.tsx +58 -48
  175. package/src/player/components/VideoThumbnail.test.tsx +152 -0
  176. package/src/player/components/VideoThumbnail.tsx +28 -7
  177. package/src/player/components/thumbnailUtils.test.ts +127 -0
  178. package/src/player/components/thumbnailUtils.ts +54 -0
  179. package/src/player/components/timelineCallbacks.ts +18 -18
  180. package/src/player/components/timelineClipChildren.tsx +39 -0
  181. package/src/player/components/timelineClipDragCommit.test.ts +1026 -0
  182. package/src/player/components/timelineClipDragCommit.ts +498 -0
  183. package/src/player/components/timelineClipDragPreview.test.ts +144 -0
  184. package/src/player/components/timelineClipDragPreview.ts +323 -38
  185. package/src/player/components/timelineClipDragTypes.ts +65 -0
  186. package/src/player/components/timelineCollision.test.ts +42 -2
  187. package/src/player/components/timelineDragDrop.ts +69 -60
  188. package/src/player/components/timelineEditCapabilities.ts +52 -0
  189. package/src/player/components/timelineEditing.test.ts +1 -1
  190. package/src/player/components/timelineEditing.ts +76 -59
  191. package/src/player/components/timelineGroupEditing.test.ts +126 -0
  192. package/src/player/components/timelineGroupEditing.ts +133 -0
  193. package/src/player/components/timelineGroupResizeCommit.ts +54 -0
  194. package/src/player/components/timelineLayout.test.ts +95 -23
  195. package/src/player/components/timelineLayout.ts +207 -75
  196. package/src/player/components/timelineMarquee.test.ts +197 -0
  197. package/src/player/components/timelineMarquee.ts +112 -0
  198. package/src/player/components/timelineOptimisticRevision.ts +42 -0
  199. package/src/player/components/timelineRevealScroll.test.ts +133 -0
  200. package/src/player/components/timelineRevealScroll.ts +91 -0
  201. package/src/player/components/timelineStackingSync.test.ts +60 -0
  202. package/src/player/components/timelineStackingSync.ts +27 -2
  203. package/src/player/components/timelineTheme.ts +6 -1
  204. package/src/player/components/timelineTrackPersistPipeline.test.ts +168 -0
  205. package/src/player/components/timelineZones.test.ts +122 -310
  206. package/src/player/components/timelineZones.ts +82 -135
  207. package/src/player/components/useResolvedTimelineEditCallbacks.ts +25 -3
  208. package/src/player/components/useTimelineClipDrag.resize.test.tsx +241 -0
  209. package/src/player/components/useTimelineClipDrag.ts +380 -386
  210. package/src/player/components/useTimelineEditPinning.ts +121 -0
  211. package/src/player/components/useTimelineGeometry.ts +129 -0
  212. package/src/player/components/useTimelinePlayhead.ts +4 -16
  213. package/src/player/components/useTimelineRangeSelection.ts +341 -50
  214. package/src/player/components/useTimelineRevealClip.ts +56 -0
  215. package/src/player/components/useTimelineStackingSync.test.tsx +77 -0
  216. package/src/player/components/useTimelineStackingSync.ts +94 -0
  217. package/src/player/hooks/useExpandedTimelineElements.ts +7 -3
  218. package/src/player/hooks/usePlaybackKeyboard.ts +5 -0
  219. package/src/player/hooks/useTimelinePlayer.seek.test.ts +55 -0
  220. package/src/player/hooks/useTimelinePlayer.test.ts +36 -3
  221. package/src/player/hooks/useTimelinePlayer.ts +52 -53
  222. package/src/player/hooks/useTimelinePlayerLoop.ts +85 -0
  223. package/src/player/hooks/useTimelineSyncCallbacks.ts +9 -1
  224. package/src/player/index.ts +5 -2
  225. package/src/player/lib/runtimeProtocol.test.ts +48 -0
  226. package/src/player/lib/runtimeProtocol.ts +65 -0
  227. package/src/player/lib/time.test.ts +19 -19
  228. package/src/player/lib/time.ts +6 -2
  229. package/src/player/lib/timelineDOM.test.ts +25 -98
  230. package/src/player/lib/timelineDOM.ts +21 -81
  231. package/src/player/lib/timelineElementHelpers.ts +73 -5
  232. package/src/player/lib/timelineIframeHelpers.ts +4 -4
  233. package/src/player/store/playerStore.test.ts +38 -13
  234. package/src/player/store/playerStore.ts +99 -3
  235. package/src/styles/studio.css +27 -0
  236. package/src/utils/assetPreviewDismiss.test.ts +27 -0
  237. package/src/utils/assetPreviewDismiss.ts +29 -0
  238. package/src/utils/assetPreviewStore.ts +33 -0
  239. package/src/utils/blockInstaller.ts +10 -2
  240. package/src/utils/editHistory.test.ts +35 -0
  241. package/src/utils/gsapSoftReload.test.ts +119 -1
  242. package/src/utils/gsapSoftReload.ts +153 -0
  243. package/src/utils/mediaTypes.ts +3 -2
  244. package/src/utils/resizeDebug.ts +55 -0
  245. package/src/utils/rootDuration.test.ts +90 -1
  246. package/src/utils/rootDuration.ts +76 -13
  247. package/src/utils/sdkCutover.ts +4 -0
  248. package/src/utils/studioFileHistory.ts +37 -7
  249. package/src/utils/studioHelpers.ts +62 -0
  250. package/src/utils/studioPreviewHelpers.test.ts +65 -8
  251. package/src/utils/studioPreviewHelpers.ts +10 -0
  252. package/src/utils/studioTelemetry.ts +4 -1
  253. package/src/utils/studioUrlState.test.ts +0 -1
  254. package/src/utils/timelineAssetDrop.test.ts +144 -52
  255. package/src/utils/timelineAssetDrop.ts +67 -29
  256. package/src/utils/timelineDiscovery.ts +0 -17
  257. package/dist/assets/hyperframes-player-BBrKzTGd.js +0 -459
  258. package/dist/assets/index-BRwkMj0w.js +0 -423
  259. package/dist/assets/index-Dq7FEg0K.css +0 -1
  260. package/dist/chunk-SOTCF4DF.js.map +0 -1
  261. package/src/components/StudioPreviewArea.tsx +0 -500
  262. package/src/components/nle/NLELayout.test.ts +0 -12
  263. package/src/components/nle/NLELayout.tsx +0 -591
  264. package/src/player/components/TimelineLayerGutter.tsx +0 -61
  265. package/src/player/components/TimelineSelectionOverlays.tsx +0 -55
  266. package/src/player/components/timelineMarqueeSelection.test.ts +0 -87
  267. package/src/player/components/timelineSnapTargets.test.ts +0 -144
  268. package/src/player/components/timelineSnapTargets.ts +0 -164
  269. package/src/player/components/useTimelineClipDrag.test.tsx +0 -506
  270. package/src/player/components/useTimelineClipGroupDrag.ts +0 -417
  271. package/src/player/components/useTimelineMarqueeSelection.test.tsx +0 -231
  272. package/src/player/components/useTimelineMarqueeSelection.ts +0 -276
  273. package/src/utils/timelineDiscovery.test.ts +0 -90
  274. /package/dist/{domEditingLayers-2ECJK24D.js.map → domEditingLayers-6LQGKPOI.js.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
1
2
  import * as react from 'react';
2
3
  import { ReactNode, RefObject } from 'react';
3
4
  import * as zustand from 'zustand';
4
5
  import { MusicBeatAnalysis } from '@hyperframes/core/beats';
5
- import * as react_jsx_runtime from 'react/jsx-runtime';
6
6
  import { GsapAnimation, ArcPathSegment } from '@hyperframes/parsers/gsap-parser';
7
7
 
8
8
  interface PlayerProps {
@@ -86,6 +86,17 @@ interface TimelineElement {
86
86
  start: number;
87
87
  duration: number;
88
88
  track: number;
89
+ /**
90
+ * The data-track-index as written in the source file. Set at the manifest
91
+ * translation boundary (createTimelineElementFromManifestClip) from the
92
+ * runtime clip's verbatim track, and preserved through display-lane remaps
93
+ * (normalizeToZones packs sparse authored tracks onto contiguous display
94
+ * lanes; expanded sub-comp children get synthetic display rows). Lane edits
95
+ * must persist THIS space — writing a display-lane number into a sparse file
96
+ * re-targets the wrong track. For an expanded child the value is in its OWN
97
+ * source file's coordinate space, not the host timeline's.
98
+ */
99
+ authoredTrack?: number;
89
100
  /** Resolved z-index for stacking-aware timeline ordering. */
90
101
  zIndex?: number;
91
102
  /** True when the effective z-index was authored inline or through CSS, not auto. */
@@ -131,6 +142,9 @@ interface TimelineElement {
131
142
  }
132
143
  type ZoomMode = "fit" | "manual";
133
144
  type TimelineTool = "select" | "razor";
145
+ interface SelectElementOptions {
146
+ preserveSet?: boolean;
147
+ }
134
148
  interface PlayerState {
135
149
  isPlaying: boolean;
136
150
  currentTime: number;
@@ -177,6 +191,28 @@ interface PlayerState {
177
191
  setAutoKeyframeEnabled: (enabled: boolean) => void;
178
192
  /** Multi-select: additional selected elements beyond selectedElementId. */
179
193
  selectedElementIds: Set<string>;
194
+ clearSelectedElementIds: () => void;
195
+ /** Replace the whole multi-selection at once (marquee live updates). */
196
+ setSelectedElementIds: (ids: Set<string>) => void;
197
+ /** Timeline magnet toggle — when false, clip drags/trims/drops never snap. */
198
+ timelineSnapEnabled: boolean;
199
+ setTimelineSnapEnabled: (enabled: boolean) => void;
200
+ /** Transport + ruler readout: timecode ("time") or frame number ("frame"). */
201
+ timeDisplayMode: "time" | "frame";
202
+ setTimeDisplayMode: (mode: "time" | "frame") => void;
203
+ /**
204
+ * Pin the timeline zoom to its current visual scale before a duration-changing
205
+ * edit, so a subsequent duration change (which recomputes fit-pps) stops
206
+ * rescaling every clip. No-op once already pinned (mode is "manual").
207
+ */
208
+ pinTimelineZoom: (currentPixelsPerSecond: number, fitPixelsPerSecond: number) => void;
209
+ /**
210
+ * The timeline's live pixels-per-second + fit basis, published by <Timeline> on
211
+ * every render. Non-reactive scratch state (never read as a render input).
212
+ */
213
+ timelinePps: number;
214
+ timelineFitPps: number;
215
+ setTimelineScale: (pps: number, fitPps: number) => void;
180
216
  setSelection: (ids: Iterable<string>, anchor?: string | null) => void;
181
217
  addSelectedElementId: (id: string) => void;
182
218
  toggleSelectedElementId: (id: string) => void;
@@ -193,7 +229,7 @@ interface PlayerState {
193
229
  setTimelineReady: (ready: boolean) => void;
194
230
  setBeatDragging: (dragging: boolean) => void;
195
231
  setElements: (elements: TimelineElement[]) => void;
196
- setSelectedElementId: (id: string | null) => void;
232
+ setSelectedElementId: (id: string | null, options?: SelectElementOptions) => void;
197
233
  /** Move the selection anchor within an active multi-selection without collapsing it. */
198
234
  setSelectionAnchor: (id: string | null) => void;
199
235
  updateElement: (elementId: string, updates: Partial<Pick<TimelineElement, "start" | "duration" | "track" | "zIndex" | "hasExplicitZIndex" | "playbackStart" | "hidden">>) => void;
@@ -209,6 +245,18 @@ interface PlayerState {
209
245
  requestedSeekTime: number | null;
210
246
  requestSeek: (time: number) => void;
211
247
  clearSeekRequest: () => void;
248
+ /**
249
+ * Request the timeline to scroll a clip into view (e.g. clicking an
250
+ * already-added asset card in the sidebar). Consumed and cleared by
251
+ * useTimelineRevealClip. The nonce makes repeat requests for the same
252
+ * clip observable so a second click re-reveals after the user scrolls away.
253
+ */
254
+ clipRevealRequest: {
255
+ elementId: string;
256
+ nonce: number;
257
+ } | null;
258
+ requestClipReveal: (elementId: string) => void;
259
+ clearClipRevealRequest: () => void;
212
260
  lintFindingsByElement: Map<string, {
213
261
  count: number;
214
262
  messages: string[];
@@ -264,36 +312,6 @@ declare const liveTime: {
264
312
  };
265
313
  declare const usePlayerStore: zustand.UseBoundStore<zustand.StoreApi<PlayerState>>;
266
314
 
267
- type TimelineLayerDropPlacement = {
268
- type: "onto";
269
- layerId: string;
270
- } | {
271
- type: "between";
272
- beforeLayerId: string;
273
- afterLayerId: string;
274
- } | {
275
- type: "above";
276
- layerId: string;
277
- } | {
278
- type: "below";
279
- layerId: string;
280
- };
281
- interface TimelineStackingZIndexChange {
282
- key: string;
283
- zIndex: number;
284
- domId?: string;
285
- selector?: string;
286
- selectorIndex?: number;
287
- sourceFile?: string;
288
- }
289
- interface TimelineStackingReorderIntent {
290
- contextKey: string;
291
- placement: TimelineLayerDropPlacement;
292
- zIndexChanges: TimelineStackingZIndexChange[];
293
- }
294
-
295
- type BlockedTimelineEditIntent = "move" | "resize-start" | "resize-end";
296
-
297
315
  /**
298
316
  * Source Patcher — Maps visual property edits back to source HTML files.
299
317
  * Handles inline style updates, attribute changes, and text content.
@@ -320,21 +338,63 @@ declare function resolveSourceFile(elementId: string | null, selector: string, f
320
338
  */
321
339
  declare function applyPatch(html: string, elementId: string, op: PatchOperation): string;
322
340
 
323
- interface TimelineGroupMoveChange {
324
- element: TimelineElement;
325
- start: number;
341
+ type BlockedTimelineEditIntent = "move" | "resize-start" | "resize-end";
342
+
343
+ interface DomEditCapabilities {
344
+ canSelect: boolean;
345
+ canEditStyles: boolean;
346
+ /** Can take a non-destructive `clip-path: inset()` crop — broader than
347
+ * canEditStyles (a sub-composition host is croppable from the parent view). */
348
+ canCrop: boolean;
349
+ /** Directly editable authored left/top style fields. Canvas drag uses manual edits instead. */
350
+ canMove: boolean;
351
+ /** Directly editable authored width/height style fields. Canvas resize uses manual edits instead. */
352
+ canResize: boolean;
353
+ canApplyManualOffset: boolean;
354
+ canApplyManualSize: boolean;
355
+ canApplyManualRotation: boolean;
356
+ reasonIfDisabled?: string;
326
357
  }
327
- interface TimelineGroupResizeChange {
328
- element: TimelineElement;
329
- start: number;
330
- duration: number;
331
- playbackStart?: number;
358
+ interface DomEditTextField {
359
+ key: string;
360
+ label: string;
361
+ value: string;
362
+ tagName: string;
363
+ attributes: Array<{
364
+ name: string;
365
+ value: string;
366
+ }>;
367
+ inlineStyles: Record<string, string>;
368
+ computedStyles: Record<string, string>;
369
+ source: "self" | "child" | "text-node";
370
+ sourceChildIndex?: number;
332
371
  }
333
- interface TimelineGroupCommitOptions {
334
- beforeTiming?: Promise<void>;
335
- coalesceKey?: string;
372
+ interface DomEditSelection extends PatchTarget {
373
+ element: HTMLElement;
374
+ label: string;
375
+ tagName: string;
376
+ sourceFile: string;
377
+ compositionPath: string;
378
+ compositionSrc?: string;
379
+ isCompositionHost: boolean;
380
+ isInsideLockedComposition: boolean;
381
+ boundingBox: {
382
+ x: number;
383
+ y: number;
384
+ width: number;
385
+ height: number;
386
+ };
387
+ textContent: string | null;
388
+ dataAttributes: Record<string, string>;
389
+ inlineStyles: Record<string, string>;
390
+ computedStyles: Record<string, string>;
391
+ textFields: DomEditTextField[];
392
+ capabilities: DomEditCapabilities;
393
+ gsapAnimations?: GsapAnimation[];
336
394
  }
337
395
 
396
+ type TimelineMoveOperation = "timing" | "lane-reorder" | "track-insert";
397
+
338
398
  /**
339
399
  * Shared callback signatures for timeline editing operations.
340
400
  * Used by NLELayout, Timeline, and any component that passes through
@@ -355,16 +415,24 @@ interface TimelineDropCallbacks {
355
415
  }) => Promise<void> | void;
356
416
  }
357
417
  interface TimelineEditCallbacks {
358
- onMoveElement?: (element: TimelineElement, updates: Pick<TimelineElement, "start" | "track"> & {
359
- stackingReorder?: TimelineStackingReorderIntent | null;
360
- }) => Promise<void> | void;
418
+ onMoveElement?: (element: TimelineElement, updates: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
419
+ /** Atomic multi-clip move (single undo) for main-track ripple + track-insert.
420
+ * `coalesceKey` (drag-commit gesture id) merges the move history entry with a
421
+ * lane change's follow-up z-reorder entry into one undo step. */
422
+ onMoveElements?: (edits: Array<{
423
+ element: TimelineElement;
424
+ updates: Pick<TimelineElement, "start" | "track">;
425
+ }>, coalesceKey?: string, operation?: TimelineMoveOperation) => Promise<void> | void;
361
426
  onResizeElement?: (element: TimelineElement, updates: Pick<TimelineElement, "start" | "duration" | "playbackStart">) => Promise<void> | void;
362
- onMoveElements?: (changes: TimelineGroupMoveChange[], options?: TimelineGroupCommitOptions) => Promise<void> | void;
363
- onResizeElements?: (changes: TimelineGroupResizeChange[], options?: TimelineGroupCommitOptions) => Promise<void> | void;
364
- onPreviewMoveElements?: (changes: TimelineGroupMoveChange[]) => void;
365
- onPreviewResizeElements?: (changes: TimelineGroupResizeChange[]) => void;
427
+ onResizeElements?: (changes: Array<{
428
+ element: TimelineElement;
429
+ start: number;
430
+ duration: number;
431
+ playbackStart?: number;
432
+ }>, options?: {
433
+ coalesceKey?: string;
434
+ }) => Promise<void> | void;
366
435
  onToggleTrackHidden?: (track: number, hidden: boolean) => Promise<void> | void;
367
- onToggleElementHidden?: (elementKey: string, hidden: boolean) => Promise<void> | void;
368
436
  onBlockedEditAttempt?: (element: TimelineElement, intent: BlockedTimelineEditIntent) => void;
369
437
  onSplitElement?: (element: TimelineElement, splitTime: number) => Promise<void> | void;
370
438
  onRazorSplit?: (element: TimelineElement, splitTime: number) => Promise<void> | void;
@@ -405,7 +473,7 @@ interface TimelineTheme {
405
473
  clipRadius: string;
406
474
  }
407
475
 
408
- type TimelineEditOverrides = Pick<TimelineEditCallbacks, "onMoveElement" | "onResizeElement" | "onBlockedEditAttempt" | "onSplitElement">;
476
+ type TimelineEditOverrides = Pick<TimelineEditCallbacks, "onMoveElement" | "onMoveElements" | "onResizeElement" | "onResizeElements" | "onBlockedEditAttempt" | "onSplitElement">;
409
477
 
410
478
  interface TimelineProps extends TimelineDropCallbacks, TimelineEditOverrides {
411
479
  onSeek?: (time: number) => void;
@@ -498,48 +566,61 @@ declare function useTimelinePlayer(): {
498
566
 
499
567
  declare function formatTime(time: number): string;
500
568
 
501
- interface NLELayoutProps {
502
- projectId: string;
503
- portrait?: boolean;
504
- /** Slot for overlays rendered on top of the preview (cursors, highlights, etc.) */
505
- previewOverlay?: ReactNode;
506
- /** Slot rendered above the timeline tracks (toolbar with split, delete, zoom) */
507
- timelineToolbar?: ReactNode;
508
- /** Slot rendered below the timeline tracks */
509
- timelineFooter?: ReactNode;
510
- /** Increment to force the preview to reload (e.g., after file writes) */
511
- refreshKey?: number;
512
- /** Navigate to a specific composition path (e.g., "compositions/intro.html") */
513
- activeCompositionPath?: string | null;
514
- /** Callback to expose the iframe ref (for element picker, etc.) */
515
- onIframeRef?: (iframe: HTMLIFrameElement | null) => void;
516
- /** Callback when the viewed composition changes (drill-down/back) */
517
- onCompositionChange?: (compositionPath: string | null) => void;
518
- /** Custom clip content renderer for timeline (thumbnails, waveforms, etc.) */
519
- renderClipContent?: (element: TimelineElement, style: {
520
- clip: string;
521
- label: string;
522
- }) => ReactNode;
523
- onFileDrop?: (files: File[], placement?: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
524
- onDeleteElement?: (element: TimelineElement) => Promise<void> | void;
525
- onAssetDrop?: (assetPath: string, placement: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
526
- onBlockDrop?: (blockName: string, placement: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
527
- onPreviewBlockDrop?: (blockName: string, position: {
569
+ interface TimelineEditCallbackDeps {
570
+ handleTimelineElementMove: (element: TimelineElement, updates: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
571
+ handleTimelineElementsMove: (edits: Array<{
572
+ element: TimelineElement;
573
+ updates: Pick<TimelineElement, "start" | "track">;
574
+ }>, coalesceKey?: string, operation?: TimelineMoveOperation) => Promise<void> | void;
575
+ handleTimelineElementResize: (element: TimelineElement, updates: Pick<TimelineElement, "start" | "duration" | "playbackStart">) => Promise<void> | void;
576
+ handleTimelineGroupResize: NonNullable<TimelineEditCallbacks["onResizeElements"]>;
577
+ handleToggleTrackHidden: (track: number, hidden: boolean) => Promise<void> | void;
578
+ handleBlockedTimelineEdit: (element: TimelineElement, intent: BlockedTimelineEditIntent) => void;
579
+ handleTimelineElementSplit: (element: TimelineElement, splitTime: number) => Promise<void> | void;
580
+ handleRazorSplit: (element: TimelineElement, splitTime: number) => Promise<void> | void;
581
+ handleRazorSplitAll: (splitTime: number) => Promise<void> | void;
582
+ }
583
+
584
+ interface BlockPreviewInfo {
585
+ videoUrl?: string;
586
+ posterUrl?: string;
587
+ title: string;
588
+ }
589
+
590
+ type GestureRecordingState = "idle" | "recording" | "preview";
591
+
592
+ type RenderClipContent = (element: TimelineElement, style: {
593
+ clip: string;
594
+ label: string;
595
+ }) => ReactNode;
596
+ type TimelineDropPlacement = Pick<TimelineElement, "start" | "track">;
597
+ interface EditorShellProps extends TimelineEditCallbackDeps {
598
+ /** Left sidebar (media/library), rendered in the top row. */
599
+ left: ReactNode;
600
+ /** Right panel (inspector/design) or null when collapsed, in the top row. */
601
+ right: ReactNode;
602
+ /** Hide the whole shell (e.g. while the storyboard view is active). */
603
+ hidden?: boolean;
604
+ timelineToolbar: ReactNode;
605
+ renderClipContent: RenderClipContent;
606
+ handleTimelineElementDelete: (element: TimelineElement) => Promise<void> | void;
607
+ handleTimelineAssetDrop: (assetPath: string, placement: TimelineDropPlacement) => Promise<void> | void;
608
+ handleTimelineBlockDrop?: (blockName: string, placement: TimelineDropPlacement) => Promise<void> | void;
609
+ handlePreviewBlockDrop?: (blockName: string, position: {
528
610
  left: number;
529
611
  top: number;
530
612
  }) => Promise<void> | void;
531
- onBlockedEditAttempt?: (element: TimelineElement, intent: BlockedTimelineEditIntent) => void;
532
- onSelectTimelineElement?: (element: TimelineElement | null) => void;
533
- /** Exposes the compIdToSrc map for parent components (e.g., useRenderClipContent) */
534
- onCompIdToSrcChange?: (map: Map<string, string>) => void;
535
- /** Whether the timeline panel is visible (default: true) */
536
- timelineVisible?: boolean;
537
- /** Callback to toggle timeline visibility */
538
- onToggleTimeline?: () => void;
539
- /** Notifies parent when composition loading state changes */
540
- onCompositionLoadingChange?: (loading: boolean) => void;
613
+ handleTimelineFileDrop: (files: File[], placement?: TimelineDropPlacement) => Promise<void> | void;
614
+ setCompIdToSrc: (map: Map<string, string>) => void;
615
+ setCompositionLoading: (loading: boolean) => void;
616
+ shouldShowSelectedDomBounds: boolean;
617
+ blockPreview?: BlockPreviewInfo | null;
618
+ isGestureRecording?: boolean;
619
+ recordingState?: GestureRecordingState;
620
+ onToggleRecording?: () => void;
621
+ gestureOverlay?: ReactNode;
541
622
  }
542
- declare const NLELayout: react.NamedExoticComponent<NLELayoutProps>;
623
+ declare function EditorShell({ left, right, hidden, timelineToolbar, renderClipContent, handleTimelineElementDelete, handleTimelineAssetDrop, handleTimelineBlockDrop, handlePreviewBlockDrop, handleTimelineFileDrop, handleTimelineElementMove, handleTimelineElementsMove, handleTimelineElementResize, handleTimelineGroupResize, handleToggleTrackHidden, handleBlockedTimelineEdit, handleTimelineElementSplit, handleRazorSplit, handleRazorSplitAll, setCompIdToSrc, setCompositionLoading, shouldShowSelectedDomBounds, isGestureRecording, recordingState, onToggleRecording, blockPreview, gestureOverlay, }: EditorShellProps): react_jsx_runtime.JSX.Element;
543
624
 
544
625
  interface NLEPreviewProps {
545
626
  projectId: string;
@@ -583,59 +664,6 @@ interface SourceEditorProps {
583
664
  }
584
665
  declare const SourceEditor: react.NamedExoticComponent<SourceEditorProps>;
585
666
 
586
- interface DomEditCapabilities {
587
- canSelect: boolean;
588
- canEditStyles: boolean;
589
- /** Can take a non-destructive `clip-path: inset()` crop — broader than
590
- * canEditStyles (a sub-composition host is croppable from the parent view). */
591
- canCrop: boolean;
592
- /** Directly editable authored left/top style fields. Canvas drag uses manual edits instead. */
593
- canMove: boolean;
594
- /** Directly editable authored width/height style fields. Canvas resize uses manual edits instead. */
595
- canResize: boolean;
596
- canApplyManualOffset: boolean;
597
- canApplyManualSize: boolean;
598
- canApplyManualRotation: boolean;
599
- reasonIfDisabled?: string;
600
- }
601
- interface DomEditTextField {
602
- key: string;
603
- label: string;
604
- value: string;
605
- tagName: string;
606
- attributes: Array<{
607
- name: string;
608
- value: string;
609
- }>;
610
- inlineStyles: Record<string, string>;
611
- computedStyles: Record<string, string>;
612
- source: "self" | "child" | "text-node";
613
- sourceChildIndex?: number;
614
- }
615
- interface DomEditSelection extends PatchTarget {
616
- element: HTMLElement;
617
- label: string;
618
- tagName: string;
619
- sourceFile: string;
620
- compositionPath: string;
621
- compositionSrc?: string;
622
- isCompositionHost: boolean;
623
- isInsideLockedComposition: boolean;
624
- boundingBox: {
625
- x: number;
626
- y: number;
627
- width: number;
628
- height: number;
629
- };
630
- textContent: string | null;
631
- dataAttributes: Record<string, string>;
632
- inlineStyles: Record<string, string>;
633
- computedStyles: Record<string, string>;
634
- textFields: DomEditTextField[];
635
- capabilities: DomEditCapabilities;
636
- gsapAnimations?: GsapAnimation[];
637
- }
638
-
639
667
  interface ImportedFontAsset {
640
668
  family: string;
641
669
  path: string;
@@ -845,4 +873,4 @@ declare function findElementBlock(html: string, elementId: string): {
845
873
  isSelfClosing: boolean;
846
874
  } | null;
847
875
 
848
- export { CompositionBreadcrumb, type CompositionLevel, CompositionThumbnail, FileTree, NLELayout, 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 };
876
+ 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 };
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-BRwkMj0w.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-Dq7FEg0K.css">
8
+ <script type="module" crossorigin src="/assets/index-DfmYkU44.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-_pqzyxB1.css">
10
10
  </head>
11
11
  <body>
12
12
  <div data-hf-id="hf-aph5" id="root"></div>