@hyperframes/studio 0.7.38 → 0.7.40
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/{index-ClUipc8i.js → index-89kPtC4s.js} +1 -1
- package/dist/assets/{index-BLRTwY5l.js → index-B2Utv-2b.js} +200 -200
- package/dist/assets/index-BpM6cnfP.css +1 -0
- package/dist/assets/{index-Ykq7ihge.js → index-CjX8Ljc8.js} +1 -1
- package/dist/{chunk-JND3XUJL.js → chunk-BA66NM4L.js} +1 -1
- package/dist/chunk-BA66NM4L.js.map +1 -0
- package/dist/{domEditingLayers-UIQZJCOA.js → domEditingLayers-H7LDFIJ7.js} +2 -2
- package/dist/index.d.ts +47 -29
- package/dist/index.html +2 -2
- package/dist/index.js +4432 -3045
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/App.tsx +9 -7
- package/src/components/StudioPreviewArea.tsx +14 -0
- package/src/components/StudioRightPanel.tsx +9 -0
- package/src/components/editor/DomEditCropHandles.tsx +238 -0
- package/src/components/editor/DomEditOverlay.tsx +140 -151
- package/src/components/editor/DomEditRotateHandle.tsx +41 -0
- package/src/components/editor/PropertyPanel.test.ts +73 -0
- package/src/components/editor/PropertyPanel.tsx +42 -37
- package/src/components/editor/PropertyPanelEmptyState.tsx +33 -0
- package/src/components/editor/SnapToolbar.tsx +20 -1
- package/src/components/editor/clipPathHelpers.ts +113 -0
- package/src/components/editor/domEditOverlayCrop.test.ts +106 -0
- package/src/components/editor/domEditOverlayCrop.ts +115 -0
- package/src/components/editor/domEditOverlayGeometry.ts +14 -0
- package/src/components/editor/domEditOverlayShape.ts +39 -0
- package/src/components/editor/domEditing.test.ts +2 -0
- package/src/components/editor/domEditingElement.ts +8 -1
- package/src/components/editor/domEditingTypes.ts +3 -0
- package/src/components/editor/manualEditsDom.ts +1 -18
- package/src/components/editor/manualEditsStyleHelpers.ts +18 -0
- package/src/components/editor/marqueeCommit.ts +3 -2
- package/src/components/editor/offCanvasIndicatorGeometry.ts +74 -0
- package/src/components/editor/offCanvasIndicatorRefresh.test.tsx +154 -0
- package/src/components/editor/offCanvasIndicatorRefresh.ts +99 -0
- package/src/components/editor/propertyPanelHelpers.ts +21 -34
- package/src/components/editor/propertyPanelStyleSections.tsx +75 -1
- package/src/components/editor/propertyPanelTypes.ts +3 -0
- package/src/components/editor/snapTargetCollection.ts +2 -3
- package/src/components/editor/useDomEditCompositionRect.ts +68 -0
- package/src/components/editor/useDomEditOverlayGestures.ts +13 -6
- package/src/components/editor/useDomEditOverlayRects.ts +5 -3
- package/src/components/sidebar/AssetsTab.test.ts +87 -0
- package/src/components/sidebar/AssetsTab.tsx +113 -15
- package/src/components/sidebar/BlocksTab.tsx +2 -1
- package/src/components/sidebar/GlobalAssetsView.tsx +91 -0
- package/src/contexts/TimelineEditContext.tsx +1 -0
- package/src/hooks/domSelectionTestHarness.ts +1 -0
- package/src/hooks/gsapDragCommit.test.ts +56 -0
- package/src/hooks/gsapDragCommit.ts +41 -109
- package/src/hooks/gsapDragPositionCommit.ts +3 -0
- package/src/hooks/gsapDragStaticSetHelpers.ts +109 -0
- package/src/hooks/gsapRuntimeBridge.ts +23 -2
- package/src/hooks/gsapRuntimeKeyframes.test.ts +34 -0
- package/src/hooks/gsapRuntimeKeyframes.ts +13 -1
- package/src/hooks/gsapWholePropertyOffsetCommit.ts +1 -0
- package/src/hooks/timelineEditingHelpers.ts +17 -5
- package/src/hooks/timelineTrackVisibility.test.ts +202 -0
- package/src/hooks/timelineTrackVisibility.ts +371 -0
- package/src/hooks/useCropMode.ts +91 -0
- package/src/hooks/useDomEditCommits.test.tsx +2 -0
- package/src/hooks/useRenderClipContent.test.ts +68 -2
- package/src/hooks/useRenderClipContent.ts +5 -6
- package/src/hooks/useTimelineEditing.ts +35 -30
- package/src/hooks/useTimelineEditingTypes.ts +30 -0
- package/src/icons/SystemIcons.tsx +12 -4
- package/src/player/components/AudioWaveform.tsx +11 -8
- package/src/player/components/CompositionThumbnail.tsx +14 -11
- package/src/player/components/PlayheadIndicator.tsx +21 -11
- package/src/player/components/ShortcutsPanel.tsx +9 -0
- package/src/player/components/Timeline.test.ts +105 -5
- package/src/player/components/Timeline.tsx +37 -47
- package/src/player/components/TimelineCanvas.tsx +275 -256
- package/src/player/components/TimelineClip.test.tsx +105 -0
- package/src/player/components/TimelineClip.tsx +44 -57
- package/src/player/components/TimelineRuler.tsx +17 -23
- package/src/player/components/TimelineShortcutHint.tsx +26 -0
- package/src/player/components/TimelineTypes.ts +18 -0
- package/src/player/components/VideoThumbnail.tsx +16 -13
- package/src/player/components/timelineCallbacks.ts +1 -0
- package/src/player/components/timelineIcons.tsx +2 -44
- package/src/player/components/timelineLayout.ts +18 -22
- package/src/player/components/timelineMotionStyles.test.ts +101 -0
- package/src/player/components/timelineTheme.test.ts +21 -4
- package/src/player/components/timelineTheme.ts +15 -15
- package/src/player/components/useTimelineActiveClips.test.ts +93 -0
- package/src/player/components/useTimelineActiveClips.ts +125 -0
- package/src/player/components/useTimelinePlayhead.ts +6 -0
- package/src/player/hooks/useExpandedTimelineElements.test.ts +110 -3
- package/src/player/hooks/useExpandedTimelineElements.ts +106 -19
- package/src/player/lib/time.test.ts +1 -0
- package/src/player/lib/timelineDOM.test.ts +48 -1
- package/src/player/lib/timelineDOM.ts +7 -0
- package/src/player/lib/timelineIframeHelpers.ts +1 -0
- package/src/player/store/playerStore.ts +19 -1
- package/src/styles/studio.css +108 -0
- package/src/utils/sourcePatcher.test.ts +11 -0
- package/src/utils/sourcePatcher.ts +6 -4
- package/dist/assets/index-DJaiR8T2.css +0 -1
- package/dist/chunk-JND3XUJL.js.map +0 -1
- /package/dist/{domEditingLayers-UIQZJCOA.js.map → domEditingLayers-H7LDFIJ7.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useRef, useMemo, useCallback, useState, useEffect, memo
|
|
1
|
+
import { useRef, useMemo, useCallback, useState, useEffect, memo } from "react";
|
|
2
2
|
import { useMusicBeatAnalysis } from "../../hooks/useMusicBeatAnalysis";
|
|
3
3
|
import { isMusicTrack } from "../../utils/timelineInspector";
|
|
4
4
|
import { remapBeatAnalysisToComposition } from "../../utils/beatEditActions";
|
|
@@ -6,9 +6,10 @@ import { usePlayerStore, type TimelineElement } from "../store/playerStore";
|
|
|
6
6
|
import { useExpandedTimelineElements } from "../hooks/useExpandedTimelineElements";
|
|
7
7
|
import { useMountEffect } from "../../hooks/useMountEffect";
|
|
8
8
|
import { EditPopover } from "./EditModal";
|
|
9
|
-
import { defaultTimelineTheme
|
|
9
|
+
import { defaultTimelineTheme } from "./timelineTheme";
|
|
10
10
|
import { useTimelineRangeSelection } from "./useTimelineRangeSelection";
|
|
11
11
|
import { useTimelinePlayhead } from "./useTimelinePlayhead";
|
|
12
|
+
import { useTimelineActiveClips } from "./useTimelineActiveClips";
|
|
12
13
|
import { type TrackVisualStyle, getTrackStyle } from "./timelineIcons";
|
|
13
14
|
import { getTimelinePixelsPerSecond } from "./timelineZoom";
|
|
14
15
|
import { useTimelineZoom } from "./useTimelineZoom";
|
|
@@ -21,17 +22,15 @@ import {
|
|
|
21
22
|
} from "./KeyframeDiamondContextMenu";
|
|
22
23
|
import { useTimelineClipDrag } from "./useTimelineClipDrag";
|
|
23
24
|
import { ClipContextMenu } from "./ClipContextMenu";
|
|
25
|
+
import { TimelineShortcutHint } from "./TimelineShortcutHint";
|
|
24
26
|
import {
|
|
25
27
|
GUTTER,
|
|
26
28
|
generateTicks,
|
|
27
29
|
getTimelineCanvasHeight,
|
|
28
30
|
shouldShowTimelineShortcutHint,
|
|
29
31
|
} from "./timelineLayout";
|
|
30
|
-
import
|
|
31
|
-
import {
|
|
32
|
-
useResolvedTimelineEditCallbacks,
|
|
33
|
-
type TimelineEditOverrides,
|
|
34
|
-
} from "./useResolvedTimelineEditCallbacks";
|
|
32
|
+
import { useResolvedTimelineEditCallbacks } from "./useResolvedTimelineEditCallbacks";
|
|
33
|
+
import type { TimelineProps } from "./TimelineTypes";
|
|
35
34
|
|
|
36
35
|
// Re-export pure utilities so existing imports from "./Timeline" still resolve.
|
|
37
36
|
export {
|
|
@@ -48,19 +47,6 @@ export {
|
|
|
48
47
|
getDefaultDroppedTrack,
|
|
49
48
|
} from "./timelineLayout";
|
|
50
49
|
|
|
51
|
-
interface TimelineProps extends TimelineDropCallbacks, TimelineEditOverrides {
|
|
52
|
-
onSeek?: (time: number) => void;
|
|
53
|
-
onDrillDown?: (element: TimelineElement) => void;
|
|
54
|
-
renderClipContent?: (
|
|
55
|
-
element: TimelineElement,
|
|
56
|
-
style: { clip: string; label: string },
|
|
57
|
-
) => ReactNode;
|
|
58
|
-
renderClipOverlay?: (element: TimelineElement) => ReactNode;
|
|
59
|
-
onDeleteElement?: (element: TimelineElement) => Promise<void> | void;
|
|
60
|
-
onSelectElement?: (element: TimelineElement | null) => void;
|
|
61
|
-
theme?: Partial<TimelineTheme>;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
50
|
export const Timeline = memo(function Timeline({
|
|
65
51
|
onSeek,
|
|
66
52
|
onDrillDown,
|
|
@@ -162,20 +148,26 @@ export const Timeline = memo(function Timeline({
|
|
|
162
148
|
});
|
|
163
149
|
}, [syncShortcutHintVisibility]);
|
|
164
150
|
|
|
165
|
-
const setContainerRef = useCallback(
|
|
151
|
+
const setContainerRef = useCallback((el: HTMLDivElement | null) => {
|
|
152
|
+
containerRef.current = el;
|
|
153
|
+
}, []);
|
|
154
|
+
|
|
155
|
+
const setScrollRef = useCallback(
|
|
166
156
|
(el: HTMLDivElement | null) => {
|
|
167
157
|
if (roRef.current) {
|
|
168
158
|
roRef.current.disconnect();
|
|
169
159
|
roRef.current = null;
|
|
170
160
|
}
|
|
171
|
-
|
|
161
|
+
scrollRef.current = el;
|
|
172
162
|
if (!el) return;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
setViewportWidth(entry.contentRect.width);
|
|
163
|
+
|
|
164
|
+
const syncScrollViewport = () => {
|
|
165
|
+
setViewportWidth(el.clientWidth);
|
|
177
166
|
scheduleShortcutHintVisibilitySync();
|
|
178
|
-
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
syncScrollViewport();
|
|
170
|
+
roRef.current = new ResizeObserver(syncScrollViewport);
|
|
179
171
|
roRef.current.observe(el);
|
|
180
172
|
},
|
|
181
173
|
[scheduleShortcutHintVisibilitySync],
|
|
@@ -273,6 +265,13 @@ export const Timeline = memo(function Timeline({
|
|
|
273
265
|
const pps = getTimelinePixelsPerSecond(fitPps, zoomMode, manualZoomPercent);
|
|
274
266
|
ppsRef.current = pps;
|
|
275
267
|
const trackContentWidth = Math.max(0, effectiveDuration * pps);
|
|
268
|
+
const clipStateVersion = useMemo(
|
|
269
|
+
() =>
|
|
270
|
+
expandedElements
|
|
271
|
+
.map((el) => `${el.key ?? el.id}:${el.start}:${el.duration}:${el.track}`)
|
|
272
|
+
.join("|"),
|
|
273
|
+
[expandedElements],
|
|
274
|
+
);
|
|
276
275
|
const zoomModeRef = useRef(zoomMode);
|
|
277
276
|
zoomModeRef.current = zoomMode;
|
|
278
277
|
const manualZoomPercentRef = useRef(manualZoomPercent);
|
|
@@ -301,6 +300,11 @@ export const Timeline = memo(function Timeline({
|
|
|
301
300
|
setManualZoomPercent,
|
|
302
301
|
onSeek,
|
|
303
302
|
});
|
|
303
|
+
useTimelineActiveClips({
|
|
304
|
+
scrollRef,
|
|
305
|
+
currentTime,
|
|
306
|
+
clipStateVersion,
|
|
307
|
+
});
|
|
304
308
|
|
|
305
309
|
const {
|
|
306
310
|
rangeSelection,
|
|
@@ -340,8 +344,7 @@ export const Timeline = memo(function Timeline({
|
|
|
340
344
|
() => generateTicks(effectiveDuration, pps),
|
|
341
345
|
[effectiveDuration, pps],
|
|
342
346
|
);
|
|
343
|
-
const majorTickInterval =
|
|
344
|
-
major.length >= 2 ? Math.max(0.25, major[1] - major[0]) : effectiveDuration;
|
|
347
|
+
const majorTickInterval = major.length >= 2 ? major[1] - major[0] : effectiveDuration;
|
|
345
348
|
|
|
346
349
|
useEffect(() => {
|
|
347
350
|
syncShortcutHintVisibility();
|
|
@@ -406,7 +409,7 @@ export const Timeline = memo(function Timeline({
|
|
|
406
409
|
}}
|
|
407
410
|
>
|
|
408
411
|
<div
|
|
409
|
-
ref={
|
|
412
|
+
ref={setScrollRef}
|
|
410
413
|
tabIndex={-1}
|
|
411
414
|
className={`${zoomMode === "fit" ? "overflow-x-hidden" : "overflow-x-auto"} overflow-y-auto h-full outline-none`}
|
|
412
415
|
onDragOver={handleAssetDragOver}
|
|
@@ -434,7 +437,6 @@ export const Timeline = memo(function Timeline({
|
|
|
434
437
|
totalH={totalH}
|
|
435
438
|
effectiveDuration={effectiveDuration}
|
|
436
439
|
majorTickInterval={majorTickInterval}
|
|
437
|
-
shiftHeld={shiftHeld}
|
|
438
440
|
rangeSelection={rangeSelection}
|
|
439
441
|
theme={theme}
|
|
440
442
|
displayTrackOrder={displayTrackOrder}
|
|
@@ -472,6 +474,9 @@ export const Timeline = memo(function Timeline({
|
|
|
472
474
|
const elKey = el.key ?? el.id;
|
|
473
475
|
setSelectedElementId(elKey);
|
|
474
476
|
onSelectElement?.(el);
|
|
477
|
+
// Visually select the clicked diamond (matches shift-click / motion-path
|
|
478
|
+
// selection); cleared above so this single-selects it.
|
|
479
|
+
toggleSelectedKeyframe(`${elKey}:${pct}`);
|
|
475
480
|
const absTime = el.start + (pct / 100) * el.duration;
|
|
476
481
|
onSeek?.(absTime);
|
|
477
482
|
const kfData = keyframeCache?.get(elKey);
|
|
@@ -519,22 +524,7 @@ export const Timeline = memo(function Timeline({
|
|
|
519
524
|
</div>
|
|
520
525
|
|
|
521
526
|
{showShortcutHint && !showPopover && !rangeSelection && (
|
|
522
|
-
<
|
|
523
|
-
<div
|
|
524
|
-
className="flex items-center gap-1.5 px-2 py-1 rounded-md border"
|
|
525
|
-
style={{ background: "rgba(17,23,35,0.84)", borderColor: theme.gutterBorder }}
|
|
526
|
-
>
|
|
527
|
-
<kbd
|
|
528
|
-
className="text-[9px] font-mono px-1 py-0.5 rounded"
|
|
529
|
-
style={{ color: theme.textSecondary, background: "rgba(255,255,255,0.06)" }}
|
|
530
|
-
>
|
|
531
|
-
Shift
|
|
532
|
-
</kbd>
|
|
533
|
-
<span className="text-[9px]" style={{ color: theme.textSecondary }}>
|
|
534
|
-
+ drag/click to edit range
|
|
535
|
-
</span>
|
|
536
|
-
</div>
|
|
537
|
-
</div>
|
|
527
|
+
<TimelineShortcutHint theme={theme} />
|
|
538
528
|
)}
|
|
539
529
|
|
|
540
530
|
{showPopover && rangeSelection && (
|