@hyperframes/studio 0.8.86 → 0.8.88

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 (96) hide show
  1. package/dist/assets/hyperframes-player-w3Bbv0kd.js +473 -0
  2. package/dist/assets/{index-Cz3E_ZSj.js → index-B6PGJTzp.js} +1 -1
  3. package/dist/assets/{index-d5DKK15Q.js → index-DE6cZYR5.js} +199 -199
  4. package/dist/assets/{index-8Fgryj7q.js → index-DldknZPp.js} +1 -1
  5. package/dist/assets/{index-mzZCha_N.css → index-Dx79V1Se.css} +1 -1
  6. package/dist/{chunk-7PLTC6SV.js → chunk-KU4F7QZ3.js} +9 -1
  7. package/dist/chunk-KU4F7QZ3.js.map +1 -0
  8. package/dist/{chunk-3IOCVWB6.js → chunk-PQFEGZWM.js} +3 -1
  9. package/dist/chunk-PQFEGZWM.js.map +1 -0
  10. package/dist/{domEditingLayers-ZOOMN7CQ.js → domEditingLayers-3BAP6NNO.js} +2 -2
  11. package/dist/index.d.ts +206 -160
  12. package/dist/index.html +2 -2
  13. package/dist/index.js +2121 -1702
  14. package/dist/index.js.map +1 -1
  15. package/dist/player.js +1 -1
  16. package/dist/styles.css +1 -1
  17. package/package.json +8 -8
  18. package/src/components/TimelineHistoryButtons.dom.test.tsx +14 -3
  19. package/src/components/TimelineToolPicker.tsx +90 -0
  20. package/src/components/TimelineToolbar.tsx +2 -27
  21. package/src/components/editor/DomEditOverlay.tsx +1 -2
  22. package/src/components/editor/DomEditOverlayHover.test.tsx +5 -0
  23. package/src/components/editor/DomEditSelectionChrome.test.tsx +0 -3
  24. package/src/components/editor/DomEditSelectionChrome.tsx +3 -13
  25. package/src/components/editor/LayersPanel.test.ts +14 -0
  26. package/src/components/editor/LayersPanel.tsx +2 -2
  27. package/src/components/editor/TopologyLens.tsx +2 -2
  28. package/src/components/editor/commitPreflightHandles.test.tsx +466 -0
  29. package/src/components/editor/domEditOverlayGestures.ts +0 -1
  30. package/src/components/editor/domEditOverlayStartGesture.ts +10 -1
  31. package/src/components/editor/domEditing.test.ts +29 -0
  32. package/src/components/editor/domEditingDom.ts +1 -0
  33. package/src/components/editor/domEditingTypes.ts +1 -0
  34. package/src/components/editor/marqueeCommit.test.tsx +84 -0
  35. package/src/components/editor/marqueeCommit.ts +13 -1
  36. package/src/components/editor/useColorGradingController.test.ts +24 -0
  37. package/src/components/editor/useColorGradingController.ts +3 -2
  38. package/src/components/editor/useDomEditOverlayGestures.ts +20 -5
  39. package/src/components/nle/useCompositionStack.test.tsx +53 -0
  40. package/src/components/nle/useCompositionStack.ts +4 -8
  41. package/src/hooks/appHotkeysDispatch.ts +8 -0
  42. package/src/hooks/domStyleCommit.ts +129 -0
  43. package/src/hooks/gsapEditOutcome.ts +2 -2
  44. package/src/hooks/gsapElementMatch.ts +38 -0
  45. package/src/hooks/gsapResizeIntercept.ts +10 -31
  46. package/src/hooks/gsapResizePreflight.ts +56 -0
  47. package/src/hooks/gsapRuntimeBridge.ts +66 -26
  48. package/src/hooks/keyframeCacheAstLoad.ts +4 -1
  49. package/src/hooks/useAppHotkeys.test.ts +58 -1
  50. package/src/hooks/useCommitPreflightCapabilities.ts +147 -0
  51. package/src/hooks/useDomEditCommits.ts +17 -182
  52. package/src/hooks/useDomEditPersist.ts +225 -0
  53. package/src/hooks/useDomEditPreviewSync.test.ts +58 -0
  54. package/src/hooks/useDomEditPreviewSync.ts +2 -4
  55. package/src/hooks/useDomEditSession.test.tsx +51 -1
  56. package/src/hooks/useDomEditSession.ts +11 -2
  57. package/src/hooks/useDomEditTextCommits.ts +15 -99
  58. package/src/hooks/useDomStyleCommit.test.tsx +155 -0
  59. package/src/hooks/useDomStyleCommit.ts +74 -0
  60. package/src/hooks/useGsapAnimationFetchFallback.test.ts +12 -0
  61. package/src/hooks/useGsapAnimationFetchFallback.ts +8 -2
  62. package/src/hooks/useGsapAwareEditing.test.tsx +4 -0
  63. package/src/hooks/useGsapAwareEditing.ts +1 -1
  64. package/src/hooks/useGsapTweenCache.ts +2 -48
  65. package/src/index.ts +10 -1
  66. package/src/player/components/Timeline.audioEffects.test.tsx +80 -0
  67. package/src/player/components/Timeline.bandEscape.test.tsx +75 -0
  68. package/src/player/components/Timeline.playheadRemount.test.tsx +3 -27
  69. package/src/player/components/Timeline.showKeyframes.test.tsx +91 -0
  70. package/src/player/components/TimelineGroupHeader.tsx +21 -10
  71. package/src/player/components/TimelineGroupLaneLabels.tsx +7 -2
  72. package/src/player/components/TimelineGroupRow.test.tsx +24 -33
  73. package/src/player/components/TimelineGroupRow.tsx +4 -1
  74. package/src/player/components/TimelineLanes.tsx +5 -5
  75. package/src/player/components/TimelineTrackHeader.test.tsx +27 -0
  76. package/src/player/components/TimelineTrackHeader.tsx +6 -3
  77. package/src/player/components/TimelineTypes.ts +2 -0
  78. package/src/player/components/studioShortcuts.ts +2 -0
  79. package/src/player/components/timelineLaneProps.ts +1 -0
  80. package/src/player/components/timelineMountTestEnv.ts +29 -0
  81. package/src/player/components/useTimelineKeyframeData.ts +14 -0
  82. package/src/player/components/useTimelineLabelColumn.ts +18 -0
  83. package/src/player/components/useTimelineLaneRowIndexes.ts +6 -1
  84. package/src/player/components/useTimelineProviderState.tsx +10 -14
  85. package/src/player/components/useTimelineRangeSelection.ts +13 -12
  86. package/src/player/hooks/useShadowPreviewReload.ts +2 -0
  87. package/src/player/hooks/useTimelinePlayer.shadowReload.test.ts +191 -0
  88. package/src/player/hooks/useTimelinePlayer.ts +29 -7
  89. package/src/player/lib/runtimeProtocol.test.ts +1 -0
  90. package/src/player/sceneSwap.test.ts +95 -0
  91. package/src/player/sceneSwap.ts +53 -0
  92. package/src/player/store/playerStore.ts +16 -0
  93. package/dist/assets/hyperframes-player-Dx-2Gpsu.js +0 -473
  94. package/dist/chunk-3IOCVWB6.js.map +0 -1
  95. package/dist/chunk-7PLTC6SV.js.map +0 -1
  96. /package/dist/{domEditingLayers-ZOOMN7CQ.js.map → domEditingLayers-3BAP6NNO.js.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -461,6 +461,8 @@ interface PlayerState extends PlayerStoreSlices {
461
461
  outPoint: number | null;
462
462
  activeTool: TimelineTool;
463
463
  setActiveTool: (tool: TimelineTool) => void;
464
+ selectLeftward: () => void;
465
+ selectRightward: () => void;
464
466
  /** Tween-relative percentage of the last-clicked keyframe diamond. Operations
465
467
  * (drag, resize, rotate) target this instead of recomputing from playhead. */
466
468
  activeKeyframePct: number | null;
@@ -652,6 +654,7 @@ interface DomEditCapabilities {
652
654
  canApplyManualSize: boolean;
653
655
  canApplyManualRotation: boolean;
654
656
  reasonIfDisabled?: string;
657
+ commitCheckPending?: boolean;
655
658
  }
656
659
  interface DomEditTextField {
657
660
  key: string;
@@ -690,6 +693,20 @@ interface DomEditSelection extends PatchTarget {
690
693
  capabilities: DomEditCapabilities;
691
694
  gsapAnimations?: GsapAnimation$1[];
692
695
  }
696
+ interface DomEditContextOptions {
697
+ activeCompositionPath: string | null;
698
+ isMasterView: boolean;
699
+ preferClipAncestor?: boolean;
700
+ /** The group wrapper the user has drilled into (null = top level). Selection
701
+ * resolution treats groups as a unit unless drilled into one. */
702
+ activeGroupElement?: HTMLElement | null;
703
+ }
704
+
705
+ declare function resolveDomEditSelection(startEl: HTMLElement | null, options: DomEditContextOptions & {
706
+ projectId?: string | null;
707
+ skipSourceProbe?: boolean;
708
+ exactTarget?: boolean;
709
+ }): Promise<DomEditSelection | null>;
693
710
 
694
711
  /**
695
712
  * Agent prompt builder for HyperFrames element edit requests.
@@ -794,7 +811,7 @@ interface DomEditPatchBatchesResult {
794
811
  changed: boolean;
795
812
  }
796
813
 
797
- interface RecordEditInput$4 {
814
+ interface RecordEditInput$5 {
798
815
  label: string;
799
816
  coalesceKey?: string;
800
817
  files: Record<string, {
@@ -818,7 +835,7 @@ interface UseTimelineEditingOptions {
818
835
  showToast: (message: string, tone?: "error" | "info") => void;
819
836
  writeProjectFile: (path: string, content: string, expectedContent?: string) => Promise<void>;
820
837
  observeProjectFileVersion?: (path: string, version: string | null) => void;
821
- recordEdit: (input: RecordEditInput$4) => Promise<void>;
838
+ recordEdit: (input: RecordEditInput$5) => Promise<void>;
822
839
  reloadPreview: () => void;
823
840
  previewIframeRef: RefObject<HTMLIFrameElement | null>;
824
841
  pendingTimelineEditPathRef: MutableRefObject<Set<string>>;
@@ -1137,6 +1154,8 @@ interface TimelineProps extends TimelineDropCallbacks, TimelineEditOverrides, Ti
1137
1154
  onDuplicateClip?: () => Promise<boolean>;
1138
1155
  canPasteClip?: () => boolean;
1139
1156
  theme?: Partial<TimelineTheme>;
1157
+ showAudioEffects?: boolean;
1158
+ showKeyframes?: boolean;
1140
1159
  }
1141
1160
 
1142
1161
  interface TimelineEmptyStateProps {
@@ -1390,6 +1409,7 @@ interface TimelineLaneBaseProps {
1390
1409
  contentGutter: number;
1391
1410
  trackContentWidth: number;
1392
1411
  theme: TimelineTheme;
1412
+ showAudioEffects?: boolean;
1393
1413
  displayTrackOrder: number[];
1394
1414
  rowHeights: readonly number[];
1395
1415
  rowGeometry: TimelineRowGeometry;
@@ -2470,7 +2490,7 @@ declare function findElementBlock(html: string, elementId: string): {
2470
2490
  isSelfClosing: boolean;
2471
2491
  } | null;
2472
2492
 
2473
- interface RecordEditInput$3 {
2493
+ interface RecordEditInput$4 {
2474
2494
  label: string;
2475
2495
  coalesceKey?: string;
2476
2496
  coalesceMs?: number;
@@ -2516,7 +2536,7 @@ declare function usePersistentEditHistory({ projectId }: UsePersistentEditHistor
2516
2536
  createdAt: number;
2517
2537
  }[];
2518
2538
  };
2519
- recordEdit: ({ label, coalesceKey, coalesceMs, files }: RecordEditInput$3) => Promise<void>;
2539
+ recordEdit: ({ label, coalesceKey, coalesceMs, files }: RecordEditInput$4) => Promise<void>;
2520
2540
  undo: (callbacks: ApplyCallbacks) => Promise<ApplyResult>;
2521
2541
  redo: (callbacks: ApplyCallbacks) => Promise<ApplyResult>;
2522
2542
  };
@@ -2754,7 +2774,7 @@ interface AudioMeterStripProps {
2754
2774
  }
2755
2775
  declare const AudioMeterStrip: react.NamedExoticComponent<AudioMeterStripProps>;
2756
2776
 
2757
- interface RecordEditInput$2 {
2777
+ interface RecordEditInput$3 {
2758
2778
  label: string;
2759
2779
  coalesceKey?: string;
2760
2780
  files: Record<string, {
@@ -2768,7 +2788,7 @@ interface UseClipboardOptions {
2768
2788
  domEditSelectionRef: React.MutableRefObject<DomEditSelection | null>;
2769
2789
  showToast: (message: string, tone?: "error" | "info") => void;
2770
2790
  writeProjectFile: (path: string, content: string) => Promise<void>;
2771
- recordEdit: (input: RecordEditInput$2) => Promise<void>;
2791
+ recordEdit: (input: RecordEditInput$3) => Promise<void>;
2772
2792
  reloadPreview: () => void;
2773
2793
  handleTimelineElementsDelete: (elements: TimelineElement[]) => Promise<void>;
2774
2794
  handleDomEditElementDelete: (selection: DomEditSelection) => Promise<void>;
@@ -2791,131 +2811,24 @@ interface InlineTextEditCommit {
2791
2811
  previousHtml: string;
2792
2812
  }
2793
2813
 
2794
- declare const SNAP_THRESHOLD_PX = 6;
2795
- /** Whether a move of this size has travelled far enough for snapping to apply. */
2796
- declare function snapEngagedForTravel(dx: number, dy: number): boolean;
2797
- interface SnapEdge {
2798
- position: number;
2799
- source: "grid";
2800
- id: string;
2801
- }
2802
- interface SnapTarget {
2803
- left: number;
2804
- top: number;
2805
- right: number;
2806
- bottom: number;
2807
- centerX: number;
2808
- centerY: number;
2809
- id: string;
2810
- }
2811
- interface SnapGuide {
2812
- axis: "x" | "y";
2813
- position: number;
2814
- /** Extent of the guide line (min of involved elements). */
2815
- from: number;
2816
- /** Extent of the guide line (max of involved elements). */
2817
- to: number;
2818
- }
2819
- interface SpacingGuide {
2820
- axis: "x" | "y";
2821
- /** Position of the gap (start of gap). */
2822
- position: number;
2823
- /** Size of the gap in pixels. */
2824
- size: number;
2825
- /** Extent for rendering the indicator. */
2826
- from: number;
2827
- /** Extent for rendering the indicator. */
2828
- to: number;
2829
- }
2830
- interface SnapResult {
2831
- dx: number;
2832
- dy: number;
2833
- guides: SnapGuide[];
2834
- spacingGuides: SpacingGuide[];
2835
- }
2836
- interface Rect {
2837
- left: number;
2838
- top: number;
2839
- width: number;
2840
- height: number;
2841
- }
2842
- /**
2843
- * Convert overlay rects to snap targets with precomputed edges & centers.
2844
- */
2845
- declare function extractSnapTargets(entries: Array<{
2846
- rect: Rect;
2847
- id: string;
2848
- }>): SnapTarget[];
2849
2814
  /**
2850
- * Create a snap target from the composition/overlay boundary.
2851
- */
2852
- declare function buildCompositionSnapTarget(rect: Rect): SnapTarget;
2853
- /**
2854
- * Generate grid-line snap edges.
2855
- * `gridSpacing` is in composition pixels; `scale` converts to overlay pixels.
2856
- * X edges are vertical grid lines; Y edges are horizontal grid lines.
2815
+ * Why a DOM edit commit did not change the file.
2816
+ *
2817
+ * `runDomEditCommit` resolves on persist failure by design (see its contract
2818
+ * above), so a caller cannot learn whether the write landed by awaiting it — a
2819
+ * failed persist and a successful one are indistinguishable. Capture and apply
2820
+ * bugs still reject. The human path does not need to ask about handled persist
2821
+ * failures, because `onError` already put a toast on screen. A programmatic
2822
+ * caller has no screen, so it has to be told.
2857
2823
  */
2858
- declare function buildGridSnapEdges(compositionRect: Rect, gridSpacing: number, scale: number): {
2859
- x: SnapEdge[];
2860
- y: SnapEdge[];
2824
+ type DomEditCommitDeclineReason = "no-project" | "no-selection" | "geometry-property" | "styles-not-editable" | "not-text-editable" | "preview-stale" | "persist-failed";
2825
+ type DomEditCommitOutcome = {
2826
+ ok: true;
2827
+ persistence?: DomEditPersistOutcome;
2828
+ } | {
2829
+ ok: false;
2830
+ reason: DomEditCommitDeclineReason;
2861
2831
  };
2862
- declare function resolveSnapAdjustment(input: {
2863
- movingRect: Rect;
2864
- proposedDx: number;
2865
- proposedDy: number;
2866
- targets: SnapTarget[];
2867
- gridEdges?: {
2868
- x: SnapEdge[];
2869
- y: SnapEdge[];
2870
- };
2871
- threshold: number;
2872
- disabled: boolean;
2873
- /** Set when the gesture has not travelled far enough for snapping yet. */
2874
- disabledForTravel?: boolean;
2875
- }): SnapResult;
2876
- /**
2877
- * Full-length guide line spanning the composition: a vertical line (axis "x")
2878
- * runs the composition's height at the snapped x position; a horizontal line
2879
- * (axis "y") runs the composition's width. `composition` is the composition
2880
- * rect in overlay space — guide positions are already overlay-space, so the
2881
- * line must be offset by the composition's left/top (the canvas is usually
2882
- * letterboxed inside the overlay).
2883
- */
2884
- declare function resolveGuideLineRect(guide: SnapGuide, composition: Rect): Rect;
2885
- declare function resolveEquidistanceGuides(input: {
2886
- movingRect: Rect;
2887
- targets: SnapTarget[];
2888
- threshold: number;
2889
- }): SpacingGuide[];
2890
-
2891
- interface SnapContext {
2892
- targets: SnapTarget[];
2893
- compositionTarget: SnapTarget | null;
2894
- gridEdges: {
2895
- x: SnapEdge[];
2896
- y: SnapEdge[];
2897
- } | null;
2898
- snapEnabled: boolean;
2899
- }
2900
- declare function collectSnapContext(input: {
2901
- overlayEl: HTMLDivElement;
2902
- iframe: HTMLIFrameElement;
2903
- excludeElements: Set<HTMLElement>;
2904
- }): SnapContext;
2905
-
2906
- interface SnapGuidesState {
2907
- guides: SnapGuide[];
2908
- spacingGuides: SpacingGuide[];
2909
- }
2910
- interface SnapGuideOverlayProps {
2911
- snapGuidesRef: RefObject<SnapGuidesState | null>;
2912
- /** Composition rect in overlay space — guide lines span exactly this rect. */
2913
- compositionLeft: number;
2914
- compositionTop: number;
2915
- compositionWidth: number;
2916
- compositionHeight: number;
2917
- }
2918
- declare const SnapGuideOverlay: react.NamedExoticComponent<SnapGuideOverlayProps>;
2919
2832
 
2920
2833
  interface ApplyDomSelectionOptions {
2921
2834
  revealPanel?: boolean;
@@ -2950,33 +2863,6 @@ interface PreviewMouseDownOptions {
2950
2863
  hoverSelection?: DomEditSelection | null;
2951
2864
  }
2952
2865
 
2953
- interface DomEditGroupPathOffsetCommit {
2954
- selection: DomEditSelection;
2955
- next: {
2956
- x: number;
2957
- y: number;
2958
- };
2959
- }
2960
-
2961
- /**
2962
- * Why a DOM edit commit did not change the file.
2963
- *
2964
- * `runDomEditCommit` resolves on persist failure by design (see its contract
2965
- * above), so a caller cannot learn whether the write landed by awaiting it — a
2966
- * failed persist and a successful one are indistinguishable. Capture and apply
2967
- * bugs still reject. The human path does not need to ask about handled persist
2968
- * failures, because `onError` already put a toast on screen. A programmatic
2969
- * caller has no screen, so it has to be told.
2970
- */
2971
- type DomEditCommitDeclineReason = "no-project" | "no-selection" | "geometry-property" | "styles-not-editable" | "not-text-editable" | "preview-stale" | "persist-failed";
2972
- type DomEditCommitOutcome = {
2973
- ok: true;
2974
- persistence?: DomEditPersistOutcome;
2975
- } | {
2976
- ok: false;
2977
- reason: DomEditCommitDeclineReason;
2978
- };
2979
-
2980
2866
  /**
2981
2867
  * Which elements a delete acts on.
2982
2868
  *
@@ -2986,7 +2872,7 @@ type DomEditCommitOutcome = {
2986
2872
 
2987
2873
  /** One entry in the studio's edit history, as `useDomEditSession`'s caller
2988
2874
  * supplies it. */
2989
- interface RecordEditInput$1 {
2875
+ interface RecordEditInput$2 {
2990
2876
  label: string;
2991
2877
  coalesceKey?: string;
2992
2878
  files: Record<string, {
@@ -3005,7 +2891,7 @@ interface UseDomEditSessionParams extends DomEditTimelineParams {
3005
2891
  writeProjectFile: (path: string, content: string, expectedContent?: string) => Promise<void>;
3006
2892
  updateEditingFileContent: (path: string, content: string) => void;
3007
2893
  editHistory: {
3008
- recordEdit: (entry: RecordEditInput$1) => Promise<void>;
2894
+ recordEdit: (entry: RecordEditInput$2) => Promise<void>;
3009
2895
  };
3010
2896
  fileTree: string[];
3011
2897
  importedFontAssetsRef: React.MutableRefObject<ImportedFontAsset[]>;
@@ -3196,7 +3082,7 @@ interface HistoryPreviewRestore {
3196
3082
  paths?: string[];
3197
3083
  files?: Record<string, UndoRestoreFile>;
3198
3084
  }
3199
- interface RecordEditInput {
3085
+ interface RecordEditInput$1 {
3200
3086
  label: string;
3201
3087
  coalesceKey?: string;
3202
3088
  files: Record<string, {
@@ -3208,7 +3094,7 @@ interface UsePreviewPersistenceParams {
3208
3094
  showToast: (message: string, tone?: "error" | "info") => void;
3209
3095
  readOptionalProjectFile: (path: string) => Promise<string>;
3210
3096
  writeProjectFile: (path: string, content: string) => Promise<void>;
3211
- recordEdit: (entry: RecordEditInput) => Promise<void>;
3097
+ recordEdit: (entry: RecordEditInput$1) => Promise<void>;
3212
3098
  previewIframeRef: React.MutableRefObject<HTMLIFrameElement | null>;
3213
3099
  activeCompPathRef: React.MutableRefObject<string | null>;
3214
3100
  /** Called to reload the preview after undo/redo or external file changes. */
@@ -3251,6 +3137,140 @@ declare function PreviewReadOnlyProvider({ readOnly, reason, children, }: {
3251
3137
  children: ReactNode;
3252
3138
  }): react_jsx_runtime.JSX.Element;
3253
3139
 
3140
+ declare const SNAP_THRESHOLD_PX = 6;
3141
+ /** Whether a move of this size has travelled far enough for snapping to apply. */
3142
+ declare function snapEngagedForTravel(dx: number, dy: number): boolean;
3143
+ interface SnapEdge {
3144
+ position: number;
3145
+ source: "grid";
3146
+ id: string;
3147
+ }
3148
+ interface SnapTarget {
3149
+ left: number;
3150
+ top: number;
3151
+ right: number;
3152
+ bottom: number;
3153
+ centerX: number;
3154
+ centerY: number;
3155
+ id: string;
3156
+ }
3157
+ interface SnapGuide {
3158
+ axis: "x" | "y";
3159
+ position: number;
3160
+ /** Extent of the guide line (min of involved elements). */
3161
+ from: number;
3162
+ /** Extent of the guide line (max of involved elements). */
3163
+ to: number;
3164
+ }
3165
+ interface SpacingGuide {
3166
+ axis: "x" | "y";
3167
+ /** Position of the gap (start of gap). */
3168
+ position: number;
3169
+ /** Size of the gap in pixels. */
3170
+ size: number;
3171
+ /** Extent for rendering the indicator. */
3172
+ from: number;
3173
+ /** Extent for rendering the indicator. */
3174
+ to: number;
3175
+ }
3176
+ interface SnapResult {
3177
+ dx: number;
3178
+ dy: number;
3179
+ guides: SnapGuide[];
3180
+ spacingGuides: SpacingGuide[];
3181
+ }
3182
+ interface Rect {
3183
+ left: number;
3184
+ top: number;
3185
+ width: number;
3186
+ height: number;
3187
+ }
3188
+ /**
3189
+ * Convert overlay rects to snap targets with precomputed edges & centers.
3190
+ */
3191
+ declare function extractSnapTargets(entries: Array<{
3192
+ rect: Rect;
3193
+ id: string;
3194
+ }>): SnapTarget[];
3195
+ /**
3196
+ * Create a snap target from the composition/overlay boundary.
3197
+ */
3198
+ declare function buildCompositionSnapTarget(rect: Rect): SnapTarget;
3199
+ /**
3200
+ * Generate grid-line snap edges.
3201
+ * `gridSpacing` is in composition pixels; `scale` converts to overlay pixels.
3202
+ * X edges are vertical grid lines; Y edges are horizontal grid lines.
3203
+ */
3204
+ declare function buildGridSnapEdges(compositionRect: Rect, gridSpacing: number, scale: number): {
3205
+ x: SnapEdge[];
3206
+ y: SnapEdge[];
3207
+ };
3208
+ declare function resolveSnapAdjustment(input: {
3209
+ movingRect: Rect;
3210
+ proposedDx: number;
3211
+ proposedDy: number;
3212
+ targets: SnapTarget[];
3213
+ gridEdges?: {
3214
+ x: SnapEdge[];
3215
+ y: SnapEdge[];
3216
+ };
3217
+ threshold: number;
3218
+ disabled: boolean;
3219
+ /** Set when the gesture has not travelled far enough for snapping yet. */
3220
+ disabledForTravel?: boolean;
3221
+ }): SnapResult;
3222
+ /**
3223
+ * Full-length guide line spanning the composition: a vertical line (axis "x")
3224
+ * runs the composition's height at the snapped x position; a horizontal line
3225
+ * (axis "y") runs the composition's width. `composition` is the composition
3226
+ * rect in overlay space — guide positions are already overlay-space, so the
3227
+ * line must be offset by the composition's left/top (the canvas is usually
3228
+ * letterboxed inside the overlay).
3229
+ */
3230
+ declare function resolveGuideLineRect(guide: SnapGuide, composition: Rect): Rect;
3231
+ declare function resolveEquidistanceGuides(input: {
3232
+ movingRect: Rect;
3233
+ targets: SnapTarget[];
3234
+ threshold: number;
3235
+ }): SpacingGuide[];
3236
+
3237
+ interface SnapContext {
3238
+ targets: SnapTarget[];
3239
+ compositionTarget: SnapTarget | null;
3240
+ gridEdges: {
3241
+ x: SnapEdge[];
3242
+ y: SnapEdge[];
3243
+ } | null;
3244
+ snapEnabled: boolean;
3245
+ }
3246
+ declare function collectSnapContext(input: {
3247
+ overlayEl: HTMLDivElement;
3248
+ iframe: HTMLIFrameElement;
3249
+ excludeElements: Set<HTMLElement>;
3250
+ }): SnapContext;
3251
+
3252
+ interface SnapGuidesState {
3253
+ guides: SnapGuide[];
3254
+ spacingGuides: SpacingGuide[];
3255
+ }
3256
+ interface SnapGuideOverlayProps {
3257
+ snapGuidesRef: RefObject<SnapGuidesState | null>;
3258
+ /** Composition rect in overlay space — guide lines span exactly this rect. */
3259
+ compositionLeft: number;
3260
+ compositionTop: number;
3261
+ compositionWidth: number;
3262
+ compositionHeight: number;
3263
+ }
3264
+ declare const SnapGuideOverlay: react.NamedExoticComponent<SnapGuideOverlayProps>;
3265
+
3266
+ interface DomEditGroupPathOffsetCommit {
3267
+ selection: DomEditSelection;
3268
+ next: {
3269
+ x: number;
3270
+ y: number;
3271
+ };
3272
+ }
3273
+
3254
3274
  /**
3255
3275
  * Pure z-order helpers for the canvas right-click context menu.
3256
3276
  *
@@ -3375,6 +3395,32 @@ interface ConnectedDomEditOverlayProps extends HostInputProps {
3375
3395
  }
3376
3396
  declare function ConnectedDomEditOverlay({ activeCompositionPath, showHoverSelection, shouldShowSelectedDomBounds, isGestureRecording, canvasInput, onTextEditingChange, onSelectionBoxClick, }: ConnectedDomEditOverlayProps): react_jsx_runtime.JSX.Element;
3377
3397
 
3398
+ interface RecordEditInput {
3399
+ label: string;
3400
+ coalesceKey?: string;
3401
+ coalesceMs?: number;
3402
+ files: Record<string, {
3403
+ before: string;
3404
+ after: string;
3405
+ }>;
3406
+ }
3407
+
3408
+ interface UseDomStyleCommitOptions {
3409
+ projectId: string | null;
3410
+ /** The preview the host already runs: the style applies there live, and it reseeks after a save. */
3411
+ iframeRef: React.MutableRefObject<HTMLIFrameElement | null>;
3412
+ /** The same function objects the host gives the timeline, so there is one writer and one undo list. */
3413
+ writeProjectFile: (path: string, content: string, expectedContent?: string) => Promise<void>;
3414
+ recordEdit: (entry: RecordEditInput) => Promise<void>;
3415
+ activeCompPath?: string | null;
3416
+ showToast?: (message: string, tone?: "error" | "info") => void;
3417
+ }
3418
+ /** Saves style edits on a selection through Studio's own style commit, for a host without the editor. */
3419
+ declare function useDomStyleCommit({ projectId, iframeRef, writeProjectFile, recordEdit, activeCompPath, showToast, }: UseDomStyleCommitOptions): {
3420
+ commitStyle: (selection: DomEditSelection, styles: Record<string, string>) => Promise<DomEditCommitOutcome>;
3421
+ waitForPendingSaves: () => Promise<DomEditSaveDrainResult>;
3422
+ };
3423
+
3378
3424
  interface MarqueeGesturesDeps<T = DomEditSelection> {
3379
3425
  iframeRef: React.RefObject<HTMLIFrameElement | null>;
3380
3426
  overlayRef: React.RefObject<HTMLDivElement | null>;
@@ -3417,4 +3463,4 @@ interface MarqueeOverlayProps {
3417
3463
  */
3418
3464
  declare function MarqueeOverlay({ candidateRects, marqueeRect }: MarqueeOverlayProps): react_jsx_runtime.JSX.Element;
3419
3465
 
3420
- export { type AgentModalAnchorPoint, type AgentPromptElementInfo, AskAgentModal, type AskAgentModalProps, AudioMeterStrip, type AudioMeterStripProps, AudioWaveform, type AudioWaveformProps, type BlockedTimelineEditIntent, type CanEditTimelineElement, CompositionBreadcrumb, type CompositionDimensions, type CompositionLevel, CompositionThumbnail, ConnectedDomEditOverlay, type ConnectedDomEditOverlayProps, DEFAULT_SHORTCUT_SECTIONS, type DomEditCapabilities, DomEditProvider, type DomEditSelection, type EditHistoryHandle, EditorShell, type EditorShellProps, type ExternalFileChangeBlockedState, type ExternalFileChangeCoordinatorHandle, ExternalFileConflictBanner, type FfmpegStatus, FileTree, GridOverlay, ImageThumbnail, type ImageThumbnailProps, type MarqueeGestures, type MarqueeGesturesDeps, MarqueeOverlay, type MarqueeOverlayProps, type Rect$1 as MarqueeRect, NLEPreview, type PatchOperation, type PersistedRenderSettings, type PickedElement, PlayerControls, type PlayerHandle, type PlayerHandleElement, type PlayerHandleListener, type PlayerHandleTimeListener, type DomEditCompositionRect as PreviewCompositionRect, PreviewGuides, PreviewOverlayProvider, type PreviewOverlayProviderProps, PreviewReadOnlyProvider, type PreviewSnapPreferences, PropertyPanel, type RenderJob, RenderQueue, type RenderQueueProps, type ResolutionPreset, SNAP_THRESHOLD_PX, type ShortcutHint, type ShortcutSection, type SnapContext, type SnapEdge, type SnapGuide, SnapGuideOverlay, type SnapGuideOverlayProps, type SnapGuidesState, type Rect as SnapRect, type SnapResult, type SnapTarget, SnapToolbar, SourceEditor, type SpacingGuide, type StartRenderOptions, StudioApp, StudioFileConflictError, type StudioPendingEditsDrainResult, type ThumbnailPriority, Timeline, TimelineClipMenu, type TimelineClipRenderContext, type TimelineEditCallbacks, type TimelineEditOutcome, type TimelineEditPermission, TimelineEditPopover, TimelineEditProvider, type TimelineElement, TimelineEmptyStatePart, TimelineFrame, TimelineGapMenu, TimelineHistoryButtons, type TimelineHistoryButtonsProps, TimelineKeyframeMenu, TimelineLanes, TimelineOverlays, TimelinePane, type TimelinePaneProps, TimelinePlayhead, TimelineProvider, TimelineRazorGuide, TimelineRuler, TimelineShortcutHint, type TimelineTheme, type TimelineTimeRange$1 as TimelineTimeRange, TimelineToolbar, type TimelineToolbarProps, type TimelineZIndexReorderCommit, type UseClipboardOptions, type UseDomEditSessionParams, type UseEditHistoryActionsOptions, type UsePersistentEditHistoryOptions, type UsePreviewPersistenceParams, type UseProjectFileWriterOptions, type UseRenderClipContentOptions, type UseTimelineEditingOptions, VideoThumbnail, applyPatch, buildCompositionSnapTarget, buildGridSnapEdges, buildPickerAgentContextPreview, buildPickerAgentPrompt, collectSnapContext, extractSnapTargets, findElementBlock, flushStudioPendingEdits, formatTime, getPersistedRenderSettings, liveTime, mergeStyleIntoTag, parseStyleString, persistRenderSettings, resolveEquidistanceGuides, resolveGuideLineRect, resolveIframe, resolveSnapAdjustment, resolveSourceFile, snapEngagedForTravel, useClipboard, useCompositionStack, useDomEditSelectionContext, useDomEditSession, useEditHistoryActions, useElementPicker, useMarqueeGestures, usePersistentEditHistory, usePlayerHandle, usePlayerStore, usePreviewCompositionRect, usePreviewGuidesStore, usePreviewOverlayContext, usePreviewPersistence, useProjectFileWriter, useRenderClipContent, useRenderQueue, useTimelineContext, useTimelineEditing, useTimelinePlayer };
3466
+ export { type AgentModalAnchorPoint, type AgentPromptElementInfo, AskAgentModal, type AskAgentModalProps, AudioMeterStrip, type AudioMeterStripProps, AudioWaveform, type AudioWaveformProps, type BlockedTimelineEditIntent, type CanEditTimelineElement, CompositionBreadcrumb, type CompositionDimensions, type CompositionLevel, CompositionThumbnail, ConnectedDomEditOverlay, type ConnectedDomEditOverlayProps, DEFAULT_SHORTCUT_SECTIONS, type DomEditCapabilities, type DomEditCommitDeclineReason, type DomEditCommitOutcome, type DomEditGroupPathOffsetCommit, DomEditOverlay, type DomEditOverlayProps, DomEditProvider, type DomEditSelection, type EditHistoryHandle, EditorShell, type EditorShellProps, type ExternalFileChangeBlockedState, type ExternalFileChangeCoordinatorHandle, ExternalFileConflictBanner, type FfmpegStatus, FileTree, GridOverlay, ImageThumbnail, type ImageThumbnailProps, type MarqueeGestures, type MarqueeGesturesDeps, MarqueeOverlay, type MarqueeOverlayProps, type Rect$1 as MarqueeRect, NLEPreview, type PatchOperation, type PersistedRenderSettings, type PickedElement, PlayerControls, type PlayerHandle, type PlayerHandleElement, type PlayerHandleListener, type PlayerHandleTimeListener, type DomEditCompositionRect as PreviewCompositionRect, PreviewGuides, PreviewOverlayProvider, type PreviewOverlayProviderProps, PreviewReadOnlyProvider, type PreviewSnapPreferences, PropertyPanel, type RenderJob, RenderQueue, type RenderQueueProps, type ResolutionPreset, SNAP_THRESHOLD_PX, type ShortcutHint, type ShortcutSection, type SnapContext, type SnapEdge, type SnapGuide, SnapGuideOverlay, type SnapGuideOverlayProps, type SnapGuidesState, type Rect as SnapRect, type SnapResult, type SnapTarget, SnapToolbar, SourceEditor, type SpacingGuide, type StartRenderOptions, StudioApp, StudioFileConflictError, type StudioPendingEditsDrainResult, type ThumbnailPriority, Timeline, TimelineClipMenu, type TimelineClipRenderContext, type TimelineEditCallbacks, type TimelineEditOutcome, type TimelineEditPermission, TimelineEditPopover, TimelineEditProvider, type TimelineElement, TimelineEmptyStatePart, TimelineFrame, TimelineGapMenu, TimelineHistoryButtons, type TimelineHistoryButtonsProps, TimelineKeyframeMenu, TimelineLanes, TimelineOverlays, TimelinePane, type TimelinePaneProps, TimelinePlayhead, TimelineProvider, TimelineRazorGuide, TimelineRuler, TimelineShortcutHint, type TimelineTheme, type TimelineTimeRange$1 as TimelineTimeRange, TimelineToolbar, type TimelineToolbarProps, type TimelineZIndexReorderCommit, type UseClipboardOptions, type UseDomEditSessionParams, type UseDomStyleCommitOptions, type UseEditHistoryActionsOptions, type UsePersistentEditHistoryOptions, type UsePreviewPersistenceParams, type UseProjectFileWriterOptions, type UseRenderClipContentOptions, type UseTimelineEditingOptions, VideoThumbnail, applyPatch, buildCompositionSnapTarget, buildGridSnapEdges, buildPickerAgentContextPreview, buildPickerAgentPrompt, collectSnapContext, extractSnapTargets, findElementBlock, flushStudioPendingEdits, formatTime, getPersistedRenderSettings, liveTime, mergeStyleIntoTag, parseStyleString, persistRenderSettings, resolveDomEditSelection, resolveEquidistanceGuides, resolveGuideLineRect, resolveIframe, resolveSnapAdjustment, resolveSourceFile, snapEngagedForTravel, useClipboard, useCompositionStack, useDomEditSelectionContext, useDomEditSession, useDomStyleCommit, useEditHistoryActions, useElementPicker, useMarqueeGestures, usePersistentEditHistory, usePlayerHandle, usePlayerStore, usePreviewCompositionRect, usePreviewGuidesStore, usePreviewOverlayContext, usePreviewPersistence, useProjectFileWriter, useRenderClipContent, useRenderQueue, useTimelineContext, useTimelineEditing, 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-d5DKK15Q.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-mzZCha_N.css">
8
+ <script type="module" crossorigin src="/assets/index-DE6cZYR5.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-Dx79V1Se.css">
10
10
  </head>
11
11
  <body>
12
12
  <div data-hf-id="hf-aph5" id="root"></div>