@hyperframes/studio 0.6.0-alpha.9 → 0.6.1

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 (111) hide show
  1. package/dist/assets/hyperframes-player-CzwFysqv.js +418 -0
  2. package/dist/assets/index-D1JDq7Gg.css +1 -0
  3. package/dist/assets/index-hYc4aP7M.js +117 -0
  4. package/dist/favicon.svg +14 -0
  5. package/dist/index.html +3 -2
  6. package/package.json +9 -9
  7. package/src/App.tsx +421 -4303
  8. package/src/captions/components/CaptionOverlay.tsx +13 -246
  9. package/src/captions/components/CaptionOverlayUtils.ts +221 -0
  10. package/src/components/AskAgentModal.tsx +120 -0
  11. package/src/components/StudioHeader.tsx +133 -0
  12. package/src/components/StudioLeftSidebar.tsx +125 -0
  13. package/src/components/StudioPreviewArea.tsx +167 -0
  14. package/src/components/StudioRightPanel.tsx +198 -0
  15. package/src/components/TimelineToolbar.tsx +89 -0
  16. package/src/components/editor/DomEditOverlay.tsx +88 -993
  17. package/src/components/editor/EaseCurveEditor.tsx +221 -0
  18. package/src/components/editor/FileTree.tsx +13 -621
  19. package/src/components/editor/FileTreeIcons.tsx +128 -0
  20. package/src/components/editor/FileTreeNodes.tsx +496 -0
  21. package/src/components/editor/MotionPanel.tsx +16 -390
  22. package/src/components/editor/MotionPanelFields.tsx +185 -0
  23. package/src/components/editor/PropertyPanel.test.ts +0 -49
  24. package/src/components/editor/PropertyPanel.tsx +132 -2763
  25. package/src/components/editor/domEditOverlayGeometry.ts +211 -0
  26. package/src/components/editor/domEditOverlayGestures.ts +138 -0
  27. package/src/components/editor/domEditOverlayStartGesture.ts +155 -0
  28. package/src/components/editor/domEditing.ts +44 -1117
  29. package/src/components/editor/domEditingAgentPrompt.ts +97 -0
  30. package/src/components/editor/domEditingDom.ts +266 -0
  31. package/src/components/editor/domEditingElement.ts +329 -0
  32. package/src/components/editor/domEditingLayers.ts +460 -0
  33. package/src/components/editor/domEditingTypes.ts +125 -0
  34. package/src/components/editor/manualEditingAvailability.test.ts +2 -2
  35. package/src/components/editor/manualEditingAvailability.ts +1 -1
  36. package/src/components/editor/manualEdits.ts +84 -1049
  37. package/src/components/editor/manualEditsDom.ts +436 -0
  38. package/src/components/editor/manualEditsParsing.ts +280 -0
  39. package/src/components/editor/manualEditsSnapshot.ts +333 -0
  40. package/src/components/editor/manualEditsTypes.ts +141 -0
  41. package/src/components/editor/propertyPanelColor.tsx +371 -0
  42. package/src/components/editor/propertyPanelFill.tsx +421 -0
  43. package/src/components/editor/propertyPanelFont.tsx +455 -0
  44. package/src/components/editor/propertyPanelHelpers.ts +401 -0
  45. package/src/components/editor/propertyPanelPrimitives.tsx +357 -0
  46. package/src/components/editor/propertyPanelSections.tsx +453 -0
  47. package/src/components/editor/propertyPanelStyleSections.tsx +411 -0
  48. package/src/components/editor/studioMotion.ts +47 -434
  49. package/src/components/editor/studioMotionOps.ts +299 -0
  50. package/src/components/editor/studioMotionTypes.ts +168 -0
  51. package/src/components/editor/useDomEditOverlayGestures.ts +393 -0
  52. package/src/components/editor/useDomEditOverlayRects.ts +207 -0
  53. package/src/components/nle/NLELayout.tsx +68 -155
  54. package/src/components/nle/NLEPreview.tsx +3 -0
  55. package/src/components/nle/useCompositionStack.ts +126 -0
  56. package/src/components/renders/RenderQueue.tsx +102 -31
  57. package/src/components/renders/useRenderQueue.ts +8 -2
  58. package/src/components/sidebar/LeftSidebar.tsx +186 -186
  59. package/src/contexts/DomEditContext.tsx +137 -0
  60. package/src/contexts/FileManagerContext.tsx +110 -0
  61. package/src/contexts/PanelLayoutContext.tsx +68 -0
  62. package/src/contexts/StudioContext.tsx +135 -0
  63. package/src/hooks/useAppHotkeys.ts +326 -0
  64. package/src/hooks/useAskAgentModal.ts +162 -0
  65. package/src/hooks/useCaptionDetection.ts +132 -0
  66. package/src/hooks/useCompositionDimensions.ts +25 -0
  67. package/src/hooks/useConsoleErrorCapture.ts +60 -0
  68. package/src/hooks/useDomEditCommits.ts +437 -0
  69. package/src/hooks/useDomEditSession.ts +342 -0
  70. package/src/hooks/useDomEditTextCommits.ts +330 -0
  71. package/src/hooks/useDomSelection.ts +398 -0
  72. package/src/hooks/useFileManager.ts +431 -0
  73. package/src/hooks/useFrameCapture.ts +77 -0
  74. package/src/hooks/useLintModal.ts +35 -0
  75. package/src/hooks/useManifestPersistence.ts +492 -0
  76. package/src/hooks/usePanelLayout.ts +68 -0
  77. package/src/hooks/usePreviewInteraction.ts +153 -0
  78. package/src/hooks/useRenderClipContent.ts +124 -0
  79. package/src/hooks/useTimelineEditing.ts +472 -0
  80. package/src/hooks/useToast.ts +20 -0
  81. package/src/player/components/Player.tsx +33 -2
  82. package/src/player/components/Timeline.test.ts +0 -8
  83. package/src/player/components/Timeline.tsx +196 -1518
  84. package/src/player/components/TimelineCanvas.tsx +434 -0
  85. package/src/player/components/TimelineClip.tsx +9 -244
  86. package/src/player/components/TimelineEmptyState.tsx +102 -0
  87. package/src/player/components/TimelineRuler.tsx +90 -0
  88. package/src/player/components/timelineIcons.tsx +49 -0
  89. package/src/player/components/timelineLayout.ts +215 -0
  90. package/src/player/components/timelineUtils.ts +211 -0
  91. package/src/player/components/useTimelineClipDrag.ts +388 -0
  92. package/src/player/components/useTimelinePlayhead.ts +200 -0
  93. package/src/player/components/useTimelineRangeSelection.ts +135 -0
  94. package/src/player/hooks/usePlaybackKeyboard.ts +171 -0
  95. package/src/player/hooks/useTimelinePlayer.ts +105 -1371
  96. package/src/player/hooks/useTimelineSyncCallbacks.ts +288 -0
  97. package/src/player/lib/playbackAdapter.ts +145 -0
  98. package/src/player/lib/playbackShortcuts.ts +68 -0
  99. package/src/player/lib/playbackTypes.ts +60 -0
  100. package/src/player/lib/timelineDOM.ts +373 -0
  101. package/src/player/lib/timelineElementHelpers.ts +303 -0
  102. package/src/player/lib/timelineIframeHelpers.ts +269 -0
  103. package/src/utils/domEditHelpers.ts +50 -0
  104. package/src/utils/studioFontHelpers.ts +83 -0
  105. package/src/utils/studioHelpers.ts +214 -0
  106. package/src/utils/studioPreviewHelpers.ts +185 -0
  107. package/src/utils/timelineDiscovery.ts +1 -1
  108. package/dist/assets/hyperframes-player-DjsVzYFP.js +0 -418
  109. package/dist/assets/index-14zH9lqh.css +0 -1
  110. package/dist/assets/index-DYCiFGWQ.js +0 -108
  111. package/src/player/components/TimelineClip.test.ts +0 -92
@@ -0,0 +1,137 @@
1
+ import { createContext, useContext, useMemo, type ReactNode } from "react";
2
+ import type { useDomEditSession } from "../hooks/useDomEditSession";
3
+
4
+ type DomEditValue = ReturnType<typeof useDomEditSession>;
5
+
6
+ const DomEditContext = createContext<DomEditValue | null>(null);
7
+
8
+ export function useDomEditContext(): DomEditValue {
9
+ const ctx = useContext(DomEditContext);
10
+ if (!ctx) throw new Error("useDomEditContext must be used within DomEditProvider");
11
+ return ctx;
12
+ }
13
+
14
+ export function DomEditProvider({
15
+ value: {
16
+ domEditSelection,
17
+ domEditGroupSelections,
18
+ domEditHoverSelection,
19
+ agentModalOpen,
20
+ agentModalAnchorPoint,
21
+ copiedAgentPrompt,
22
+ agentPromptSelectionContext,
23
+ domEditSelectionRef,
24
+ handleTimelineElementSelect,
25
+ handlePreviewCanvasMouseDown,
26
+ handlePreviewCanvasPointerMove,
27
+ handlePreviewCanvasPointerLeave,
28
+ applyDomSelection,
29
+ clearDomSelection,
30
+ handleDomStyleCommit,
31
+ handleDomPathOffsetCommit,
32
+ handleDomGroupPathOffsetCommit,
33
+ handleDomBoxSizeCommit,
34
+ handleDomRotationCommit,
35
+ handleDomManualEditsReset,
36
+ handleDomMotionCommit,
37
+ handleDomMotionClear,
38
+ handleDomTextCommit,
39
+ handleDomTextFieldStyleCommit,
40
+ handleDomAddTextField,
41
+ handleDomRemoveTextField,
42
+ handleAskAgent,
43
+ handleAgentModalSubmit,
44
+ handleBlockedDomMove,
45
+ handleDomManualDragStart,
46
+ handleDomEditElementDelete,
47
+ buildDomSelectionForTimelineElement,
48
+ resolveImportedFontAsset,
49
+ setAgentModalOpen,
50
+ setAgentPromptSelectionContext,
51
+ setAgentModalAnchorPoint,
52
+ },
53
+ children,
54
+ }: {
55
+ value: DomEditValue;
56
+ children: ReactNode;
57
+ }) {
58
+ const stable = useMemo<DomEditValue>(
59
+ () => ({
60
+ domEditSelection,
61
+ domEditGroupSelections,
62
+ domEditHoverSelection,
63
+ agentModalOpen,
64
+ agentModalAnchorPoint,
65
+ copiedAgentPrompt,
66
+ agentPromptSelectionContext,
67
+ domEditSelectionRef,
68
+ handleTimelineElementSelect,
69
+ handlePreviewCanvasMouseDown,
70
+ handlePreviewCanvasPointerMove,
71
+ handlePreviewCanvasPointerLeave,
72
+ applyDomSelection,
73
+ clearDomSelection,
74
+ handleDomStyleCommit,
75
+ handleDomPathOffsetCommit,
76
+ handleDomGroupPathOffsetCommit,
77
+ handleDomBoxSizeCommit,
78
+ handleDomRotationCommit,
79
+ handleDomManualEditsReset,
80
+ handleDomMotionCommit,
81
+ handleDomMotionClear,
82
+ handleDomTextCommit,
83
+ handleDomTextFieldStyleCommit,
84
+ handleDomAddTextField,
85
+ handleDomRemoveTextField,
86
+ handleAskAgent,
87
+ handleAgentModalSubmit,
88
+ handleBlockedDomMove,
89
+ handleDomManualDragStart,
90
+ handleDomEditElementDelete,
91
+ buildDomSelectionForTimelineElement,
92
+ resolveImportedFontAsset,
93
+ setAgentModalOpen,
94
+ setAgentPromptSelectionContext,
95
+ setAgentModalAnchorPoint,
96
+ }),
97
+ [
98
+ domEditSelection,
99
+ domEditGroupSelections,
100
+ domEditHoverSelection,
101
+ agentModalOpen,
102
+ agentModalAnchorPoint,
103
+ copiedAgentPrompt,
104
+ agentPromptSelectionContext,
105
+ domEditSelectionRef,
106
+ handleTimelineElementSelect,
107
+ handlePreviewCanvasMouseDown,
108
+ handlePreviewCanvasPointerMove,
109
+ handlePreviewCanvasPointerLeave,
110
+ applyDomSelection,
111
+ clearDomSelection,
112
+ handleDomStyleCommit,
113
+ handleDomPathOffsetCommit,
114
+ handleDomGroupPathOffsetCommit,
115
+ handleDomBoxSizeCommit,
116
+ handleDomRotationCommit,
117
+ handleDomManualEditsReset,
118
+ handleDomMotionCommit,
119
+ handleDomMotionClear,
120
+ handleDomTextCommit,
121
+ handleDomTextFieldStyleCommit,
122
+ handleDomAddTextField,
123
+ handleDomRemoveTextField,
124
+ handleAskAgent,
125
+ handleAgentModalSubmit,
126
+ handleBlockedDomMove,
127
+ handleDomManualDragStart,
128
+ handleDomEditElementDelete,
129
+ buildDomSelectionForTimelineElement,
130
+ resolveImportedFontAsset,
131
+ setAgentModalOpen,
132
+ setAgentPromptSelectionContext,
133
+ setAgentModalAnchorPoint,
134
+ ],
135
+ );
136
+ return <DomEditContext value={stable}>{children}</DomEditContext>;
137
+ }
@@ -0,0 +1,110 @@
1
+ import { createContext, useContext, useMemo, type ReactNode } from "react";
2
+ import type { useFileManager } from "../hooks/useFileManager";
3
+
4
+ type FileManagerValue = ReturnType<typeof useFileManager>;
5
+
6
+ const FileManagerContext = createContext<FileManagerValue | null>(null);
7
+
8
+ export function useFileManagerContext(): FileManagerValue {
9
+ const ctx = useContext(FileManagerContext);
10
+ if (!ctx) throw new Error("useFileManagerContext must be used within FileManagerProvider");
11
+ return ctx;
12
+ }
13
+
14
+ export function FileManagerProvider({
15
+ value: {
16
+ editingFile,
17
+ setEditingFile,
18
+ projectDir,
19
+ fileTree,
20
+ setFileTree,
21
+ editingPathRef,
22
+ projectIdRef,
23
+ saveTimerRef,
24
+ importedFontAssetsRef,
25
+ readProjectFile,
26
+ writeProjectFile,
27
+ readOptionalProjectFile,
28
+ handleFileSelect,
29
+ handleContentChange,
30
+ refreshFileTree,
31
+ uploadProjectFiles,
32
+ handleCreateFile,
33
+ handleCreateFolder,
34
+ handleDeleteFile,
35
+ handleRenameFile,
36
+ handleDuplicateFile,
37
+ handleMoveFile,
38
+ handleImportFiles,
39
+ handleImportFonts,
40
+ compositions,
41
+ assets,
42
+ fontAssets,
43
+ },
44
+ children,
45
+ }: {
46
+ value: FileManagerValue;
47
+ children: ReactNode;
48
+ }) {
49
+ const stable = useMemo<FileManagerValue>(
50
+ () => ({
51
+ editingFile,
52
+ setEditingFile,
53
+ projectDir,
54
+ fileTree,
55
+ setFileTree,
56
+ editingPathRef,
57
+ projectIdRef,
58
+ saveTimerRef,
59
+ importedFontAssetsRef,
60
+ readProjectFile,
61
+ writeProjectFile,
62
+ readOptionalProjectFile,
63
+ handleFileSelect,
64
+ handleContentChange,
65
+ refreshFileTree,
66
+ uploadProjectFiles,
67
+ handleCreateFile,
68
+ handleCreateFolder,
69
+ handleDeleteFile,
70
+ handleRenameFile,
71
+ handleDuplicateFile,
72
+ handleMoveFile,
73
+ handleImportFiles,
74
+ handleImportFonts,
75
+ compositions,
76
+ assets,
77
+ fontAssets,
78
+ }),
79
+ [
80
+ editingFile,
81
+ setEditingFile,
82
+ projectDir,
83
+ fileTree,
84
+ setFileTree,
85
+ editingPathRef,
86
+ projectIdRef,
87
+ saveTimerRef,
88
+ importedFontAssetsRef,
89
+ readProjectFile,
90
+ writeProjectFile,
91
+ readOptionalProjectFile,
92
+ handleFileSelect,
93
+ handleContentChange,
94
+ refreshFileTree,
95
+ uploadProjectFiles,
96
+ handleCreateFile,
97
+ handleCreateFolder,
98
+ handleDeleteFile,
99
+ handleRenameFile,
100
+ handleDuplicateFile,
101
+ handleMoveFile,
102
+ handleImportFiles,
103
+ handleImportFonts,
104
+ compositions,
105
+ assets,
106
+ fontAssets,
107
+ ],
108
+ );
109
+ return <FileManagerContext value={stable}>{children}</FileManagerContext>;
110
+ }
@@ -0,0 +1,68 @@
1
+ import { createContext, useContext, useMemo, type ReactNode } from "react";
2
+ import type { usePanelLayout } from "../hooks/usePanelLayout";
3
+
4
+ type PanelLayoutValue = ReturnType<typeof usePanelLayout>;
5
+
6
+ const PanelLayoutContext = createContext<PanelLayoutValue | null>(null);
7
+
8
+ export function usePanelLayoutContext(): PanelLayoutValue {
9
+ const ctx = useContext(PanelLayoutContext);
10
+ if (!ctx) throw new Error("usePanelLayoutContext must be used within PanelLayoutProvider");
11
+ return ctx;
12
+ }
13
+
14
+ export function PanelLayoutProvider({
15
+ value: {
16
+ leftWidth,
17
+ setLeftWidth,
18
+ rightWidth,
19
+ leftCollapsed,
20
+ setLeftCollapsed,
21
+ rightCollapsed,
22
+ setRightCollapsed,
23
+ rightPanelTab,
24
+ setRightPanelTab,
25
+ toggleLeftSidebar,
26
+ handlePanelResizeStart,
27
+ handlePanelResizeMove,
28
+ handlePanelResizeEnd,
29
+ },
30
+ children,
31
+ }: {
32
+ value: PanelLayoutValue;
33
+ children: ReactNode;
34
+ }) {
35
+ const stable = useMemo<PanelLayoutValue>(
36
+ () => ({
37
+ leftWidth,
38
+ setLeftWidth,
39
+ rightWidth,
40
+ leftCollapsed,
41
+ setLeftCollapsed,
42
+ rightCollapsed,
43
+ setRightCollapsed,
44
+ rightPanelTab,
45
+ setRightPanelTab,
46
+ toggleLeftSidebar,
47
+ handlePanelResizeStart,
48
+ handlePanelResizeMove,
49
+ handlePanelResizeEnd,
50
+ }),
51
+ [
52
+ leftWidth,
53
+ setLeftWidth,
54
+ rightWidth,
55
+ leftCollapsed,
56
+ setLeftCollapsed,
57
+ rightCollapsed,
58
+ setRightCollapsed,
59
+ rightPanelTab,
60
+ setRightPanelTab,
61
+ toggleLeftSidebar,
62
+ handlePanelResizeStart,
63
+ handlePanelResizeMove,
64
+ handlePanelResizeEnd,
65
+ ],
66
+ );
67
+ return <PanelLayoutContext value={stable}>{children}</PanelLayoutContext>;
68
+ }
@@ -0,0 +1,135 @@
1
+ import { createContext, useContext, useMemo, type ReactNode } from "react";
2
+ import type { TimelineElement } from "../player";
3
+ import type { CompositionDimensions } from "../components/renders/RenderQueue";
4
+
5
+ export interface StudioContextValue {
6
+ projectId: string;
7
+ activeCompPath: string | null;
8
+ setActiveCompPath: (path: string | null) => void;
9
+ showToast: (message: string, tone?: "error" | "info") => void;
10
+ previewIframeRef: React.MutableRefObject<HTMLIFrameElement | null>;
11
+ captionEditMode: boolean;
12
+ compositionLoading: boolean;
13
+ refreshKey: number;
14
+ setRefreshKey: React.Dispatch<React.SetStateAction<number>>;
15
+ currentTime: number;
16
+ timelineElements: TimelineElement[];
17
+ isPlaying: boolean;
18
+ editHistory: {
19
+ canUndo: boolean;
20
+ canRedo: boolean;
21
+ undoLabel: string | undefined;
22
+ redoLabel: string | undefined;
23
+ };
24
+ handleUndo: () => Promise<void>;
25
+ handleRedo: () => Promise<void>;
26
+ renderQueue: {
27
+ jobs: unknown[];
28
+ isRendering: boolean;
29
+ deleteRender: (jobId: string) => void;
30
+ clearCompleted: () => void;
31
+ startRender: (options: unknown) => Promise<void>;
32
+ };
33
+ compositionDimensions: CompositionDimensions | null;
34
+ waitForPendingDomEditSaves: () => Promise<void>;
35
+ handlePreviewIframeRef: (iframe: HTMLIFrameElement | null) => void;
36
+ refreshPreviewDocumentVersion: () => void;
37
+ timelineVisible: boolean;
38
+ toggleTimelineVisibility: () => void;
39
+ }
40
+
41
+ const StudioContext = createContext<StudioContextValue | null>(null);
42
+
43
+ export function useStudioContext(): StudioContextValue {
44
+ const ctx = useContext(StudioContext);
45
+ if (!ctx) throw new Error("useStudioContext must be used within StudioProvider");
46
+ return ctx;
47
+ }
48
+
49
+ export function StudioProvider({
50
+ value,
51
+ children,
52
+ }: {
53
+ value: StudioContextValue;
54
+ children: ReactNode;
55
+ }) {
56
+ const {
57
+ projectId,
58
+ activeCompPath,
59
+ setActiveCompPath,
60
+ showToast,
61
+ previewIframeRef,
62
+ captionEditMode,
63
+ compositionLoading,
64
+ refreshKey,
65
+ setRefreshKey,
66
+ currentTime,
67
+ timelineElements,
68
+ isPlaying,
69
+ editHistory,
70
+ handleUndo,
71
+ handleRedo,
72
+ renderQueue,
73
+ compositionDimensions,
74
+ waitForPendingDomEditSaves,
75
+ handlePreviewIframeRef,
76
+ refreshPreviewDocumentVersion,
77
+ timelineVisible,
78
+ toggleTimelineVisibility,
79
+ } = value;
80
+
81
+ const stable = useMemo<StudioContextValue>(
82
+ () => ({
83
+ projectId,
84
+ activeCompPath,
85
+ setActiveCompPath,
86
+ showToast,
87
+ previewIframeRef,
88
+ captionEditMode,
89
+ compositionLoading,
90
+ refreshKey,
91
+ setRefreshKey,
92
+ currentTime,
93
+ timelineElements,
94
+ isPlaying,
95
+ editHistory,
96
+ handleUndo,
97
+ handleRedo,
98
+ renderQueue,
99
+ compositionDimensions,
100
+ waitForPendingDomEditSaves,
101
+ handlePreviewIframeRef,
102
+ refreshPreviewDocumentVersion,
103
+ timelineVisible,
104
+ toggleTimelineVisibility,
105
+ }),
106
+ // Representative subset of deps that actually change — stable callbacks
107
+ // (showToast, setActiveCompPath, etc.) are included for correctness but
108
+ // won't trigger re-renders on their own.
109
+ [
110
+ projectId,
111
+ activeCompPath,
112
+ captionEditMode,
113
+ compositionLoading,
114
+ refreshKey,
115
+ currentTime,
116
+ isPlaying,
117
+ compositionDimensions,
118
+ timelineVisible,
119
+ editHistory,
120
+ timelineElements,
121
+ renderQueue,
122
+ setActiveCompPath,
123
+ showToast,
124
+ previewIframeRef,
125
+ setRefreshKey,
126
+ handleUndo,
127
+ handleRedo,
128
+ waitForPendingDomEditSaves,
129
+ handlePreviewIframeRef,
130
+ refreshPreviewDocumentVersion,
131
+ toggleTimelineVisibility,
132
+ ],
133
+ );
134
+ return <StudioContext value={stable}>{children}</StudioContext>;
135
+ }