@hyperframes/studio 0.8.112 → 0.8.114
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-CBpg41JM.js → hyperframes-player-aXNJKiIg.js} +1 -1
- package/dist/assets/index-BYnsJnJV.css +1 -0
- package/dist/assets/{index-BFitquwi.js → index-Bn2RJNTJ.js} +1 -1
- package/dist/assets/{index-CZfrSyU9.js → index-C9N-DGjC.js} +1 -1
- package/dist/assets/{index-BKy_birQ.js → index-Dz7doz9l.js} +199 -199
- package/dist/index.d.ts +3 -3
- package/dist/index.html +2 -2
- package/dist/index.js +1605 -1536
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +9 -8
- package/src/App.tsx +82 -84
- package/src/components/EditorShell.tsx +3 -3
- package/src/components/StudioHeader.tsx +4 -4
- package/src/components/StudioLeftPanels.tsx +3 -3
- package/src/components/StudioOverlays.tsx +4 -4
- package/src/components/StudioRightPanels.tsx +14 -9
- package/src/components/StudioToast.tsx +1 -1
- package/src/components/TimelineToolbar.tsx +3 -3
- package/src/components/editor/InlineTextToolbar.tsx +11 -27
- package/src/components/editor/colorBrowserCanvas.test.ts +116 -0
- package/src/components/editor/colorValue.test.ts +16 -0
- package/src/components/editor/colorValue.ts +100 -24
- package/src/components/editor/cropResize.test.ts +11 -0
- package/src/components/editor/cropResize.ts +2 -3
- package/src/components/editor/gradientValue.ts +28 -36
- package/src/components/editor/gsapAnimatesProperty.ts +0 -54
- package/src/components/editor/inlineTextStyleRange.test.ts +31 -1
- package/src/components/editor/inlineTextStyleRange.ts +5 -2
- package/src/components/editor/inlineTextStyleRead.ts +9 -0
- package/src/components/editor/manualEditsDom.ts +2 -2
- package/src/components/editor/manualEditsSeekReapply.ts +2 -2
- package/src/components/editor/propertyPanelColor.tsx +1 -1
- package/src/components/editor/reapplyPositionEditsAfterSeek.test.ts +25 -0
- package/src/hooks/gsapRuntimeKeyframes.ts +1 -1
- package/src/hooks/gsapRuntimeReaders.test.ts +48 -0
- package/src/hooks/gsapRuntimeReaders.ts +3 -90
- package/src/hooks/useAppHotkeys.ts +11 -5
- package/src/hooks/useFrameCapture.ts +15 -8
- package/src/hooks/useGestureCommit.ts +4 -1
- package/src/hooks/useGestureTrailOverlay.tsx +33 -0
- package/src/hooks/usePanelLayout.ts +5 -1
- package/src/hooks/useShellSlices.ts +53 -0
- package/src/hooks/useStableHandlers.test.tsx +77 -0
- package/src/hooks/useStableHandlers.ts +44 -0
- package/src/hooks/useStudioSdkSessions.ts +2 -1
- package/src/hooks/useStudioSidePanels.test.tsx +44 -0
- package/src/hooks/useStudioSidePanels.tsx +23 -0
- package/src/hooks/useTimelineAddAtPlayhead.ts +16 -8
- package/src/hooks/useTimelineEditing.ts +33 -27
- package/src/utils/frameCapture.ts +3 -1
- package/src/utils/gsapUndoRestore.browser.test.ts +4 -2
- package/dist/assets/index-DbfKVTId.css +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// fallow-ignore-file complexity
|
|
2
2
|
import { useCallback, useRef } from "react";
|
|
3
|
+
import { useStableHandlers } from "./useStableHandlers";
|
|
3
4
|
import { usePlayerStore, type TimelineElement } from "../player";
|
|
4
5
|
import { toAuthoredStart, toCompositionTime } from "../player/store/timelineElement";
|
|
5
6
|
import { useRazorSplit } from "./useRazorSplit";
|
|
@@ -508,13 +509,41 @@ export function useTimelineEditing({
|
|
|
508
509
|
return [...flatMembers, ...domMembers];
|
|
509
510
|
};
|
|
510
511
|
|
|
512
|
+
const audioGroupAttribute = {
|
|
513
|
+
...setAudioGroupAttribute,
|
|
514
|
+
// Same two-array member lookup syncStoredGroupAttribute mirrors into
|
|
515
|
+
// (timelineAudioGroupVolume.ts): a sub-composition's group members have
|
|
516
|
+
// no flat twin, only a domClipChildren entry, so both are checked.
|
|
517
|
+
setQuiet: track(
|
|
518
|
+
guard(audioGroupMembers, setAudioGroupAttribute.setQuiet, (reason, groupId, attr) => {
|
|
519
|
+
setAudioGroupAttribute.revertLive(groupId, attr);
|
|
520
|
+
return refused(reason);
|
|
521
|
+
}),
|
|
522
|
+
),
|
|
523
|
+
};
|
|
524
|
+
const stableAudioGroupAttribute = useStableHandlers(audioGroupAttribute, projectId);
|
|
525
|
+
const elementFxAttribute = {
|
|
526
|
+
...setElementFxAttribute,
|
|
527
|
+
setMany: track(guard((edits) => edits.map((edit) => edit.element), setElementsAttribute)),
|
|
528
|
+
setQuiet: track(
|
|
529
|
+
guard(
|
|
530
|
+
(element) => [element],
|
|
531
|
+
setElementFxAttribute.setQuiet,
|
|
532
|
+
(reason, element, attr) => {
|
|
533
|
+
setElementFxAttribute.revertLive(element, attr);
|
|
534
|
+
return refused(reason);
|
|
535
|
+
},
|
|
536
|
+
),
|
|
537
|
+
),
|
|
538
|
+
};
|
|
539
|
+
const stableElementFxAttribute = useStableHandlers(elementFxAttribute, projectId);
|
|
511
540
|
// Every write-handler is tracked here, the one place all hand edits
|
|
512
541
|
// converge, so undo never races a write; canEdit gates the same point.
|
|
513
542
|
// Coverage boundary: see the PR body, not every kind resolves an element.
|
|
514
543
|
const trackedRazorSplit = track(
|
|
515
544
|
guard((element) => withLinkPartners([element]), handleRazorSplit),
|
|
516
545
|
);
|
|
517
|
-
|
|
546
|
+
const editing = {
|
|
518
547
|
handleTimelineElementMove: track(guard((element) => [element], handleTimelineElementMove)),
|
|
519
548
|
handleTimelineElementResize: track(guard((element) => [element], handleTimelineElementResize)),
|
|
520
549
|
handleToggleTrackHidden: track(
|
|
@@ -530,32 +559,8 @@ export function useTimelineEditing({
|
|
|
530
559
|
}, handleToggleElementHidden),
|
|
531
560
|
),
|
|
532
561
|
handleAutoGroupCarveSources: track(handleAutoGroupCarveSources),
|
|
533
|
-
setAudioGroupAttribute:
|
|
534
|
-
|
|
535
|
-
// Same two-array member lookup syncStoredGroupAttribute mirrors into
|
|
536
|
-
// (timelineAudioGroupVolume.ts): a sub-composition's group members have
|
|
537
|
-
// no flat twin, only a domClipChildren entry, so both are checked.
|
|
538
|
-
setQuiet: track(
|
|
539
|
-
guard(audioGroupMembers, setAudioGroupAttribute.setQuiet, (reason, groupId, attr) => {
|
|
540
|
-
setAudioGroupAttribute.revertLive(groupId, attr);
|
|
541
|
-
return refused(reason);
|
|
542
|
-
}),
|
|
543
|
-
),
|
|
544
|
-
},
|
|
545
|
-
setElementFxAttribute: {
|
|
546
|
-
...setElementFxAttribute,
|
|
547
|
-
setMany: track(guard((edits) => edits.map((edit) => edit.element), setElementsAttribute)),
|
|
548
|
-
setQuiet: track(
|
|
549
|
-
guard(
|
|
550
|
-
(element) => [element],
|
|
551
|
-
setElementFxAttribute.setQuiet,
|
|
552
|
-
(reason, element, attr) => {
|
|
553
|
-
setElementFxAttribute.revertLive(element, attr);
|
|
554
|
-
return refused(reason);
|
|
555
|
-
},
|
|
556
|
-
),
|
|
557
|
-
),
|
|
558
|
-
},
|
|
562
|
+
setAudioGroupAttribute: stableAudioGroupAttribute,
|
|
563
|
+
setElementFxAttribute: stableElementFxAttribute,
|
|
559
564
|
handleTimelineElementDelete: track(
|
|
560
565
|
guard((element) => withLinkPartners([element]), linkEditing.handleLinkedElementDelete),
|
|
561
566
|
),
|
|
@@ -591,4 +596,5 @@ export function useTimelineEditing({
|
|
|
591
596
|
setAudioGroupAttribute.restoreLive(restore);
|
|
592
597
|
},
|
|
593
598
|
};
|
|
599
|
+
return useStableHandlers(editing, projectId);
|
|
594
600
|
}
|
|
@@ -5,6 +5,7 @@ export interface FrameCaptureRequest {
|
|
|
5
5
|
compositionPath: string | null;
|
|
6
6
|
currentTime: number;
|
|
7
7
|
origin?: string;
|
|
8
|
+
version?: number;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
function normalizeCompositionPath(compositionPath: string | null): string {
|
|
@@ -16,6 +17,7 @@ export function buildFrameCaptureUrl({
|
|
|
16
17
|
compositionPath,
|
|
17
18
|
currentTime,
|
|
18
19
|
origin = window.location.origin,
|
|
20
|
+
version = Date.now(),
|
|
19
21
|
}: FrameCaptureRequest): string {
|
|
20
22
|
const compPath = normalizeCompositionPath(compositionPath);
|
|
21
23
|
const url = new URL(
|
|
@@ -25,7 +27,7 @@ export function buildFrameCaptureUrl({
|
|
|
25
27
|
url.searchParams.set("t", Math.max(0, currentTime).toFixed(3));
|
|
26
28
|
url.searchParams.set("format", "png");
|
|
27
29
|
url.searchParams.set("output", "source");
|
|
28
|
-
url.searchParams.set("v", String(
|
|
30
|
+
url.searchParams.set("v", String(version));
|
|
29
31
|
return url.toString();
|
|
30
32
|
}
|
|
31
33
|
|
|
@@ -6,12 +6,14 @@ import { join } from "node:path";
|
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import puppeteer, { type Browser } from "puppeteer-core";
|
|
8
8
|
import { build } from "vite";
|
|
9
|
-
import { afterAll, beforeAll, expect, it } from "vitest";
|
|
9
|
+
import { afterAll, beforeAll, expect, it, vi } from "vitest";
|
|
10
10
|
import { findSystemChrome } from "../../vite.browser";
|
|
11
11
|
import { writeFixture } from "../../tests/e2e/edit-accuracy/grid.mjs";
|
|
12
12
|
|
|
13
13
|
const require = createRequire(import.meta.url);
|
|
14
14
|
const CROP = "inset(0px 40px 0px 0px)";
|
|
15
|
+
// Real Chrome on a loaded Windows runner exceeds Vitest's 5s test and 10s hook defaults.
|
|
16
|
+
vi.setConfig({ testTimeout: 60_000, hookTimeout: 60_000 });
|
|
15
17
|
let browser: Browser;
|
|
16
18
|
let undoBundle: string;
|
|
17
19
|
|
|
@@ -37,7 +39,7 @@ beforeAll(async () => {
|
|
|
37
39
|
});
|
|
38
40
|
undoBundle = (Array.isArray(out) ? out[0]! : (out as { output: [{ code: string }] })).output[0]
|
|
39
41
|
.code;
|
|
40
|
-
}
|
|
42
|
+
});
|
|
41
43
|
|
|
42
44
|
afterAll(() => browser?.close());
|
|
43
45
|
|