@hyperframes/studio 0.8.51 → 0.8.53-desktop.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{hyperframes-player-Cn_PpHqP.js → hyperframes-player-PTEnAHhg.js} +1 -1
- package/dist/assets/{index-CPS3Cvj8.js → index--myXp8ui.js} +1 -1
- package/dist/assets/{index-Clrb11lj.js → index-BjslOS9g.js} +1 -1
- package/dist/assets/index-BnXZuIJD.css +1 -0
- package/dist/assets/index-CNyviK_l.js +390 -0
- package/dist/index.css +29 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +808 -12
- package/dist/index.html +2 -2
- package/dist/index.js +8109 -7583
- package/dist/index.js.map +1 -1
- package/package.json +9 -7
- package/src/App.tsx +45 -50
- package/src/captions/components/CaptionOverlay.sender.test.tsx +52 -0
- package/src/captions/components/CaptionOverlay.tsx +8 -4
- package/src/components/EditorShell.selectionSync.test.tsx +9 -4
- package/src/components/EditorShell.tsx +56 -56
- package/src/components/RightPanelTabs.test.tsx +151 -0
- package/src/components/RightPanelTabs.tsx +59 -0
- package/src/components/StudioHeader.dom.test.tsx +181 -0
- package/src/components/StudioHeader.test.ts +0 -12
- package/src/components/StudioHeader.tsx +117 -160
- package/src/components/StudioLeftPanels.tsx +202 -0
- package/src/components/{StudioRightPanel.tsx → StudioRightPanels.tsx} +57 -194
- package/src/components/{StudioRightPanel.types.ts → StudioRightPanels.types.ts} +4 -3
- package/src/components/TimelineHistoryButtons.dom.test.tsx +117 -0
- package/src/components/TimelineHistoryButtons.tsx +54 -0
- package/src/components/TimelineToolbar.test.tsx +8 -0
- package/src/components/TimelineToolbar.tsx +3 -7
- package/src/components/dock/Dock.test.tsx +100 -18
- package/src/components/dock/Dock.tsx +32 -5
- package/src/components/dock/dock.css +5 -0
- package/src/components/dock/dockAccessibility.test.ts +166 -0
- package/src/components/dock/dockAccessibility.ts +98 -0
- package/src/components/dock/dockLayout.test.ts +134 -0
- package/src/components/dock/dockLayout.ts +53 -6
- package/src/components/dock/dockLayoutStore.test.ts +28 -0
- package/src/components/dock/dockLayoutStore.ts +21 -4
- package/src/components/dock/dockTestHarness.ts +11 -0
- package/src/components/editor/LayersPanel.test.ts +97 -1
- package/src/components/editor/LayersPanel.tsx +4 -2
- package/src/components/editor/PreviewGuides.tsx +1 -1
- package/src/components/editor/SnapToolbar.test.tsx +0 -3
- package/src/components/editor/TopologyLens.test.tsx +28 -0
- package/src/components/editor/TopologyLens.tsx +3 -1
- package/src/components/editor/useColorGradingController.test.ts +38 -0
- package/src/components/editor/useColorGradingController.ts +9 -1
- package/src/components/editor/useColorGradingPreviews.test.ts +76 -0
- package/src/components/editor/useColorGradingPreviews.ts +11 -1
- package/src/components/editor/usePreviewCompositionRect.test.tsx +95 -0
- package/src/components/editor/usePreviewCompositionRect.ts +21 -0
- package/src/components/nle/NLEContext.tsx +0 -43
- package/src/components/nle/NLEPreview.tsx +1 -1
- package/src/components/nle/PreviewPane.tsx +1 -1
- package/src/components/nle/TimelinePane.tsx +53 -67
- package/src/components/panels/SlideshowPanel.tsx +1 -1
- package/src/components/panels/VariablesPanel.tsx +1 -1
- package/src/components/pointerTargetSize.test.tsx +8 -0
- package/src/components/renders/RenderQueue.tsx +1 -1
- package/src/components/renders/RenderQueuePanel.tsx +1 -1
- package/src/components/sidebar/{LeftSidebar.masterComposition.test.tsx → CompositionsPanel.masterComposition.test.tsx} +6 -9
- package/src/components/sidebar/CompositionsPanel.tsx +15 -0
- package/src/components/sidebar/{LeftSidebar.lintBadge.test.tsx → SidebarLintButton.test.tsx} +6 -11
- package/src/components/sidebar/SidebarLintButton.tsx +50 -0
- package/src/components/timelineToolbarStyles.ts +5 -0
- package/src/components/ui/Button.test.tsx +222 -30
- package/src/components/ui/Button.tsx +88 -125
- package/src/components/ui/IconButton.tsx +38 -0
- package/src/components/ui/Input.tsx +115 -0
- package/src/components/ui/Menu.test.tsx +374 -0
- package/src/components/ui/Menu.tsx +213 -0
- package/src/components/ui/NumberField.tsx +122 -0
- package/src/components/ui/Popover.tsx +74 -0
- package/src/components/ui/Select.tsx +100 -0
- package/src/components/ui/Slider.tsx +153 -0
- package/src/components/ui/Tabs.test.tsx +98 -0
- package/src/components/ui/Tabs.tsx +71 -0
- package/src/components/ui/Toggle.tsx +63 -0
- package/src/components/ui/Tooltip.test.tsx +110 -0
- package/src/components/ui/Tooltip.tsx +38 -112
- package/src/components/ui/cn.test.ts +30 -0
- package/src/components/ui/cn.ts +25 -0
- package/src/components/ui/index.ts +29 -2
- package/src/components/ui/mountHost.testHelpers.ts +24 -0
- package/src/components/ui/valueControls.test.tsx +524 -0
- package/src/contexts/PanelLayoutContext.tsx +3 -57
- package/src/hooks/appHotkeysDispatch.ts +3 -4
- package/src/hooks/timelineEditPermission.ts +31 -0
- package/src/hooks/useAppHotkeys.previewForwarding.test.tsx +0 -2
- package/src/hooks/useAppHotkeys.test.ts +0 -1
- package/src/hooks/useAppHotkeys.textEditing.test.tsx +0 -3
- package/src/hooks/useAppHotkeys.ts +20 -83
- package/src/hooks/useCaptionDetection.sender.test.tsx +46 -0
- package/src/hooks/useCaptionDetection.ts +3 -1
- package/src/hooks/useDomEditPreviewSync.ts +4 -6
- package/src/hooks/useDomEditSession.ts +0 -7
- package/src/hooks/useDomEditWiring.ts +4 -9
- package/src/hooks/useEditHistoryActions.test.tsx +90 -0
- package/src/hooks/useEditHistoryActions.ts +106 -0
- package/src/hooks/useFileManager.ts +21 -123
- package/src/hooks/usePanelLayout.test.ts +108 -296
- package/src/hooks/usePanelLayout.ts +50 -255
- package/src/hooks/usePersistentEditHistory.ts +1 -1
- package/src/hooks/useProjectFileWriter.ts +150 -0
- package/src/hooks/useRightPanelIntents.test.ts +181 -0
- package/src/hooks/useRightPanelIntents.ts +63 -0
- package/src/hooks/useServerConnection.hashProject.test.tsx +94 -0
- package/src/hooks/useServerConnection.ts +43 -10
- package/src/hooks/useSlideshowTabState.test.ts +9 -31
- package/src/hooks/useSlideshowTabState.ts +6 -19
- package/src/hooks/useStudioContextValue.test.ts +6 -18
- package/src/hooks/useStudioContextValue.ts +5 -26
- package/src/hooks/useTimelineDeleteOps.test.tsx +111 -0
- package/src/hooks/useTimelineEditing.test.tsx +322 -3
- package/src/hooks/useTimelineEditing.ts +103 -16
- package/src/hooks/useTimelineEditingTypes.ts +3 -0
- package/src/hooks/useTrackPendingTimelineEdit.test.tsx +62 -0
- package/src/hooks/useTrackPendingTimelineEdit.ts +22 -0
- package/src/hostMount.test.tsx +222 -0
- package/src/index.ts +87 -0
- package/src/player/components/AutomationSelectionMenu.tsx +1 -1
- package/src/player/components/Timeline.tsx +1 -1
- package/src/player/components/TimelineCanvas.tsx +4 -4
- package/src/player/components/TimelineClip.tsx +0 -1
- package/src/player/components/TimelineTrackHeader.test.tsx +26 -5
- package/src/player/components/TimelineTrackHeader.tsx +1 -1
- package/src/player/components/timelineTheme.test.ts +4 -4
- package/src/player/components/timelineTheme.ts +30 -30
- package/src/player/lib/playbackShortcuts.ts +2 -0
- package/src/player/lib/timelinePerformanceDiagnostics.test.ts +3 -2
- package/src/player/lib/timelinePerformanceDiagnostics.ts +1 -1
- package/src/player/store/previewIframeStore.notify.test.tsx +75 -0
- package/src/player/store/previewIframeStore.test.tsx +29 -0
- package/src/player/store/previewIframeStore.ts +25 -0
- package/src/renderQueueExports.test.tsx +58 -0
- package/src/styles/classCandidates.test.ts +105 -0
- package/src/styles/classCandidates.ts +281 -0
- package/src/styles/hex-baseline.json +84 -0
- package/src/styles/hexRatchet.test.ts +201 -0
- package/src/styles/styleSources.test.ts +20 -0
- package/src/styles/styleSources.ts +47 -0
- package/src/styles/theme.css +57 -0
- package/src/styles/theme.test.ts +2 -15
- package/src/styles/tokenGate.test.ts +109 -0
- package/src/utils/sourcePatcher.ts +1 -1
- package/src/utils/studioHelpers.test.ts +18 -0
- package/src/utils/studioHelpers.ts +11 -8
- package/src/utils/studioUiPreferences.test.ts +10 -16
- package/src/utils/studioUiPreferences.ts +0 -16
- package/src/utils/typingTarget.ts +4 -0
- package/dist/assets/index-C05SNrvY.js +0 -360
- package/dist/assets/index-DUR9qzQM.css +0 -1
- package/src/components/PanelTabButton.tsx +0 -31
- package/src/components/StudioLeftSidebar.tsx +0 -207
- package/src/components/nle/TimelineResizeDivider.tsx +0 -101
- package/src/components/sidebar/LeftSidebar.storage.test.ts +0 -28
- package/src/components/sidebar/LeftSidebar.tsx +0 -348
- package/src/hooks/useInspectorSplitResize.ts +0 -51
- package/src/utils/fitPanels.test.ts +0 -164
- package/src/utils/fitPanels.ts +0 -151
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,281 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import * as react from 'react';
|
|
3
|
-
import { ReactNode, RefObject } from 'react';
|
|
2
|
+
import { ButtonHTMLAttributes, ReactNode, ElementType, ComponentPropsWithoutRef, ReactElement, RefObject, MutableRefObject } from 'react';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
import { Tabs as Tabs$1 } from '@base-ui/react/tabs';
|
|
5
|
+
import * as node_modules_cn_dist_types from 'node_modules/cn/dist/types';
|
|
6
|
+
import { ContextMenu as ContextMenu$1 } from '@base-ui/react/context-menu';
|
|
7
|
+
import { Menu as Menu$1 } from '@base-ui/react/menu';
|
|
8
|
+
import { Popover as Popover$1 } from '@base-ui/react/popover';
|
|
4
9
|
import { RuntimeTimelineClipIdentity, HyperframePickerElementInfo } from '@hyperframes/core';
|
|
5
10
|
import { GsapAnimation, PropertyGroupName } from '@hyperframes/core/gsap-parser';
|
|
6
11
|
import * as zustand from 'zustand';
|
|
7
12
|
import { StoreApi } from 'zustand';
|
|
8
13
|
import { MusicBeatAnalysis } from '@hyperframes/core/beats';
|
|
9
14
|
import { GsapAnimation as GsapAnimation$1, ArcPathSegment } from '@hyperframes/parsers/gsap-parser';
|
|
15
|
+
import { CanvasResolution } from '@hyperframes/parsers';
|
|
16
|
+
import { Composition } from '@hyperframes/sdk';
|
|
17
|
+
|
|
18
|
+
type ButtonVariant = "primary" | "secondary" | "danger" | "ghost";
|
|
19
|
+
type ButtonSize = "sm" | "md" | "lg";
|
|
20
|
+
/** Forces one interactive look for a gallery shot. CSS-only; see the header. */
|
|
21
|
+
type PreviewState = "hover" | "active" | "focus";
|
|
22
|
+
interface ButtonBaseProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
23
|
+
variant?: ButtonVariant;
|
|
24
|
+
size?: ButtonSize;
|
|
25
|
+
"data-preview-state"?: PreviewState;
|
|
26
|
+
}
|
|
27
|
+
interface ButtonProps extends ButtonBaseProps {
|
|
28
|
+
loading?: boolean;
|
|
29
|
+
icon?: ReactNode;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Shared by Button and IconButton. `disabled:` keeps pointer events alive so a
|
|
33
|
+
* wrapping Tooltip can still explain why the control is disabled.
|
|
34
|
+
*/
|
|
35
|
+
declare const buttonBase: string;
|
|
36
|
+
/**
|
|
37
|
+
* One entry per variant. The `data-[preview-state=…]` half of each string
|
|
38
|
+
* repeats the `hover:` and `active:` half exactly; the test pairs them.
|
|
39
|
+
*/
|
|
40
|
+
declare const buttonVariants: Record<ButtonVariant, string>;
|
|
41
|
+
declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
42
|
+
|
|
43
|
+
interface IconButtonProps extends ButtonBaseProps {
|
|
44
|
+
icon: ReactNode;
|
|
45
|
+
"aria-label": string;
|
|
46
|
+
}
|
|
47
|
+
declare const IconButton: react.ForwardRefExoticComponent<IconButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Base UI lets `className` be a function of the part's state. Studio's parts
|
|
51
|
+
* merge a string with `cn`, so the string form is the one they accept.
|
|
52
|
+
*/
|
|
53
|
+
type StyledProps$1<T extends ElementType> = Omit<ComponentPropsWithoutRef<T>, "className"> & {
|
|
54
|
+
className?: string;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Groups a tab list with its panels. Uncontrolled by default; pass `value` and
|
|
58
|
+
* `onValueChange` for a strip whose selection lives in a store.
|
|
59
|
+
*/
|
|
60
|
+
declare function Tabs(props: ComponentPropsWithoutRef<typeof Tabs$1.Root>): react_jsx_runtime.JSX.Element;
|
|
61
|
+
/** The strip. Give it an `aria-label`: a tablist with no name is unlabelled. */
|
|
62
|
+
declare function TabsList({ className, ...props }: StyledProps$1<typeof Tabs$1.List>): react_jsx_runtime.JSX.Element;
|
|
63
|
+
interface TabProps extends StyledProps$1<typeof Tabs$1.Tab> {
|
|
64
|
+
value: string;
|
|
65
|
+
"data-preview-state"?: PreviewState;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* aria-selected drives the selected look (Base UI sets it) so assistive tech
|
|
69
|
+
* and sighted users match. data-preview-state is for gallery shots only.
|
|
70
|
+
*/
|
|
71
|
+
declare function Tab({ value, className, ...props }: TabProps): react_jsx_runtime.JSX.Element;
|
|
72
|
+
/** The panel for one tab. Base UI wires `aria-labelledby` back to its tab. */
|
|
73
|
+
declare function TabPanel({ className, ...props }: StyledProps$1<typeof Tabs$1.Panel>): react_jsx_runtime.JSX.Element;
|
|
74
|
+
|
|
75
|
+
interface TooltipProps {
|
|
76
|
+
label: string;
|
|
77
|
+
/** A single element, wrapped in a box-less span so a disabled one still gets hover. */
|
|
78
|
+
children: ReactElement<{
|
|
79
|
+
"aria-describedby"?: string;
|
|
80
|
+
}>;
|
|
81
|
+
/** Hover delay in ms. */
|
|
82
|
+
delay?: number;
|
|
83
|
+
side?: "top" | "bottom" | "left" | "right";
|
|
84
|
+
}
|
|
85
|
+
declare function Tooltip({ label, children, delay, side }: TooltipProps): react_jsx_runtime.JSX.Element;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Studio's tailwind-merge config: teaches it the two scales `theme.css`
|
|
89
|
+
* invents (`text-step-*`, `ctl`/`ctl-sm`/`ctl-lg`) so overrides replace, not stack.
|
|
90
|
+
*/
|
|
91
|
+
declare const cn: node_modules_cn_dist_types.CnFunction;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Base UI lets `className` be a function of the part's state. Studio's parts
|
|
95
|
+
* merge a string with `cn`, so the string form is the one they accept.
|
|
96
|
+
*/
|
|
97
|
+
type StyledProps<T extends ElementType> = Omit<ComponentPropsWithoutRef<T>, "className"> & {
|
|
98
|
+
className?: string;
|
|
99
|
+
};
|
|
100
|
+
/** Forces the settled open look for a gallery shot; CSS-only, open state stays controlled. */
|
|
101
|
+
type PopupPreviewState = "open";
|
|
102
|
+
/** Where the portal puts the popup. `null` keeps it inline, next to its trigger. */
|
|
103
|
+
type PortalContainer$1 = ComponentPropsWithoutRef<typeof Menu$1.Portal>["container"];
|
|
104
|
+
/**
|
|
105
|
+
* Chrome shared by every floating panel (`Popover` too); callers add their own shadow token.
|
|
106
|
+
* `data-starting-style`/`data-ending-style` are Base UI's transition attributes.
|
|
107
|
+
*/
|
|
108
|
+
declare const popupSurface: string;
|
|
109
|
+
type MenuItemTone = "default" | "danger";
|
|
110
|
+
interface PositionedProps {
|
|
111
|
+
side?: "top" | "bottom" | "left" | "right";
|
|
112
|
+
align?: "start" | "center" | "end";
|
|
113
|
+
sideOffset?: number;
|
|
114
|
+
/** Portal target. Pass the shadow root when the trigger lives in one. */
|
|
115
|
+
container?: PortalContainer$1;
|
|
116
|
+
/** Names the popup for assistive tech. A menu with no name is unlabelled. */
|
|
117
|
+
"aria-label"?: string;
|
|
118
|
+
className?: string;
|
|
119
|
+
"data-preview-state"?: PopupPreviewState;
|
|
120
|
+
}
|
|
121
|
+
interface MenuProps extends PositionedProps, Omit<ComponentPropsWithoutRef<typeof Menu$1.Root>, "children"> {
|
|
122
|
+
/** A single element. It becomes the trigger; no wrapper is added around it. */
|
|
123
|
+
trigger: ReactElement;
|
|
124
|
+
/** The items: `MenuItem`, `MenuRadioGroup`, `MenuSeparator`. */
|
|
125
|
+
children: ReactNode;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* A menu opened by its trigger. Uncontrolled by default; pass `open` and
|
|
129
|
+
* `onOpenChange` for a menu whose state lives in a store.
|
|
130
|
+
*/
|
|
131
|
+
declare function Menu({ trigger, children, side, align, sideOffset, container, className, "aria-label": ariaLabel, "data-preview-state": previewState, ...root }: MenuProps): react_jsx_runtime.JSX.Element;
|
|
132
|
+
interface ContextMenuProps extends PositionedProps, Omit<ComponentPropsWithoutRef<typeof ContextMenu$1.Root>, "children"> {
|
|
133
|
+
/**
|
|
134
|
+
* The right-clickable area, as the caller's own element. Its children are
|
|
135
|
+
* kept: the trigger renders that element rather than wrapping it.
|
|
136
|
+
*/
|
|
137
|
+
trigger: ReactElement;
|
|
138
|
+
children: ReactNode;
|
|
139
|
+
}
|
|
140
|
+
/** Opened by right click or long press at the pointer, so `side` and `align` are not offered. */
|
|
141
|
+
declare function ContextMenu({ trigger, children, container, className, "aria-label": ariaLabel, "data-preview-state": previewState, ...root }: Omit<ContextMenuProps, "side" | "align" | "sideOffset">): react_jsx_runtime.JSX.Element;
|
|
142
|
+
/** Keyboard shortcut hint, mono and tabular; exported for hints that are not a plain string. */
|
|
143
|
+
declare function MenuShortcut({ className, ...props }: StyledProps<"span">): react_jsx_runtime.JSX.Element;
|
|
144
|
+
interface MenuItemProps extends StyledProps<typeof Menu$1.Item> {
|
|
145
|
+
/** Rendered as a dim mono hint on the trailing edge. Decorative. */
|
|
146
|
+
shortcut?: string;
|
|
147
|
+
/** `danger` for a destructive action (Delete, Remove). */
|
|
148
|
+
tone?: MenuItemTone;
|
|
149
|
+
"data-preview-state"?: "hover";
|
|
150
|
+
}
|
|
151
|
+
/** One action. `disabled` items are skipped by the arrow keys, not just dimmed. */
|
|
152
|
+
declare function MenuItem({ shortcut, tone, className, children, ...props }: MenuItemProps): react_jsx_runtime.JSX.Element;
|
|
153
|
+
/** Single-choice group; selection is `aria-checked` on each item, which the dot indicator draws from. */
|
|
154
|
+
declare function MenuRadioGroup(props: ComponentPropsWithoutRef<typeof Menu$1.RadioGroup>): react_jsx_runtime.JSX.Element;
|
|
155
|
+
interface MenuRadioItemProps extends StyledProps<typeof Menu$1.RadioItem> {
|
|
156
|
+
"data-preview-state"?: "hover";
|
|
157
|
+
}
|
|
158
|
+
/** One choice in a `MenuRadioGroup`. The dot renders only while it is checked. */
|
|
159
|
+
declare function MenuRadioItem({ className, children, ...props }: MenuRadioItemProps): react_jsx_runtime.JSX.Element;
|
|
160
|
+
/** A hairline between two groups of items. */
|
|
161
|
+
declare function MenuSeparator({ className, ...props }: StyledProps<typeof Menu$1.Separator>): react_jsx_runtime.JSX.Element;
|
|
162
|
+
|
|
163
|
+
type PortalContainer = ComponentPropsWithoutRef<typeof Popover$1.Portal>["container"];
|
|
164
|
+
interface PopoverProps extends Omit<ComponentPropsWithoutRef<typeof Popover$1.Root>, "children"> {
|
|
165
|
+
/** A single element. It becomes the trigger; no wrapper is added around it. */
|
|
166
|
+
trigger: ReactElement;
|
|
167
|
+
/** Arbitrary content. The popover owns none of its keys. */
|
|
168
|
+
children: ReactNode;
|
|
169
|
+
side?: "top" | "bottom" | "left" | "right";
|
|
170
|
+
align?: "start" | "center" | "end";
|
|
171
|
+
sideOffset?: number;
|
|
172
|
+
/** Portal target. Pass the shadow root when the trigger lives in one. */
|
|
173
|
+
container?: PortalContainer;
|
|
174
|
+
/** Names the popup for assistive tech. */
|
|
175
|
+
"aria-label"?: string;
|
|
176
|
+
/**
|
|
177
|
+
* What to focus on open. Defaults to Base UI's behaviour (the first tabbable
|
|
178
|
+
* element), which is what a rename field wants.
|
|
179
|
+
*/
|
|
180
|
+
initialFocus?: ComponentPropsWithoutRef<typeof Popover$1.Popup>["initialFocus"];
|
|
181
|
+
className?: string;
|
|
182
|
+
"data-preview-state"?: PopupPreviewState;
|
|
183
|
+
}
|
|
184
|
+
declare function Popover({ trigger, children, side, align, sideOffset, container, className, initialFocus, "aria-label": ariaLabel, "data-preview-state": previewState, ...root }: PopoverProps): react_jsx_runtime.JSX.Element;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Shared field look (also used by NumberField and Select). Each interactive state is written
|
|
188
|
+
* twice, real and `data-[preview-state=...]`; `valueControls.test.tsx` asserts the lists match.
|
|
189
|
+
*/
|
|
190
|
+
declare const fieldBase: string;
|
|
191
|
+
/** The text itself, inside the box. The box owns the border and the ring. */
|
|
192
|
+
declare const fieldText: string;
|
|
193
|
+
interface InputProps extends Omit<ComponentPropsWithoutRef<"input">, "value" | "onChange" | "className"> {
|
|
194
|
+
/** The committed value. A draft lives inside until Enter or blur. */
|
|
195
|
+
value: string;
|
|
196
|
+
/** Called with the draft on Enter and on blur, only when it really changed. */
|
|
197
|
+
onCommit: (next: string) => void;
|
|
198
|
+
/** Called once per committed change, for design-input telemetry. */
|
|
199
|
+
onTrack?: () => void;
|
|
200
|
+
/** Marks the field invalid: red boundary and `aria-invalid`. */
|
|
201
|
+
invalid?: boolean;
|
|
202
|
+
className?: string;
|
|
203
|
+
"data-preview-state"?: PreviewState;
|
|
204
|
+
}
|
|
205
|
+
declare function Input({ value, onCommit, onTrack, invalid, disabled, className, "data-preview-state": previewState, ...props }: InputProps): react_jsx_runtime.JSX.Element;
|
|
206
|
+
|
|
207
|
+
interface NumberFieldProps {
|
|
208
|
+
/** Accessible name. The inspector's row label is the usual one. */
|
|
209
|
+
label: string;
|
|
210
|
+
/** The committed value. */
|
|
211
|
+
value: number;
|
|
212
|
+
/** Called when a commit boundary produces a value different from `value`. */
|
|
213
|
+
onCommit: (next: number) => void;
|
|
214
|
+
/** Called once per committed change, for design-input telemetry. */
|
|
215
|
+
onTrack?: () => void;
|
|
216
|
+
/** Rendered beside the number: "px", "%", "deg". Never part of the text. */
|
|
217
|
+
unit?: string;
|
|
218
|
+
min?: number;
|
|
219
|
+
max?: number;
|
|
220
|
+
step?: number;
|
|
221
|
+
disabled?: boolean;
|
|
222
|
+
className?: string;
|
|
223
|
+
"data-preview-state"?: PreviewState;
|
|
224
|
+
}
|
|
225
|
+
declare function NumberField({ label, value, onCommit, onTrack, unit, min, max, step, disabled, className, "data-preview-state": previewState, }: NumberFieldProps): react_jsx_runtime.JSX.Element;
|
|
226
|
+
|
|
227
|
+
interface SelectOption {
|
|
228
|
+
label: string;
|
|
229
|
+
value: string;
|
|
230
|
+
}
|
|
231
|
+
interface SelectProps {
|
|
232
|
+
/** Accessible name for the trigger. */
|
|
233
|
+
label: string;
|
|
234
|
+
value: string;
|
|
235
|
+
options: SelectOption[];
|
|
236
|
+
/** Called when a different option is chosen. */
|
|
237
|
+
onCommit: (next: string) => void;
|
|
238
|
+
/** Called once per committed change, for design-input telemetry. */
|
|
239
|
+
onTrack?: () => void;
|
|
240
|
+
disabled?: boolean;
|
|
241
|
+
className?: string;
|
|
242
|
+
"data-preview-state"?: PreviewState;
|
|
243
|
+
}
|
|
244
|
+
declare function Select({ label, value, options, onCommit, onTrack, disabled, className, "data-preview-state": previewState, }: SelectProps): react_jsx_runtime.JSX.Element;
|
|
245
|
+
|
|
246
|
+
interface SliderProps {
|
|
247
|
+
/** Accessible name for the thumb. The inspector's row label is the usual one. */
|
|
248
|
+
label: string;
|
|
249
|
+
/** The committed value. */
|
|
250
|
+
value: number;
|
|
251
|
+
min: number;
|
|
252
|
+
max: number;
|
|
253
|
+
step?: number;
|
|
254
|
+
/** Every intermediate value while dragging or stepping. Not a commit. */
|
|
255
|
+
onPreview?: (next: number) => void;
|
|
256
|
+
/** Called at a commit boundary when the value really changed. */
|
|
257
|
+
onCommit: (next: number) => void;
|
|
258
|
+
/** Called once per commit boundary, for design-input telemetry. */
|
|
259
|
+
onTrack?: () => void;
|
|
260
|
+
disabled?: boolean;
|
|
261
|
+
className?: string;
|
|
262
|
+
"data-preview-state"?: PreviewState;
|
|
263
|
+
}
|
|
264
|
+
declare function Slider({ label, value, min, max, step, onPreview, onCommit, onTrack, disabled, className, "data-preview-state": previewState, }: SliderProps): react_jsx_runtime.JSX.Element;
|
|
265
|
+
|
|
266
|
+
interface ToggleProps {
|
|
267
|
+
/** Accessible name. */
|
|
268
|
+
label: string;
|
|
269
|
+
checked: boolean;
|
|
270
|
+
/** Called on every flip. */
|
|
271
|
+
onCommit: (next: boolean) => void;
|
|
272
|
+
/** Called once per flip, for design-input telemetry. */
|
|
273
|
+
onTrack?: () => void;
|
|
274
|
+
disabled?: boolean;
|
|
275
|
+
className?: string;
|
|
276
|
+
"data-preview-state"?: PreviewState;
|
|
277
|
+
}
|
|
278
|
+
declare function Toggle({ label, checked, onCommit, onTrack, disabled, className, "data-preview-state": previewState, }: ToggleProps): react_jsx_runtime.JSX.Element;
|
|
10
279
|
|
|
11
280
|
interface PlayerProps {
|
|
12
281
|
projectId?: string;
|
|
@@ -587,10 +856,6 @@ interface BeatHistoryEntry {
|
|
|
587
856
|
}
|
|
588
857
|
declare const usePlayerStore: zustand.UseBoundStore<zustand.StoreApi<PlayerState>>;
|
|
589
858
|
|
|
590
|
-
/**
|
|
591
|
-
* Source Patcher — Maps visual property edits back to source HTML files.
|
|
592
|
-
* Handles inline style updates, attribute changes, and text content.
|
|
593
|
-
*/
|
|
594
859
|
interface PatchOperation {
|
|
595
860
|
type: "inline-style" | "attribute" | "text-content" | "html-attribute" | "rich-text";
|
|
596
861
|
property: string;
|
|
@@ -705,8 +970,179 @@ declare function buildPickerAgentPrompt({ selection, userInstruction, }: {
|
|
|
705
970
|
}): string;
|
|
706
971
|
declare function buildPickerAgentContextPreview(selection: HyperframePickerElementInfo | null): string;
|
|
707
972
|
|
|
973
|
+
type EditHistoryKind = "manual" | "motion" | "timeline" | "source";
|
|
974
|
+
interface EditHistoryFileSnapshot {
|
|
975
|
+
before: string;
|
|
976
|
+
after: string;
|
|
977
|
+
beforeHash: string;
|
|
978
|
+
afterHash: string;
|
|
979
|
+
}
|
|
980
|
+
interface EditHistoryEntry {
|
|
981
|
+
id: string;
|
|
982
|
+
projectId: string;
|
|
983
|
+
label: string;
|
|
984
|
+
kind: EditHistoryKind;
|
|
985
|
+
coalesceKey?: string;
|
|
986
|
+
/** Per-entry coalesce window override (ms). Falls back to the reducer default. */
|
|
987
|
+
coalesceMs?: number;
|
|
988
|
+
createdAt: number;
|
|
989
|
+
files: Record<string, EditHistoryFileSnapshot>;
|
|
990
|
+
}
|
|
991
|
+
interface EditHistoryState {
|
|
992
|
+
version: 1;
|
|
993
|
+
updatedAt: number;
|
|
994
|
+
undo: EditHistoryEntry[];
|
|
995
|
+
redo: EditHistoryEntry[];
|
|
996
|
+
}
|
|
997
|
+
interface BuildEditHistoryEntryInput {
|
|
998
|
+
id: string;
|
|
999
|
+
projectId: string;
|
|
1000
|
+
label: string;
|
|
1001
|
+
kind?: EditHistoryKind;
|
|
1002
|
+
coalesceKey?: string;
|
|
1003
|
+
coalesceMs?: number;
|
|
1004
|
+
now: number;
|
|
1005
|
+
files: Record<string, {
|
|
1006
|
+
before: string;
|
|
1007
|
+
after: string;
|
|
1008
|
+
}>;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
interface SdkSessionPublication {
|
|
1012
|
+
candidate: Composition;
|
|
1013
|
+
expectedSession: Composition;
|
|
1014
|
+
targetPath: string;
|
|
1015
|
+
}
|
|
1016
|
+
type SdkSessionPublicationResult = "published" | "rejected-active-target" | "rejected-inactive-target";
|
|
1017
|
+
type PublishSdkSession = (publication: SdkSessionPublication) => SdkSessionPublicationResult;
|
|
1018
|
+
|
|
1019
|
+
type TimelineLayerDropPlacement = {
|
|
1020
|
+
type: "onto";
|
|
1021
|
+
layerId: string;
|
|
1022
|
+
} | {
|
|
1023
|
+
type: "between";
|
|
1024
|
+
beforeLayerId: string;
|
|
1025
|
+
afterLayerId: string;
|
|
1026
|
+
} | {
|
|
1027
|
+
type: "above";
|
|
1028
|
+
layerId: string;
|
|
1029
|
+
} | {
|
|
1030
|
+
type: "below";
|
|
1031
|
+
layerId: string;
|
|
1032
|
+
};
|
|
1033
|
+
interface TimelineStackingZIndexChange {
|
|
1034
|
+
key: string;
|
|
1035
|
+
zIndex: number;
|
|
1036
|
+
domId?: string;
|
|
1037
|
+
selector?: string;
|
|
1038
|
+
selectorIndex?: number;
|
|
1039
|
+
sourceFile?: string;
|
|
1040
|
+
}
|
|
1041
|
+
interface TimelineStackingReorderIntent {
|
|
1042
|
+
contextKey: string;
|
|
1043
|
+
placement: TimelineLayerDropPlacement;
|
|
1044
|
+
zIndexChanges: TimelineStackingZIndexChange[];
|
|
1045
|
+
}
|
|
1046
|
+
|
|
708
1047
|
type BlockedTimelineEditIntent = "move" | "resize-start" | "resize-end";
|
|
709
1048
|
|
|
1049
|
+
/**
|
|
1050
|
+
* Durability report for a patch-batches commit. `durable === false` means the
|
|
1051
|
+
* server could not locate at least one patch target on disk — the preview was
|
|
1052
|
+
* reloaded to reconverge, and dependent follow-up writes (the z→lane timeline
|
|
1053
|
+
* mirror) must be skipped. `allMatched` retains the underlying match detail.
|
|
1054
|
+
* `changed === false` means no source file was written: every patch was a
|
|
1055
|
+
* byte-identical no-op, or the atomic gesture was refused before any write.
|
|
1056
|
+
*/
|
|
1057
|
+
interface DomEditPatchBatchesResult {
|
|
1058
|
+
durable: boolean;
|
|
1059
|
+
allMatched: boolean;
|
|
1060
|
+
changed: boolean;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
/** A host's verdict on one element: editable, or blocked with a reason to show. */
|
|
1064
|
+
type TimelineEditPermission = true | {
|
|
1065
|
+
blocked: true;
|
|
1066
|
+
reason: string;
|
|
1067
|
+
};
|
|
1068
|
+
type CanEditTimelineElement = (element: TimelineElement) => TimelineEditPermission;
|
|
1069
|
+
|
|
1070
|
+
interface RecordEditInput$1 {
|
|
1071
|
+
label: string;
|
|
1072
|
+
kind: EditHistoryKind;
|
|
1073
|
+
coalesceKey?: string;
|
|
1074
|
+
files: Record<string, {
|
|
1075
|
+
before: string;
|
|
1076
|
+
after: string;
|
|
1077
|
+
}>;
|
|
1078
|
+
}
|
|
1079
|
+
type TimelineZIndexReorderCommit = (entries: Array<{
|
|
1080
|
+
element: HTMLElement;
|
|
1081
|
+
zIndex: number;
|
|
1082
|
+
id?: string;
|
|
1083
|
+
selector?: string;
|
|
1084
|
+
selectorIndex?: number;
|
|
1085
|
+
sourceFile: string;
|
|
1086
|
+
key?: string;
|
|
1087
|
+
}>, coalesceKey?: string) => Promise<DomEditPatchBatchesResult | undefined | void>;
|
|
1088
|
+
interface UseTimelineEditingOptions {
|
|
1089
|
+
projectId: string | null;
|
|
1090
|
+
activeCompPath: string | null;
|
|
1091
|
+
timelineElements: TimelineElement[];
|
|
1092
|
+
showToast: (message: string, tone?: "error" | "info") => void;
|
|
1093
|
+
writeProjectFile: (path: string, content: string, expectedContent?: string) => Promise<void>;
|
|
1094
|
+
observeProjectFileVersion?: (path: string, version: string | null) => void;
|
|
1095
|
+
recordEdit: (input: RecordEditInput$1) => Promise<void>;
|
|
1096
|
+
reloadPreview: () => void;
|
|
1097
|
+
previewIframeRef: RefObject<HTMLIFrameElement | null>;
|
|
1098
|
+
pendingTimelineEditPathRef: MutableRefObject<Set<string>>;
|
|
1099
|
+
uploadProjectFiles: (files: Iterable<File>, dir?: string) => Promise<string[]>;
|
|
1100
|
+
isRecordingRef?: RefObject<boolean>;
|
|
1101
|
+
/** Stage 7 §3.2: SDK session for routing timing ops through setTiming. */
|
|
1102
|
+
sdkSession?: Composition | null;
|
|
1103
|
+
/** Publish a fully persisted candidate SDK session. */
|
|
1104
|
+
publishSdkSession?: PublishSdkSession;
|
|
1105
|
+
/** Resync the SDK session after a server-authoritative timeline write. */
|
|
1106
|
+
forceReloadSdkSession?: () => void;
|
|
1107
|
+
/** Reparse authored animations after a timing rewrite changes their positions. */
|
|
1108
|
+
invalidateGsapCache?: () => void;
|
|
1109
|
+
handleDomZIndexReorderCommitRef?: MutableRefObject<TimelineZIndexReorderCommit | null>;
|
|
1110
|
+
/** Refuses a hand edit at the persist boundary when set; absent = Studio unchanged. */
|
|
1111
|
+
canEdit?: CanEditTimelineElement;
|
|
1112
|
+
}
|
|
1113
|
+
/** What a timeline move commits: the new start and track, plus the z-index
|
|
1114
|
+
* reorder a vertical drag resolves to (absent for a pure horizontal move). */
|
|
1115
|
+
type TimelineMoveUpdates = Pick<TimelineElement, "start" | "track"> & {
|
|
1116
|
+
stackingReorder?: TimelineStackingReorderIntent | null;
|
|
1117
|
+
};
|
|
1118
|
+
|
|
1119
|
+
interface TimelineGroupMoveChange {
|
|
1120
|
+
element: TimelineElement;
|
|
1121
|
+
start: number;
|
|
1122
|
+
track?: number;
|
|
1123
|
+
}
|
|
1124
|
+
interface TimelineGroupResizeChange {
|
|
1125
|
+
element: TimelineElement;
|
|
1126
|
+
start: number;
|
|
1127
|
+
duration: number;
|
|
1128
|
+
playbackStart?: number;
|
|
1129
|
+
}
|
|
1130
|
+
interface TimelineGroupCommitOptions {
|
|
1131
|
+
beforeTiming?: Promise<void>;
|
|
1132
|
+
coalesceKey?: string;
|
|
1133
|
+
/** Per-entry undo coalesce window override (ms) — see EditHistoryEntry.coalesceMs. */
|
|
1134
|
+
coalesceMs?: number;
|
|
1135
|
+
/** Overrides the default "Move timeline clips" undo-history label. Coalescing
|
|
1136
|
+
* keeps the LAST entry's label (editHistory.ts), so a mechanical follow-up
|
|
1137
|
+
* move folded into another gesture's coalesceKey (e.g. the ripple after a
|
|
1138
|
+
* delete) should carry that gesture's own label, not its own. */
|
|
1139
|
+
label?: string;
|
|
1140
|
+
/** Skips this call's own generic failure toast (the error is still logged
|
|
1141
|
+
* to the console) — for a caller that shows its own more specific message
|
|
1142
|
+
* on the same failure, so the user isn't told about one action twice. */
|
|
1143
|
+
suppressFailureToast?: boolean;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
710
1146
|
type TimelineMoveOperation = "timing" | "lane-reorder" | "track-insert";
|
|
711
1147
|
|
|
712
1148
|
interface TimelineKeyframeTarget {
|
|
@@ -991,10 +1427,8 @@ type RenderClipContent = (element: TimelineElement, style: {
|
|
|
991
1427
|
label: string;
|
|
992
1428
|
}) => ReactNode;
|
|
993
1429
|
interface EditorShellProps extends TimelineEditCallbackDeps {
|
|
994
|
-
/**
|
|
995
|
-
|
|
996
|
-
/** Right panel (inspector/design) or null when collapsed, in the top row. */
|
|
997
|
-
right: ReactNode;
|
|
1430
|
+
/** Dock.Panel elements for every panel except the built-in preview and timeline. */
|
|
1431
|
+
panels: ReactNode;
|
|
998
1432
|
timelineToolbar: ReactNode;
|
|
999
1433
|
renderClipContent: RenderClipContent;
|
|
1000
1434
|
handleTimelineElementDelete: (element: TimelineElement) => Promise<void> | void;
|
|
@@ -1018,9 +1452,13 @@ interface EditorShellProps extends TimelineEditCallbackDeps {
|
|
|
1018
1452
|
isGestureRecording?: boolean;
|
|
1019
1453
|
recordingState?: GestureRecordingState;
|
|
1020
1454
|
onToggleRecording?: () => void;
|
|
1455
|
+
/**
|
|
1456
|
+
* Host layer over the preview, positioned with `usePreviewCompositionRect`. Hidden in
|
|
1457
|
+
* fullscreen and during a block preview; below the selection overlay past z-index 10.
|
|
1458
|
+
*/
|
|
1021
1459
|
gestureOverlay?: ReactNode;
|
|
1022
1460
|
}
|
|
1023
|
-
declare function EditorShell({
|
|
1461
|
+
declare function EditorShell({ panels, timelineToolbar, renderClipContent, handleTimelineElementDelete, handleTimelineAssetDrop, handleTimelineBlockDrop, handleTimelineCompositionDrop, handlePreviewBlockDrop, handleTimelineFileDrop, handleTimelineElementMove, handleTimelineElementsMove, handleTimelineElementResize, handleTimelineGroupResize, handleToggleTrackHidden, setAudioGroupAttribute, handleGroupClips, setElementFxAttribute, handleBlockedTimelineEdit, handleTimelineElementSplit, handleRazorSplit, handleRazorSplitAll, onCopyClip, onPasteClip, onDuplicateClip, canPasteClip, setCompIdToSrc, setCompositionLoading, shouldShowMotionPath, shouldShowSelectedDomBounds, isGestureRecording, recordingState, onToggleRecording, blockPreview, gestureOverlay, }: EditorShellProps): react_jsx_runtime.JSX.Element;
|
|
1024
1462
|
|
|
1025
1463
|
interface NLEPreviewProps {
|
|
1026
1464
|
projectId: string;
|
|
@@ -1054,6 +1492,21 @@ interface CompositionBreadcrumbProps {
|
|
|
1054
1492
|
}
|
|
1055
1493
|
declare function CompositionBreadcrumb({ stack, onNavigate }: CompositionBreadcrumbProps): react_jsx_runtime.JSX.Element | null;
|
|
1056
1494
|
|
|
1495
|
+
interface DomEditCompositionRect {
|
|
1496
|
+
left: number;
|
|
1497
|
+
top: number;
|
|
1498
|
+
width: number;
|
|
1499
|
+
height: number;
|
|
1500
|
+
scaleX: number;
|
|
1501
|
+
scaleY: number;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
/**
|
|
1505
|
+
* Where the composition sits inside `overlayRef`, in overlay pixels, plus the scale from
|
|
1506
|
+
* composition units to pixels. Follows the live preview iframe across reloads.
|
|
1507
|
+
*/
|
|
1508
|
+
declare function usePreviewCompositionRect(overlayRef: RefObject<HTMLDivElement | null>): DomEditCompositionRect;
|
|
1509
|
+
|
|
1057
1510
|
interface SourceEditorProps {
|
|
1058
1511
|
content: string;
|
|
1059
1512
|
filePath?: string;
|
|
@@ -1273,6 +1726,117 @@ interface AskAgentModalProps {
|
|
|
1273
1726
|
}
|
|
1274
1727
|
declare function AskAgentModal({ selectionLabel, contextPreview, anchorPoint, onSubmit, onClose, }: AskAgentModalProps): react_jsx_runtime.JSX.Element;
|
|
1275
1728
|
|
|
1729
|
+
/**
|
|
1730
|
+
* What the dev server knows about this machine's FFmpeg, as reported by
|
|
1731
|
+
* `GET /api/environment/ffmpeg`. Studio asks when the Render panel opens so a
|
|
1732
|
+
* missing encoder is a prompt with an install command, not a failed export an
|
|
1733
|
+
* hour into the work.
|
|
1734
|
+
*/
|
|
1735
|
+
interface FfmpegStatus {
|
|
1736
|
+
ok: boolean;
|
|
1737
|
+
/** Short headline, e.g. "FFmpeg not found". Absent when ok. */
|
|
1738
|
+
title?: string;
|
|
1739
|
+
/** Why it cannot run, in the server's words. Absent when ok. */
|
|
1740
|
+
detail?: string;
|
|
1741
|
+
/** Prose remediation, including the manual route where one exists. */
|
|
1742
|
+
hint?: string;
|
|
1743
|
+
/** A single pasteable install command, when this platform has one. */
|
|
1744
|
+
command?: string;
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
interface RenderJob {
|
|
1748
|
+
id: string;
|
|
1749
|
+
status: "rendering" | "complete" | "failed" | "cancelled";
|
|
1750
|
+
progress: number;
|
|
1751
|
+
stage?: string;
|
|
1752
|
+
error?: string;
|
|
1753
|
+
filename: string;
|
|
1754
|
+
createdAt: number;
|
|
1755
|
+
durationMs?: number;
|
|
1756
|
+
}
|
|
1757
|
+
type ResolutionPreset = CanvasResolution;
|
|
1758
|
+
interface StartRenderOptions {
|
|
1759
|
+
fps?: number;
|
|
1760
|
+
quality?: "draft" | "standard" | "high";
|
|
1761
|
+
format?: "mp4" | "webm" | "mov";
|
|
1762
|
+
/** `"auto"` (default) renders at the composition's authored dimensions. */
|
|
1763
|
+
resolution?: ResolutionPreset | "auto";
|
|
1764
|
+
/**
|
|
1765
|
+
* Render a specific composition file. Omit it to render the composition the
|
|
1766
|
+
* user currently has open — only the sidebar's per-composition Render button
|
|
1767
|
+
* names one, because it renders a card the user is not looking at.
|
|
1768
|
+
*/
|
|
1769
|
+
composition?: string;
|
|
1770
|
+
/**
|
|
1771
|
+
* Composition-variable overrides ({variableId: value}), forwarded to the
|
|
1772
|
+
* render route and injected as window.__hfVariables — the same channel
|
|
1773
|
+
* `hyperframes render --variables` uses.
|
|
1774
|
+
*/
|
|
1775
|
+
variables?: Record<string, unknown>;
|
|
1776
|
+
}
|
|
1777
|
+
declare function useRenderQueue(projectId: string | null, activeCompPathRef: {
|
|
1778
|
+
current: string | null;
|
|
1779
|
+
}): {
|
|
1780
|
+
jobs: RenderJob[];
|
|
1781
|
+
isRendering: boolean;
|
|
1782
|
+
loadError: string | null;
|
|
1783
|
+
actionError: string | null;
|
|
1784
|
+
dismissActionError: () => void;
|
|
1785
|
+
reloadRenders: () => Promise<void>;
|
|
1786
|
+
deleteRender: (jobId: string) => Promise<void>;
|
|
1787
|
+
cancelRender: (jobId: string) => Promise<void>;
|
|
1788
|
+
clearCompleted: () => void;
|
|
1789
|
+
startRender: (options: unknown) => Promise<void>;
|
|
1790
|
+
ffmpeg: FfmpegStatus | null;
|
|
1791
|
+
ffmpegMissing: boolean;
|
|
1792
|
+
ffmpegChecking: boolean;
|
|
1793
|
+
recheckFfmpeg: () => void;
|
|
1794
|
+
};
|
|
1795
|
+
|
|
1796
|
+
interface CompositionDimensions {
|
|
1797
|
+
width: number;
|
|
1798
|
+
height: number;
|
|
1799
|
+
}
|
|
1800
|
+
type StartRenderHandler = (format: "mp4" | "webm" | "mov", quality: "draft" | "standard" | "high", resolution: ResolutionPreset | "auto", fps: 24 | 30 | 60) => void | Promise<void>;
|
|
1801
|
+
interface RenderQueueProps {
|
|
1802
|
+
jobs: RenderJob[];
|
|
1803
|
+
projectId: string;
|
|
1804
|
+
onDelete: (jobId: string) => void;
|
|
1805
|
+
onCancel?: (jobId: string) => void;
|
|
1806
|
+
onClearCompleted: () => void;
|
|
1807
|
+
onStartRender: StartRenderHandler;
|
|
1808
|
+
isRendering: boolean;
|
|
1809
|
+
/** History fetch failure (null when the last load succeeded). */
|
|
1810
|
+
loadError?: string | null;
|
|
1811
|
+
/** Retry a failed history load. */
|
|
1812
|
+
onRetryLoad?: () => void;
|
|
1813
|
+
/** Failure of a delete/cancel action, shown inline until dismissed. */
|
|
1814
|
+
actionError?: string | null;
|
|
1815
|
+
onDismissActionError?: () => void;
|
|
1816
|
+
/**
|
|
1817
|
+
* Authored dimensions of the active composition. Used to pick the
|
|
1818
|
+
* matching preset (landscape / portrait / square) when the user selects
|
|
1819
|
+
* a 1080p or 4K scale. `null` falls back to landscape (legacy default).
|
|
1820
|
+
*/
|
|
1821
|
+
compositionDimensions?: CompositionDimensions | null;
|
|
1822
|
+
/**
|
|
1823
|
+
* Encoder availability, owned by useRenderQueue so the panel's Export button
|
|
1824
|
+
* and the header's agree. `null` means "no answer", not "missing".
|
|
1825
|
+
*/
|
|
1826
|
+
ffmpeg: FfmpegStatus | null;
|
|
1827
|
+
ffmpegChecking: boolean;
|
|
1828
|
+
onRecheckFfmpeg: () => void;
|
|
1829
|
+
}
|
|
1830
|
+
declare const RenderQueue: react.NamedExoticComponent<RenderQueueProps>;
|
|
1831
|
+
|
|
1832
|
+
interface PersistedRenderSettings {
|
|
1833
|
+
format: "mp4" | "webm" | "mov";
|
|
1834
|
+
quality: "draft" | "standard" | "high";
|
|
1835
|
+
fps: 24 | 30 | 60;
|
|
1836
|
+
}
|
|
1837
|
+
declare function getPersistedRenderSettings(): PersistedRenderSettings;
|
|
1838
|
+
declare function persistRenderSettings(format: PersistedRenderSettings["format"], quality: PersistedRenderSettings["quality"], fps: PersistedRenderSettings["fps"]): void;
|
|
1839
|
+
|
|
1276
1840
|
interface PickedElement {
|
|
1277
1841
|
id: string | null;
|
|
1278
1842
|
tagName: string;
|
|
@@ -1348,4 +1912,236 @@ declare function findElementBlock(html: string, elementId: string): {
|
|
|
1348
1912
|
isSelfClosing: boolean;
|
|
1349
1913
|
} | null;
|
|
1350
1914
|
|
|
1351
|
-
|
|
1915
|
+
interface EditHistoryStorageAdapter {
|
|
1916
|
+
get(projectId: string): Promise<EditHistoryState | null>;
|
|
1917
|
+
set(projectId: string, state: EditHistoryState): Promise<void>;
|
|
1918
|
+
delete(projectId: string): Promise<void>;
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
interface RecordEditInput {
|
|
1922
|
+
label: string;
|
|
1923
|
+
kind: EditHistoryKind;
|
|
1924
|
+
coalesceKey?: string;
|
|
1925
|
+
coalesceMs?: number;
|
|
1926
|
+
files: BuildEditHistoryEntryInput["files"];
|
|
1927
|
+
}
|
|
1928
|
+
interface ApplyCallbacks {
|
|
1929
|
+
readFile: (path: string) => Promise<string>;
|
|
1930
|
+
writeFile: (path: string, content: string) => Promise<void>;
|
|
1931
|
+
serialize?: <T>(paths: readonly string[], task: () => Promise<T>) => Promise<T>;
|
|
1932
|
+
}
|
|
1933
|
+
interface UsePersistentEditHistoryOptions {
|
|
1934
|
+
projectId: string | null;
|
|
1935
|
+
storage?: EditHistoryStorageAdapter;
|
|
1936
|
+
now?: () => number;
|
|
1937
|
+
}
|
|
1938
|
+
/**
|
|
1939
|
+
* Per-file content the restore just applied. `restored` is the bytes written to
|
|
1940
|
+
* disk (the undo/redo target); `previous` is what was on disk immediately before
|
|
1941
|
+
* (the current live preview state). The undo preview-sync diffs these to decide
|
|
1942
|
+
* whether the restore is soft-reloadable (attributes/style/GSAP-script only) or
|
|
1943
|
+
* needs a full iframe reload.
|
|
1944
|
+
*/
|
|
1945
|
+
interface ApplyRestoredFile {
|
|
1946
|
+
previous: string;
|
|
1947
|
+
restored: string;
|
|
1948
|
+
}
|
|
1949
|
+
interface ApplyResult {
|
|
1950
|
+
ok: boolean;
|
|
1951
|
+
reason?: "empty" | "content-mismatch";
|
|
1952
|
+
label?: string;
|
|
1953
|
+
paths?: string[];
|
|
1954
|
+
files?: Record<string, ApplyRestoredFile>;
|
|
1955
|
+
}
|
|
1956
|
+
declare function usePersistentEditHistory(options: UsePersistentEditHistoryOptions): {
|
|
1957
|
+
recordEdit: (input: RecordEditInput) => Promise<void>;
|
|
1958
|
+
undo: (callbacks: ApplyCallbacks) => Promise<ApplyResult>;
|
|
1959
|
+
redo: (callbacks: ApplyCallbacks) => Promise<ApplyResult>;
|
|
1960
|
+
canUndo: boolean;
|
|
1961
|
+
canRedo: boolean;
|
|
1962
|
+
undoLabel: string;
|
|
1963
|
+
redoLabel: string;
|
|
1964
|
+
undoPaths: string[];
|
|
1965
|
+
redoPaths: string[];
|
|
1966
|
+
state: EditHistoryState;
|
|
1967
|
+
loaded: boolean;
|
|
1968
|
+
};
|
|
1969
|
+
|
|
1970
|
+
declare function useTimelineEditing({ projectId, activeCompPath, timelineElements, showToast, writeProjectFile, observeProjectFileVersion, recordEdit, reloadPreview, previewIframeRef, pendingTimelineEditPathRef, uploadProjectFiles, isRecordingRef, sdkSession, publishSdkSession, forceReloadSdkSession, invalidateGsapCache, handleDomZIndexReorderCommitRef, canEdit, }: UseTimelineEditingOptions): {
|
|
1971
|
+
handleTimelineElementMove: (element: TimelineElement, updates: TimelineMoveUpdates) => Promise<void>;
|
|
1972
|
+
handleTimelineElementResize: (element: TimelineElement, updates: Pick<TimelineElement, "start" | "duration" | "playbackStart">) => Promise<void>;
|
|
1973
|
+
handleToggleTrackHidden: (track: number, hidden: boolean, displayNumber?: number | null | undefined) => Promise<void>;
|
|
1974
|
+
handleToggleElementHidden: (elementKey: string | readonly string[], hidden: boolean) => Promise<void>;
|
|
1975
|
+
handleAutoGroupCarveSources: (clipIds: readonly string[], groupId: string, groupLabel?: string | undefined) => Promise<void>;
|
|
1976
|
+
setAudioGroupAttribute: {
|
|
1977
|
+
setQuiet: (groupId: string, attr: string, value: string | null, label: string) => Promise<void>;
|
|
1978
|
+
setLive: (groupId: string, attr: string, value: string | null) => void;
|
|
1979
|
+
};
|
|
1980
|
+
setElementFxAttribute: {
|
|
1981
|
+
setQuiet: (element: TimelineElement, attr: string, value: string | null, label: string) => Promise<void>;
|
|
1982
|
+
setLive: (element: TimelineElement, attr: string, value: string | null) => void;
|
|
1983
|
+
};
|
|
1984
|
+
handleTimelineElementDelete: (element: TimelineElement) => Promise<void>;
|
|
1985
|
+
handleTimelineElementsDelete: (selection: TimelineElement[]) => Promise<void>;
|
|
1986
|
+
handleTimelineElementSplit: (element: TimelineElement, splitTime: number) => Promise<void>;
|
|
1987
|
+
handleRazorSplit: (element: TimelineElement, splitTime: number) => Promise<void>;
|
|
1988
|
+
handleRazorSplitAll: (splitTime: number) => Promise<void>;
|
|
1989
|
+
handleTimelineAssetDrop: (assetPath: string, placement: TimelineDropPlacement, durationOverride?: number | undefined) => Promise<void>;
|
|
1990
|
+
handleTimelineFileDrop: (files: File[], placement?: TimelineDropPlacement | undefined) => Promise<void>;
|
|
1991
|
+
handleTimelineCompositionDrop: (sourcePath: string, placement: Pick<TimelineElement, "track" | "start">) => Promise<void>;
|
|
1992
|
+
handleBlockedTimelineEdit: (element: TimelineElement) => void;
|
|
1993
|
+
handleTimelineGroupMove: (changes: TimelineGroupMoveChange[], options?: TimelineGroupCommitOptions | undefined) => Promise<void>;
|
|
1994
|
+
handleTimelineGroupResize: (changes: TimelineGroupResizeChange[], options?: TimelineGroupCommitOptions | undefined) => Promise<void>;
|
|
1995
|
+
};
|
|
1996
|
+
|
|
1997
|
+
declare class StudioSaveHttpError extends Error {
|
|
1998
|
+
readonly statusCode: number;
|
|
1999
|
+
readonly alreadyToasted: boolean;
|
|
2000
|
+
constructor(message: string, statusCode: number, options?: {
|
|
2001
|
+
alreadyToasted?: boolean;
|
|
2002
|
+
});
|
|
2003
|
+
}
|
|
2004
|
+
declare class StudioFileConflictError extends StudioSaveHttpError {
|
|
2005
|
+
readonly filePath: string;
|
|
2006
|
+
readonly currentVersion: string | null;
|
|
2007
|
+
readonly currentContent: string | null;
|
|
2008
|
+
readonly attemptedContent: string;
|
|
2009
|
+
constructor(input: {
|
|
2010
|
+
filePath: string;
|
|
2011
|
+
currentVersion: string | null;
|
|
2012
|
+
currentContent: string | null;
|
|
2013
|
+
attemptedContent: string;
|
|
2014
|
+
});
|
|
2015
|
+
}
|
|
2016
|
+
type StudioSaveDrainResult<Failure = unknown> = {
|
|
2017
|
+
status: "clean";
|
|
2018
|
+
} | {
|
|
2019
|
+
status: "conflict";
|
|
2020
|
+
error: StudioFileConflictError;
|
|
2021
|
+
} | {
|
|
2022
|
+
status: "failed";
|
|
2023
|
+
error: Failure;
|
|
2024
|
+
};
|
|
2025
|
+
|
|
2026
|
+
type StudioPendingEditsDrainResult = StudioSaveDrainResult;
|
|
2027
|
+
declare function flushStudioPendingEdits(): Promise<StudioPendingEditsDrainResult>;
|
|
2028
|
+
|
|
2029
|
+
interface HistoryResult {
|
|
2030
|
+
ok: boolean;
|
|
2031
|
+
reason?: string;
|
|
2032
|
+
label?: string;
|
|
2033
|
+
paths?: string[];
|
|
2034
|
+
/** Per-file restored/previous content, used to soft-apply the preview. */
|
|
2035
|
+
files?: Record<string, {
|
|
2036
|
+
previous: string;
|
|
2037
|
+
restored: string;
|
|
2038
|
+
}>;
|
|
2039
|
+
}
|
|
2040
|
+
interface HistoryFileCallbacks {
|
|
2041
|
+
readFile: (path: string) => Promise<string>;
|
|
2042
|
+
writeFile: (path: string, content: string) => Promise<void>;
|
|
2043
|
+
serialize?: <T>(paths: readonly string[], task: () => Promise<T>) => Promise<T>;
|
|
2044
|
+
}
|
|
2045
|
+
interface EditHistoryHandle {
|
|
2046
|
+
undo: (cb: HistoryFileCallbacks) => Promise<HistoryResult>;
|
|
2047
|
+
redo: (cb: HistoryFileCallbacks) => Promise<HistoryResult>;
|
|
2048
|
+
state: {
|
|
2049
|
+
undo: ReadonlyArray<{
|
|
2050
|
+
createdAt: number;
|
|
2051
|
+
}>;
|
|
2052
|
+
redo: ReadonlyArray<{
|
|
2053
|
+
createdAt: number;
|
|
2054
|
+
}>;
|
|
2055
|
+
};
|
|
2056
|
+
}
|
|
2057
|
+
interface UseEditHistoryActionsOptions {
|
|
2058
|
+
editHistory: Pick<EditHistoryHandle, "undo" | "redo">;
|
|
2059
|
+
readOptionalProjectFile: (path: string) => Promise<string>;
|
|
2060
|
+
readProjectFile: (path: string) => Promise<string>;
|
|
2061
|
+
writeProjectFile: (path: string, content: string) => Promise<void>;
|
|
2062
|
+
showToast: (message: string, tone?: "error" | "info") => void;
|
|
2063
|
+
syncHistoryPreviewAfterApply: (restore: Pick<HistoryResult, "paths" | "files">) => Promise<void>;
|
|
2064
|
+
waitForPendingDomEditSaves: () => Promise<void>;
|
|
2065
|
+
onAfterUndoRedo?: () => void;
|
|
2066
|
+
/** Active composition path — decides whether undo/redo must resync the SDK session. */
|
|
2067
|
+
activeCompPath?: string | null;
|
|
2068
|
+
/** Reloads the SDK session after a revert of the active comp, past the self-write suppress window. */
|
|
2069
|
+
forceReloadSdkSession?: () => void;
|
|
2070
|
+
}
|
|
2071
|
+
/** Applies one persisted file-history step: the single owner of undo/redo over project files. */
|
|
2072
|
+
declare function useEditHistoryActions({ editHistory, readOptionalProjectFile, readProjectFile, writeProjectFile, showToast, syncHistoryPreviewAfterApply, waitForPendingDomEditSaves, onAfterUndoRedo, activeCompPath, forceReloadSdkSession, }: UseEditHistoryActionsOptions): {
|
|
2073
|
+
undo: () => Promise<void>;
|
|
2074
|
+
redo: () => Promise<void>;
|
|
2075
|
+
};
|
|
2076
|
+
|
|
2077
|
+
interface UseProjectFileWriterOptions {
|
|
2078
|
+
projectId: string | null;
|
|
2079
|
+
}
|
|
2080
|
+
declare function useProjectFileWriter({ projectId }: UseProjectFileWriterOptions): {
|
|
2081
|
+
fileVersions: Map<string, string | null>;
|
|
2082
|
+
readProjectFile: (path: string) => Promise<string>;
|
|
2083
|
+
writeProjectFile: (path: string, content: string, expectedContent?: string) => Promise<void>;
|
|
2084
|
+
readOptionalProjectFile: (path: string) => Promise<string>;
|
|
2085
|
+
observeProjectFileVersion: (path: string, version: string | null) => void;
|
|
2086
|
+
};
|
|
2087
|
+
|
|
2088
|
+
type ExternalFileChangeBlockedState = {
|
|
2089
|
+
status: "conflict";
|
|
2090
|
+
generation: number;
|
|
2091
|
+
error: StudioFileConflictError;
|
|
2092
|
+
payload: unknown;
|
|
2093
|
+
} | {
|
|
2094
|
+
status: "failed";
|
|
2095
|
+
generation: number;
|
|
2096
|
+
path: string;
|
|
2097
|
+
error: unknown;
|
|
2098
|
+
payload: unknown;
|
|
2099
|
+
studioContent: string | null;
|
|
2100
|
+
recovered: boolean;
|
|
2101
|
+
};
|
|
2102
|
+
interface ExternalFileChangeCoordinatorHandle {
|
|
2103
|
+
blocked: ExternalFileChangeBlockedState | null;
|
|
2104
|
+
retry: () => Promise<void>;
|
|
2105
|
+
useExternalFile: () => Promise<void>;
|
|
2106
|
+
keepStudioFile: () => Promise<void>;
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
declare function ExternalFileConflictBanner({ coordinator, }: {
|
|
2110
|
+
coordinator: ExternalFileChangeCoordinatorHandle;
|
|
2111
|
+
}): react_jsx_runtime.JSX.Element | null;
|
|
2112
|
+
|
|
2113
|
+
interface TimelinePaneProps {
|
|
2114
|
+
/** Slot rendered above the timeline tracks (toolbar with split, delete, zoom) */
|
|
2115
|
+
timelineToolbar?: ReactNode;
|
|
2116
|
+
/** Slot rendered below the timeline tracks */
|
|
2117
|
+
timelineFooter?: ReactNode;
|
|
2118
|
+
/** Slot for a host's own overlay spanning the whole timeline area (e.g. a draft/ghost
|
|
2119
|
+
* clip), positioned absolutely the same way PreviewPane's previewOverlay is. */
|
|
2120
|
+
timelineOverlay?: ReactNode;
|
|
2121
|
+
/** Custom clip content renderer for timeline (thumbnails, waveforms, etc.) */
|
|
2122
|
+
renderClipContent?: (element: TimelineElement, style: {
|
|
2123
|
+
clip: string;
|
|
2124
|
+
label: string;
|
|
2125
|
+
}) => ReactNode;
|
|
2126
|
+
onFileDrop?: (files: File[], placement?: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
|
|
2127
|
+
onDeleteElement?: (element: TimelineElement) => Promise<void> | void;
|
|
2128
|
+
onAssetDrop?: (assetPath: string, placement: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
|
|
2129
|
+
onBlockDrop?: (blockName: string, placement: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
|
|
2130
|
+
onCompositionDrop?: (sourcePath: string, placement: Pick<TimelineElement, "start" | "track">) => Promise<void> | void;
|
|
2131
|
+
onBlockedEditAttempt?: (element: TimelineElement, intent: BlockedTimelineEditIntent) => void;
|
|
2132
|
+
onSelectTimelineElement?: (element: TimelineElement | null) => void;
|
|
2133
|
+
/** Copy/paste/duplicate act on the store's own selection, not a passed
|
|
2134
|
+
* element, so unlike onDeleteElement they need no composition-basis wrapper. */
|
|
2135
|
+
onCopyClip?: () => boolean;
|
|
2136
|
+
onPasteClip?: () => Promise<void>;
|
|
2137
|
+
onDuplicateClip?: () => Promise<boolean>;
|
|
2138
|
+
canPasteClip?: () => boolean;
|
|
2139
|
+
}
|
|
2140
|
+
declare function TimelinePane({ timelineToolbar, timelineFooter, timelineOverlay, renderClipContent, onFileDrop, onDeleteElement, onAssetDrop, onBlockDrop, onCompositionDrop, onBlockedEditAttempt, onSelectTimelineElement, onCopyClip, onPasteClip, onDuplicateClip, canPasteClip, }: TimelinePaneProps): react_jsx_runtime.JSX.Element;
|
|
2141
|
+
|
|
2142
|
+
declare function TimelineEditProvider({ value, children, }: {
|
|
2143
|
+
value: TimelineEditCallbacks;
|
|
2144
|
+
children: ReactNode;
|
|
2145
|
+
}): react_jsx_runtime.JSX.Element;
|
|
2146
|
+
|
|
2147
|
+
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, 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, Toggle, type ToggleProps, Tooltip, type UseEditHistoryActionsOptions, type UsePersistentEditHistoryOptions, type UseProjectFileWriterOptions, type UseTimelineEditingOptions, VideoThumbnail, applyPatch, buildPickerAgentContextPreview, buildPickerAgentPrompt, buttonBase, buttonVariants, cn, fieldBase, fieldText, findElementBlock, flushStudioPendingEdits, formatTime, getPersistedRenderSettings, liveTime, mergeStyleIntoTag, parseStyleString, persistRenderSettings, popupSurface, resolveIframe, resolveSourceFile, useEditHistoryActions, useElementPicker, usePersistentEditHistory, usePlayerStore, usePreviewCompositionRect, useProjectFileWriter, useRenderQueue, useTimelineEditing, useTimelinePlayer };
|