hyperframes 0.8.53 → 0.8.54

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-HfP3sap2.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-DPUJoO8n.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,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ButtonHTMLAttributes, ReactNode, ElementType, ComponentPropsWithoutRef, ReactElement, RefObject } from 'react';
2
+ import { ButtonHTMLAttributes, ReactNode, ElementType, ComponentPropsWithoutRef, ReactElement, RefObject, MutableRefObject } from 'react';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { Tabs as Tabs$1 } from '@base-ui/react/tabs';
5
5
  import * as node_modules_cn_dist_types from 'node_modules/cn/dist/types';
@@ -13,6 +13,7 @@ import { StoreApi } from 'zustand';
13
13
  import { MusicBeatAnalysis } from '@hyperframes/core/beats';
14
14
  import { GsapAnimation as GsapAnimation$1, ArcPathSegment } from '@hyperframes/parsers/gsap-parser';
15
15
  import { CanvasResolution } from '@hyperframes/parsers';
16
+ import { Composition } from '@hyperframes/sdk';
16
17
 
17
18
  type ButtonVariant = "primary" | "secondary" | "danger" | "ghost";
18
19
  type ButtonSize = "sm" | "md" | "lg";
@@ -44,6 +45,8 @@ declare const buttonVariants: Record<ButtonVariant, string>;
44
45
  declare const buttonSizes: Record<ButtonSize, string>;
45
46
  declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
46
47
 
48
+ declare function HyperframesLogo(): react_jsx_runtime.JSX.Element;
49
+
47
50
  interface IconButtonProps extends ButtonBaseProps {
48
51
  icon: ReactNode;
49
52
  "aria-label": string;
@@ -76,6 +79,20 @@ declare function Tab({ value, className, ...props }: TabProps): react_jsx_runtim
76
79
  /** The panel for one tab. Base UI wires `aria-labelledby` back to its tab. */
77
80
  declare function TabPanel({ className, ...props }: StyledProps$1<typeof Tabs$1.Panel>): react_jsx_runtime.JSX.Element;
78
81
 
82
+ interface HyperframesLoaderProps {
83
+ /** Status text shown below the mark. */
84
+ title: string;
85
+ /** Optional secondary detail line. */
86
+ detail?: string;
87
+ /** Optional monospace third line for IDs, counts, or percentages. */
88
+ mono?: string;
89
+ /** Pixel size of the mark itself; status text scales independently. */
90
+ size?: number;
91
+ /** Optional normalized progress value from 0 to 1. */
92
+ progress?: number;
93
+ }
94
+ declare function HyperframesLoader({ title, detail, mono, size, progress, }: HyperframesLoaderProps): react_jsx_runtime.JSX.Element;
95
+
79
96
  interface TooltipProps {
80
97
  label: string;
81
98
  /** A single element, wrapped in a box-less span so a disabled one still gets hover. */
@@ -88,8 +105,6 @@ interface TooltipProps {
88
105
  }
89
106
  declare function Tooltip({ label, children, delay, side }: TooltipProps): react_jsx_runtime.JSX.Element;
90
107
 
91
- declare function HyperframesLogo(): react_jsx_runtime.JSX.Element;
92
-
93
108
  /**
94
109
  * Studio's tailwind-merge config: teaches it the two scales `theme.css`
95
110
  * invents (`text-step-*`, `ctl`/`ctl-sm`/`ctl-lg`) so overrides replace, not stack.
@@ -543,11 +558,14 @@ interface PlaybackReadinessSlice {
543
558
  }
544
559
  declare function createPlaybackReadinessSlice(set: StoreApi<PlaybackReadinessSlice>["setState"]): PlaybackReadinessSlice;
545
560
 
546
- type TimeListener = (time: number) => void;
547
- declare const liveTime: {
548
- notify: (time: number) => void;
549
- subscribe: (listener: TimeListener) => () => boolean;
550
- };
561
+ interface TimelineTimeRange {
562
+ t0: number;
563
+ t1: number;
564
+ }
565
+ interface RangeSelectionSlice {
566
+ /** Shift-drag ruler range in seconds, normalized so t0 <= t1. */
567
+ rangeSelection: TimelineTimeRange | null;
568
+ }
551
569
 
552
570
  /**
553
571
  * One row in the timeline: a clip as Studio needs it, translated from the
@@ -668,12 +686,18 @@ interface SubCompositionHostState {
668
686
  automation?: string;
669
687
  }
670
688
 
689
+ type TimeListener = (time: number) => void;
690
+ declare const liveTime: {
691
+ notify: (time: number) => void;
692
+ subscribe: (listener: TimeListener) => () => boolean;
693
+ };
694
+
671
695
  type ZoomMode = "fit" | "manual";
672
696
  type TimelineTool = "select" | "razor";
673
697
  interface SelectElementOptions {
674
698
  preserveSet?: boolean;
675
699
  }
676
- type PlayerStoreSlices = KeyframeSlice & AutomationSelectionSlice & ThumbnailSlice & EditingModeSlice & ReturnType<typeof createPlaybackReadinessSlice>;
700
+ type PlayerStoreSlices = KeyframeSlice & AutomationSelectionSlice & ThumbnailSlice & EditingModeSlice & ReturnType<typeof createPlaybackReadinessSlice> & RangeSelectionSlice;
677
701
  interface PlayerState extends PlayerStoreSlices {
678
702
  isPlaying: boolean;
679
703
  currentTime: number;
@@ -978,8 +1002,179 @@ declare function buildPickerAgentPrompt({ selection, userInstruction, }: {
978
1002
  }): string;
979
1003
  declare function buildPickerAgentContextPreview(selection: HyperframePickerElementInfo | null): string;
980
1004
 
1005
+ type EditHistoryKind = "manual" | "motion" | "timeline" | "source";
1006
+ interface EditHistoryFileSnapshot {
1007
+ before: string;
1008
+ after: string;
1009
+ beforeHash: string;
1010
+ afterHash: string;
1011
+ }
1012
+ interface EditHistoryEntry {
1013
+ id: string;
1014
+ projectId: string;
1015
+ label: string;
1016
+ kind: EditHistoryKind;
1017
+ coalesceKey?: string;
1018
+ /** Per-entry coalesce window override (ms). Falls back to the reducer default. */
1019
+ coalesceMs?: number;
1020
+ createdAt: number;
1021
+ files: Record<string, EditHistoryFileSnapshot>;
1022
+ }
1023
+ interface EditHistoryState {
1024
+ version: 1;
1025
+ updatedAt: number;
1026
+ undo: EditHistoryEntry[];
1027
+ redo: EditHistoryEntry[];
1028
+ }
1029
+ interface BuildEditHistoryEntryInput {
1030
+ id: string;
1031
+ projectId: string;
1032
+ label: string;
1033
+ kind?: EditHistoryKind;
1034
+ coalesceKey?: string;
1035
+ coalesceMs?: number;
1036
+ now: number;
1037
+ files: Record<string, {
1038
+ before: string;
1039
+ after: string;
1040
+ }>;
1041
+ }
1042
+
1043
+ interface SdkSessionPublication {
1044
+ candidate: Composition;
1045
+ expectedSession: Composition;
1046
+ targetPath: string;
1047
+ }
1048
+ type SdkSessionPublicationResult = "published" | "rejected-active-target" | "rejected-inactive-target";
1049
+ type PublishSdkSession = (publication: SdkSessionPublication) => SdkSessionPublicationResult;
1050
+
1051
+ type TimelineLayerDropPlacement = {
1052
+ type: "onto";
1053
+ layerId: string;
1054
+ } | {
1055
+ type: "between";
1056
+ beforeLayerId: string;
1057
+ afterLayerId: string;
1058
+ } | {
1059
+ type: "above";
1060
+ layerId: string;
1061
+ } | {
1062
+ type: "below";
1063
+ layerId: string;
1064
+ };
1065
+ interface TimelineStackingZIndexChange {
1066
+ key: string;
1067
+ zIndex: number;
1068
+ domId?: string;
1069
+ selector?: string;
1070
+ selectorIndex?: number;
1071
+ sourceFile?: string;
1072
+ }
1073
+ interface TimelineStackingReorderIntent {
1074
+ contextKey: string;
1075
+ placement: TimelineLayerDropPlacement;
1076
+ zIndexChanges: TimelineStackingZIndexChange[];
1077
+ }
1078
+
981
1079
  type BlockedTimelineEditIntent = "move" | "resize-start" | "resize-end";
982
1080
 
1081
+ /**
1082
+ * Durability report for a patch-batches commit. `durable === false` means the
1083
+ * server could not locate at least one patch target on disk — the preview was
1084
+ * reloaded to reconverge, and dependent follow-up writes (the z→lane timeline
1085
+ * mirror) must be skipped. `allMatched` retains the underlying match detail.
1086
+ * `changed === false` means no source file was written: every patch was a
1087
+ * byte-identical no-op, or the atomic gesture was refused before any write.
1088
+ */
1089
+ interface DomEditPatchBatchesResult {
1090
+ durable: boolean;
1091
+ allMatched: boolean;
1092
+ changed: boolean;
1093
+ }
1094
+
1095
+ /** A host's verdict on one element: editable, or blocked with a reason to show. */
1096
+ type TimelineEditPermission = true | {
1097
+ blocked: true;
1098
+ reason: string;
1099
+ };
1100
+ type CanEditTimelineElement = (element: TimelineElement) => TimelineEditPermission;
1101
+
1102
+ interface RecordEditInput$1 {
1103
+ label: string;
1104
+ kind: EditHistoryKind;
1105
+ coalesceKey?: string;
1106
+ files: Record<string, {
1107
+ before: string;
1108
+ after: string;
1109
+ }>;
1110
+ }
1111
+ type TimelineZIndexReorderCommit = (entries: Array<{
1112
+ element: HTMLElement;
1113
+ zIndex: number;
1114
+ id?: string;
1115
+ selector?: string;
1116
+ selectorIndex?: number;
1117
+ sourceFile: string;
1118
+ key?: string;
1119
+ }>, coalesceKey?: string) => Promise<DomEditPatchBatchesResult | undefined | void>;
1120
+ interface UseTimelineEditingOptions {
1121
+ projectId: string | null;
1122
+ activeCompPath: string | null;
1123
+ timelineElements: TimelineElement[];
1124
+ showToast: (message: string, tone?: "error" | "info") => void;
1125
+ writeProjectFile: (path: string, content: string, expectedContent?: string) => Promise<void>;
1126
+ observeProjectFileVersion?: (path: string, version: string | null) => void;
1127
+ recordEdit: (input: RecordEditInput$1) => Promise<void>;
1128
+ reloadPreview: () => void;
1129
+ previewIframeRef: RefObject<HTMLIFrameElement | null>;
1130
+ pendingTimelineEditPathRef: MutableRefObject<Set<string>>;
1131
+ uploadProjectFiles: (files: Iterable<File>, dir?: string) => Promise<string[]>;
1132
+ isRecordingRef?: RefObject<boolean>;
1133
+ /** Stage 7 §3.2: SDK session for routing timing ops through setTiming. */
1134
+ sdkSession?: Composition | null;
1135
+ /** Publish a fully persisted candidate SDK session. */
1136
+ publishSdkSession?: PublishSdkSession;
1137
+ /** Resync the SDK session after a server-authoritative timeline write. */
1138
+ forceReloadSdkSession?: () => void;
1139
+ /** Reparse authored animations after a timing rewrite changes their positions. */
1140
+ invalidateGsapCache?: () => void;
1141
+ handleDomZIndexReorderCommitRef?: MutableRefObject<TimelineZIndexReorderCommit | null>;
1142
+ /** Refuses a hand edit at the persist boundary when set; absent = Studio unchanged. */
1143
+ canEdit?: CanEditTimelineElement;
1144
+ }
1145
+ /** What a timeline move commits: the new start and track, plus the z-index
1146
+ * reorder a vertical drag resolves to (absent for a pure horizontal move). */
1147
+ type TimelineMoveUpdates = Pick<TimelineElement, "start" | "track"> & {
1148
+ stackingReorder?: TimelineStackingReorderIntent | null;
1149
+ };
1150
+
1151
+ interface TimelineGroupMoveChange {
1152
+ element: TimelineElement;
1153
+ start: number;
1154
+ track?: number;
1155
+ }
1156
+ interface TimelineGroupResizeChange {
1157
+ element: TimelineElement;
1158
+ start: number;
1159
+ duration: number;
1160
+ playbackStart?: number;
1161
+ }
1162
+ interface TimelineGroupCommitOptions {
1163
+ beforeTiming?: Promise<void>;
1164
+ coalesceKey?: string;
1165
+ /** Per-entry undo coalesce window override (ms) — see EditHistoryEntry.coalesceMs. */
1166
+ coalesceMs?: number;
1167
+ /** Overrides the default "Move timeline clips" undo-history label. Coalescing
1168
+ * keeps the LAST entry's label (editHistory.ts), so a mechanical follow-up
1169
+ * move folded into another gesture's coalesceKey (e.g. the ripple after a
1170
+ * delete) should carry that gesture's own label, not its own. */
1171
+ label?: string;
1172
+ /** Skips this call's own generic failure toast (the error is still logged
1173
+ * to the console) — for a caller that shows its own more specific message
1174
+ * on the same failure, so the user isn't told about one action twice. */
1175
+ suppressFailureToast?: boolean;
1176
+ }
1177
+
983
1178
  type TimelineMoveOperation = "timing" | "lane-reorder" | "track-insert";
984
1179
 
985
1180
  interface TimelineKeyframeTarget {
@@ -1130,6 +1325,8 @@ interface TimelineProps extends TimelineDropCallbacks, TimelineEditOverrides {
1130
1325
  renderClipOverlay?: (element: TimelineElement) => ReactNode;
1131
1326
  onDeleteElement?: (element: TimelineElement) => Promise<void> | void;
1132
1327
  onSelectElement?: (element: TimelineElement | null) => void;
1328
+ /** Notification only; null when cleared. The value lives in usePlayerStore.rangeSelection. */
1329
+ onRangeSelect?: (range: TimelineTimeRange | null) => void;
1133
1330
  onCopyClip?: () => boolean;
1134
1331
  onPasteClip?: () => Promise<void>;
1135
1332
  onDuplicateClip?: () => Promise<boolean>;
@@ -1749,4 +1946,237 @@ declare function findElementBlock(html: string, elementId: string): {
1749
1946
  isSelfClosing: boolean;
1750
1947
  } | null;
1751
1948
 
1752
- export { type AgentModalAnchorPoint, type AgentPromptElementInfo, AskAgentModal, type AskAgentModalProps, Button, type ButtonSize, type ButtonVariant, CompositionBreadcrumb, type CompositionDimensions, type CompositionLevel, CompositionThumbnail, ContextMenu, EditorShell, type EditorShellProps, type FfmpegStatus, FileTree, HyperframesLogo, IconButton, Input, type InputProps, Menu, MenuItem, type MenuItemTone, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuShortcut, NLEPreview, NumberField, type NumberFieldProps, type PatchOperation, type PersistedRenderSettings, type PickedElement, Player, PlayerControls, Popover, type PopupPreviewState, type DomEditCompositionRect as PreviewCompositionRect, type PreviewState, PropertyPanel, type RenderJob, RenderQueue, type RenderQueueProps, type ResolutionPreset, Select, type SelectOption, type SelectProps, Slider, type SliderProps, SourceEditor, type StartRenderOptions, StudioApp, Tab, TabPanel, Tabs, TabsList, Timeline, type TimelineElement, Toggle, type ToggleProps, Tooltip, VideoThumbnail, applyPatch, buildPickerAgentContextPreview, buildPickerAgentPrompt, buttonBase, buttonSizes, buttonVariants, cn, fieldBase, fieldText, findElementBlock, formatTime, getPersistedRenderSettings, liveTime, mergeStyleIntoTag, parseStyleString, persistRenderSettings, popupSurface, resolveIframe, resolveSourceFile, useElementPicker, usePlayerStore, usePreviewCompositionRect, useRenderQueue, useTimelinePlayer };
1949
+ interface EditHistoryStorageAdapter {
1950
+ get(projectId: string): Promise<EditHistoryState | null>;
1951
+ set(projectId: string, state: EditHistoryState): Promise<void>;
1952
+ delete(projectId: string): Promise<void>;
1953
+ }
1954
+
1955
+ interface RecordEditInput {
1956
+ label: string;
1957
+ kind: EditHistoryKind;
1958
+ coalesceKey?: string;
1959
+ coalesceMs?: number;
1960
+ files: BuildEditHistoryEntryInput["files"];
1961
+ }
1962
+ interface ApplyCallbacks {
1963
+ readFile: (path: string) => Promise<string>;
1964
+ writeFile: (path: string, content: string) => Promise<void>;
1965
+ serialize?: <T>(paths: readonly string[], task: () => Promise<T>) => Promise<T>;
1966
+ }
1967
+ interface UsePersistentEditHistoryOptions {
1968
+ projectId: string | null;
1969
+ storage?: EditHistoryStorageAdapter;
1970
+ now?: () => number;
1971
+ }
1972
+ /**
1973
+ * Per-file content the restore just applied. `restored` is the bytes written to
1974
+ * disk (the undo/redo target); `previous` is what was on disk immediately before
1975
+ * (the current live preview state). The undo preview-sync diffs these to decide
1976
+ * whether the restore is soft-reloadable (attributes/style/GSAP-script only) or
1977
+ * needs a full iframe reload.
1978
+ */
1979
+ interface ApplyRestoredFile {
1980
+ previous: string;
1981
+ restored: string;
1982
+ }
1983
+ interface ApplyResult {
1984
+ ok: boolean;
1985
+ reason?: "empty" | "content-mismatch";
1986
+ label?: string;
1987
+ paths?: string[];
1988
+ files?: Record<string, ApplyRestoredFile>;
1989
+ }
1990
+ declare function usePersistentEditHistory(options: UsePersistentEditHistoryOptions): {
1991
+ recordEdit: (input: RecordEditInput) => Promise<void>;
1992
+ undo: (callbacks: ApplyCallbacks) => Promise<ApplyResult>;
1993
+ redo: (callbacks: ApplyCallbacks) => Promise<ApplyResult>;
1994
+ canUndo: boolean;
1995
+ canRedo: boolean;
1996
+ undoLabel: string;
1997
+ redoLabel: string;
1998
+ undoPaths: string[];
1999
+ redoPaths: string[];
2000
+ state: EditHistoryState;
2001
+ loaded: boolean;
2002
+ };
2003
+
2004
+ declare function useTimelineEditing({ projectId, activeCompPath, timelineElements, showToast, writeProjectFile, observeProjectFileVersion, recordEdit, reloadPreview, previewIframeRef, pendingTimelineEditPathRef, uploadProjectFiles, isRecordingRef, sdkSession, publishSdkSession, forceReloadSdkSession, invalidateGsapCache, handleDomZIndexReorderCommitRef, canEdit, }: UseTimelineEditingOptions): {
2005
+ handleTimelineElementMove: (element: TimelineElement, updates: TimelineMoveUpdates) => Promise<void>;
2006
+ handleTimelineElementResize: (element: TimelineElement, updates: Pick<TimelineElement, "start" | "duration" | "playbackStart">) => Promise<void>;
2007
+ handleToggleTrackHidden: (track: number, hidden: boolean, displayNumber?: number | null | undefined) => Promise<void>;
2008
+ handleToggleElementHidden: (elementKey: string | readonly string[], hidden: boolean) => Promise<void>;
2009
+ handleAutoGroupCarveSources: (clipIds: readonly string[], groupId: string, groupLabel?: string | undefined) => Promise<void>;
2010
+ setAudioGroupAttribute: {
2011
+ setQuiet: (groupId: string, attr: string, value: string | null, label: string) => Promise<void>;
2012
+ setLive: (groupId: string, attr: string, value: string | null) => void;
2013
+ };
2014
+ setElementFxAttribute: {
2015
+ setQuiet: (element: TimelineElement, attr: string, value: string | null, label: string) => Promise<void>;
2016
+ setLive: (element: TimelineElement, attr: string, value: string | null) => void;
2017
+ };
2018
+ handleTimelineElementDelete: (element: TimelineElement) => Promise<void>;
2019
+ handleTimelineElementsDelete: (selection: TimelineElement[]) => Promise<void>;
2020
+ handleTimelineElementSplit: (element: TimelineElement, splitTime: number) => Promise<void>;
2021
+ handleRazorSplit: (element: TimelineElement, splitTime: number) => Promise<void>;
2022
+ handleRazorSplitAll: (splitTime: number) => Promise<void>;
2023
+ handleTimelineAssetDrop: (assetPath: string, placement: TimelineDropPlacement, durationOverride?: number | undefined) => Promise<void>;
2024
+ handleTimelineFileDrop: (files: File[], placement?: TimelineDropPlacement | undefined) => Promise<void>;
2025
+ handleTimelineCompositionDrop: (sourcePath: string, placement: Pick<TimelineElement, "track" | "start">) => Promise<void>;
2026
+ handleBlockedTimelineEdit: (element: TimelineElement) => void;
2027
+ handleTimelineGroupMove: (changes: TimelineGroupMoveChange[], options?: TimelineGroupCommitOptions | undefined) => Promise<void>;
2028
+ handleTimelineGroupResize: (changes: TimelineGroupResizeChange[], options?: TimelineGroupCommitOptions | undefined) => Promise<void>;
2029
+ };
2030
+
2031
+ declare class StudioSaveHttpError extends Error {
2032
+ readonly statusCode: number;
2033
+ readonly alreadyToasted: boolean;
2034
+ constructor(message: string, statusCode: number, options?: {
2035
+ alreadyToasted?: boolean;
2036
+ });
2037
+ }
2038
+ declare class StudioFileConflictError extends StudioSaveHttpError {
2039
+ readonly filePath: string;
2040
+ readonly currentVersion: string | null;
2041
+ readonly currentContent: string | null;
2042
+ readonly attemptedContent: string;
2043
+ constructor(input: {
2044
+ filePath: string;
2045
+ currentVersion: string | null;
2046
+ currentContent: string | null;
2047
+ attemptedContent: string;
2048
+ });
2049
+ }
2050
+ type StudioSaveDrainResult<Failure = unknown> = {
2051
+ status: "clean";
2052
+ } | {
2053
+ status: "conflict";
2054
+ error: StudioFileConflictError;
2055
+ } | {
2056
+ status: "failed";
2057
+ error: Failure;
2058
+ };
2059
+
2060
+ type StudioPendingEditsDrainResult = StudioSaveDrainResult;
2061
+ declare function flushStudioPendingEdits(): Promise<StudioPendingEditsDrainResult>;
2062
+
2063
+ interface HistoryResult {
2064
+ ok: boolean;
2065
+ reason?: string;
2066
+ label?: string;
2067
+ paths?: string[];
2068
+ /** Per-file restored/previous content, used to soft-apply the preview. */
2069
+ files?: Record<string, {
2070
+ previous: string;
2071
+ restored: string;
2072
+ }>;
2073
+ }
2074
+ interface HistoryFileCallbacks {
2075
+ readFile: (path: string) => Promise<string>;
2076
+ writeFile: (path: string, content: string) => Promise<void>;
2077
+ serialize?: <T>(paths: readonly string[], task: () => Promise<T>) => Promise<T>;
2078
+ }
2079
+ interface EditHistoryHandle {
2080
+ undo: (cb: HistoryFileCallbacks) => Promise<HistoryResult>;
2081
+ redo: (cb: HistoryFileCallbacks) => Promise<HistoryResult>;
2082
+ state: {
2083
+ undo: ReadonlyArray<{
2084
+ createdAt: number;
2085
+ }>;
2086
+ redo: ReadonlyArray<{
2087
+ createdAt: number;
2088
+ }>;
2089
+ };
2090
+ }
2091
+ interface UseEditHistoryActionsOptions {
2092
+ editHistory: Pick<EditHistoryHandle, "undo" | "redo">;
2093
+ readOptionalProjectFile: (path: string) => Promise<string>;
2094
+ readProjectFile: (path: string) => Promise<string>;
2095
+ writeProjectFile: (path: string, content: string) => Promise<void>;
2096
+ showToast: (message: string, tone?: "error" | "info") => void;
2097
+ syncHistoryPreviewAfterApply: (restore: Pick<HistoryResult, "paths" | "files">) => Promise<void>;
2098
+ waitForPendingDomEditSaves: () => Promise<void>;
2099
+ onAfterUndoRedo?: () => void;
2100
+ /** Active composition path — decides whether undo/redo must resync the SDK session. */
2101
+ activeCompPath?: string | null;
2102
+ /** Reloads the SDK session after a revert of the active comp, past the self-write suppress window. */
2103
+ forceReloadSdkSession?: () => void;
2104
+ }
2105
+ /** Applies one persisted file-history step: the single owner of undo/redo over project files. */
2106
+ declare function useEditHistoryActions({ editHistory, readOptionalProjectFile, readProjectFile, writeProjectFile, showToast, syncHistoryPreviewAfterApply, waitForPendingDomEditSaves, onAfterUndoRedo, activeCompPath, forceReloadSdkSession, }: UseEditHistoryActionsOptions): {
2107
+ undo: () => Promise<void>;
2108
+ redo: () => Promise<void>;
2109
+ };
2110
+
2111
+ interface UseProjectFileWriterOptions {
2112
+ projectId: string | null;
2113
+ }
2114
+ declare function useProjectFileWriter({ projectId }: UseProjectFileWriterOptions): {
2115
+ fileVersions: Map<string, string | null>;
2116
+ readProjectFile: (path: string) => Promise<string>;
2117
+ writeProjectFile: (path: string, content: string, expectedContent?: string) => Promise<void>;
2118
+ readOptionalProjectFile: (path: string) => Promise<string>;
2119
+ observeProjectFileVersion: (path: string, version: string | null) => void;
2120
+ };
2121
+
2122
+ type ExternalFileChangeBlockedState = {
2123
+ status: "conflict";
2124
+ generation: number;
2125
+ error: StudioFileConflictError;
2126
+ payload: unknown;
2127
+ } | {
2128
+ status: "failed";
2129
+ generation: number;
2130
+ path: string;
2131
+ error: unknown;
2132
+ payload: unknown;
2133
+ studioContent: string | null;
2134
+ recovered: boolean;
2135
+ };
2136
+ interface ExternalFileChangeCoordinatorHandle {
2137
+ blocked: ExternalFileChangeBlockedState | null;
2138
+ retry: () => Promise<void>;
2139
+ useExternalFile: () => Promise<void>;
2140
+ keepStudioFile: () => Promise<void>;
2141
+ }
2142
+
2143
+ declare function ExternalFileConflictBanner({ coordinator, }: {
2144
+ coordinator: ExternalFileChangeCoordinatorHandle;
2145
+ }): react_jsx_runtime.JSX.Element | null;
2146
+
2147
+ interface TimelinePaneProps {
2148
+ /** Slot rendered above the timeline tracks (toolbar with split, delete, zoom) */
2149
+ timelineToolbar?: ReactNode;
2150
+ /** Slot rendered below the timeline tracks */
2151
+ timelineFooter?: ReactNode;
2152
+ /** Slot for a host's own overlay spanning the whole timeline area (e.g. a draft/ghost
2153
+ * clip), positioned absolutely the same way PreviewPane's previewOverlay is. */
2154
+ timelineOverlay?: ReactNode;
2155
+ /** Custom clip content renderer for timeline (thumbnails, waveforms, etc.) */
2156
+ renderClipContent?: (element: TimelineElement, style: {
2157
+ clip: string;
2158
+ label: string;
2159
+ }) => ReactNode;
2160
+ onFileDrop?: (files: File[], placement?: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
2161
+ onDeleteElement?: (element: TimelineElement) => Promise<void> | void;
2162
+ onAssetDrop?: (assetPath: string, placement: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
2163
+ onBlockDrop?: (blockName: string, placement: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
2164
+ onCompositionDrop?: (sourcePath: string, placement: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
2165
+ onBlockedEditAttempt?: (element: TimelineElement, intent: BlockedTimelineEditIntent) => void;
2166
+ onSelectTimelineElement?: (element: TimelineElement | null) => void;
2167
+ onRangeSelect?: (range: TimelineTimeRange | null) => void;
2168
+ /** Copy/paste/duplicate act on the store's own selection, not a passed
2169
+ * element, so unlike onDeleteElement they need no composition-basis wrapper. */
2170
+ onCopyClip?: () => boolean;
2171
+ onPasteClip?: () => Promise<void>;
2172
+ onDuplicateClip?: () => Promise<boolean>;
2173
+ canPasteClip?: () => boolean;
2174
+ }
2175
+ declare function TimelinePane({ timelineToolbar, timelineFooter, timelineOverlay, renderClipContent, onFileDrop, onDeleteElement, onAssetDrop, onBlockDrop, onCompositionDrop, onBlockedEditAttempt, onSelectTimelineElement, onRangeSelect, onCopyClip, onPasteClip, onDuplicateClip, canPasteClip, }: TimelinePaneProps): react_jsx_runtime.JSX.Element;
2176
+
2177
+ declare function TimelineEditProvider({ value, children, }: {
2178
+ value: TimelineEditCallbacks;
2179
+ children: ReactNode;
2180
+ }): react_jsx_runtime.JSX.Element;
2181
+
2182
+ export { type AgentModalAnchorPoint, type AgentPromptElementInfo, AskAgentModal, type AskAgentModalProps, type BlockedTimelineEditIntent, Button, type ButtonSize, type ButtonVariant, type CanEditTimelineElement, CompositionBreadcrumb, type CompositionDimensions, type CompositionLevel, CompositionThumbnail, ContextMenu, type EditHistoryHandle, EditorShell, type EditorShellProps, type ExternalFileChangeBlockedState, type ExternalFileChangeCoordinatorHandle, ExternalFileConflictBanner, type FfmpegStatus, FileTree, HyperframesLoader, type HyperframesLoaderProps, HyperframesLogo, IconButton, Input, type InputProps, Menu, MenuItem, type MenuItemTone, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuShortcut, NLEPreview, NumberField, type NumberFieldProps, type PatchOperation, type PersistedRenderSettings, type PickedElement, Player, PlayerControls, Popover, type PopupPreviewState, type DomEditCompositionRect as PreviewCompositionRect, type PreviewState, PropertyPanel, type RenderJob, RenderQueue, type RenderQueueProps, type ResolutionPreset, Select, type SelectOption, type SelectProps, Slider, type SliderProps, SourceEditor, type StartRenderOptions, StudioApp, StudioFileConflictError, type StudioPendingEditsDrainResult, Tab, TabPanel, Tabs, TabsList, Timeline, type TimelineEditCallbacks, type TimelineEditPermission, TimelineEditProvider, type TimelineElement, TimelinePane, type TimelinePaneProps, type TimelineTimeRange, Toggle, type ToggleProps, Tooltip, type UseEditHistoryActionsOptions, type UsePersistentEditHistoryOptions, type UseProjectFileWriterOptions, type UseTimelineEditingOptions, VideoThumbnail, applyPatch, buildPickerAgentContextPreview, buildPickerAgentPrompt, buttonBase, buttonSizes, buttonVariants, cn, fieldBase, fieldText, findElementBlock, flushStudioPendingEdits, formatTime, getPersistedRenderSettings, liveTime, mergeStyleIntoTag, parseStyleString, persistRenderSettings, popupSurface, resolveIframe, resolveSourceFile, useEditHistoryActions, useElementPicker, usePersistentEditHistory, usePlayerStore, usePreviewCompositionRect, useProjectFileWriter, useRenderQueue, useTimelineEditing, useTimelinePlayer };
@@ -5,7 +5,7 @@
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-HfP3sap2.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-DPUJoO8n.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-DrHQAuGO.css">
10
10
  </head>
11
11
  <body>