@hyperframes/studio 0.8.54 → 0.8.56
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-Cy_AwUa8.js → hyperframes-player-k8LzMtXX.js} +1 -1
- package/dist/assets/{index-DPUJoO8n.js → index-BlkJ_Axe.js} +192 -192
- package/dist/assets/{index-CTa-6Kso.js → index-CxR7F2YQ.js} +1 -1
- package/dist/assets/{index-DkAzKuPZ.js → index-DFlILHJe.js} +1 -1
- package/dist/assets/{index-DrHQAuGO.css → index-ZmBtVrEm.css} +1 -1
- package/dist/index.d.ts +16 -8
- package/dist/index.html +2 -2
- package/dist/index.js +3152 -3010
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +7 -7
- package/src/App.tsx +14 -1
- package/src/components/EditorShell.readOnlyHostMount.test.tsx +116 -0
- package/src/components/EditorShell.selectionSync.test.tsx +57 -67
- package/src/components/EditorShell.tsx +59 -50
- package/src/components/EditorShellTestMocks.ts +46 -0
- package/src/components/editor/DomEditOverlay.tsx +19 -40
- package/src/components/editor/DomEditOverlayHover.test.tsx +1 -15
- package/src/components/editor/DomEditSelectionChrome.tsx +11 -9
- package/src/components/editor/PropertyPanel.deselect.test.tsx +71 -0
- package/src/components/editor/PropertyPanel.tsx +4 -3
- package/src/components/editor/SnapToolbar.test.tsx +1 -0
- package/src/components/editor/domEditOverlayTestMocks.ts +16 -0
- package/src/components/editor/previewReadOnly.overlay.test.tsx +260 -0
- package/src/components/editor/previewReadOnlyContext.tsx +59 -0
- package/src/components/editor/propertyPanelFlatLayoutSection.tsx +9 -0
- package/src/components/editor/propertyPanelFlatPrimitives.tsx +4 -1
- package/src/components/editor/propertyPanelInputCoverage.test.tsx +3 -13
- package/src/components/editor/useDomEditNudge.ts +9 -0
- package/src/components/editor/useDomEditOverlayGestures.ts +4 -0
- package/src/components/editor/useOffCanvasIndicators.ts +50 -0
- package/src/components/nle/PreviewOverlays.topologyLens.test.tsx +4 -35
- package/src/components/nle/PreviewOverlays.tsx +15 -8
- package/src/components/nle/PreviewOverlaysTestMocks.ts +40 -0
- package/src/components/nle/TimelinePane.tsx +5 -1
- package/src/components/nle/previewReadOnly.test.tsx +128 -0
- package/src/components/nle/useCanvasZOrderTimelineMirror.test.tsx +1 -1
- package/src/components/nle/useCanvasZOrderTimelineMirror.ts +3 -6
- package/src/components/nle/usePreviewBlockDrop.ts +3 -1
- package/src/hooks/appHotkeysDispatch.ts +16 -1
- package/src/hooks/gsapDragCommit.ts +1 -1
- package/src/hooks/gsapEditOutcome.test.ts +115 -0
- package/src/hooks/gsapEditOutcome.ts +39 -10
- package/src/hooks/gsapResizeIntercept.test.ts +42 -3
- package/src/hooks/gsapResizeIntercept.ts +12 -2
- package/src/hooks/gsapRuntimeBridge.test.ts +10 -2
- package/src/hooks/gsapRuntimeBridge.ts +14 -3
- package/src/hooks/newTweenTargetHooks.test.tsx +1 -0
- package/src/hooks/timelineAudioGroupCreate.ts +3 -4
- package/src/hooks/timelineTrackVisibility.ts +7 -8
- package/src/hooks/useAppHotkeys.test.ts +71 -3
- package/src/hooks/useAppHotkeys.textEditing.test.tsx +1 -0
- package/src/hooks/useAppHotkeys.ts +4 -0
- package/src/hooks/useDomEditCommits.test.tsx +1 -0
- package/src/hooks/useDomEditCommits.ts +3 -0
- package/src/hooks/useDomEditSession.test.tsx +1 -0
- package/src/hooks/useDomEditSession.ts +7 -4
- package/src/hooks/useDomEditWiring.ts +40 -40
- package/src/hooks/useDomGeometryCommits.test.tsx +85 -2
- package/src/hooks/useDomGeometryCommits.ts +26 -20
- package/src/hooks/useGestureCommit.test.tsx +29 -0
- package/src/hooks/useGestureCommit.ts +23 -0
- package/src/hooks/useInlineTextEdit.test.tsx +23 -2
- package/src/hooks/useInlineTextEdit.ts +11 -2
- package/src/hooks/useTimelineAssetDropOps.test.tsx +3 -4
- package/src/hooks/useTimelineAssetDropOps.ts +1 -6
- package/src/hooks/useTimelineEditing.test.tsx +10 -7
- package/src/hooks/useTimelineEditing.ts +2 -7
- package/src/player/components/Timeline.tsx +22 -23
- package/src/player/components/TimelineClip.test.tsx +52 -0
- package/src/player/components/TimelineClip.tsx +13 -2
- package/src/player/components/TimelineTrackHeader.test.tsx +26 -5
- package/src/player/components/TimelineTrackHeader.tsx +1 -1
- package/src/player/components/timelineMotionStyles.test.ts +3 -3
- package/src/player/components/timelineTheme.test.ts +4 -4
- package/src/player/components/timelineTheme.ts +34 -30
- package/src/player/components/timelineTrackDisplay.ts +1 -4
- package/src/player/components/useTimelineTrackDerivations.ts +2 -2
- package/src/player/hooks/timelineSyncHydration.test.ts +0 -18
- package/src/player/hooks/timelineSyncHydration.ts +0 -23
- package/src/player/hooks/useTimelineSyncCallbacks.ts +0 -3
- package/src/player/store/playerStore.ts +0 -4
- package/src/player/store/timelineElement.ts +2 -4
- package/src/player/store/timelineResetState.ts +0 -1
- package/src/styles/hex-baseline.json +3 -4
- package/src/styles/studio.css +7 -7
- package/src/styles/theme.css +29 -0
- package/src/utils/studioSaveDiagnostics.ts +12 -0
- package/src/player/hooks/useTimelineRowElements.test.ts +0 -28
- package/src/player/hooks/useTimelineRowElements.ts +0 -17
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"total":
|
|
2
|
+
"total": 385,
|
|
3
3
|
"files": {
|
|
4
4
|
"packages/studio/src/captions/components/CaptionOverlay.tsx": 5,
|
|
5
5
|
"packages/studio/src/captions/components/CaptionTimeline.tsx": 11,
|
|
@@ -61,7 +61,6 @@
|
|
|
61
61
|
"packages/studio/src/player/components/SpeedMenu.tsx": 2,
|
|
62
62
|
"packages/studio/src/player/components/TimelineAutomationLane.tsx": 4,
|
|
63
63
|
"packages/studio/src/player/components/TimelineCanvas.tsx": 13,
|
|
64
|
-
"packages/studio/src/player/components/TimelineClip.tsx": 2,
|
|
65
64
|
"packages/studio/src/player/components/TimelineClipDiamonds.tsx": 2,
|
|
66
65
|
"packages/studio/src/player/components/TimelineDiamondConnectors.tsx": 2,
|
|
67
66
|
"packages/studio/src/player/components/TimelineEmptyState.tsx": 1,
|
|
@@ -75,9 +74,9 @@
|
|
|
75
74
|
"packages/studio/src/player/components/TimelineTrackHeader.tsx": 2,
|
|
76
75
|
"packages/studio/src/player/components/TimelineTrackPlainHeader.tsx": 2,
|
|
77
76
|
"packages/studio/src/player/components/VideoThumbnail.tsx": 6,
|
|
78
|
-
"packages/studio/src/player/components/timelineTheme.ts":
|
|
77
|
+
"packages/studio/src/player/components/timelineTheme.ts": 5,
|
|
79
78
|
"packages/studio/src/player/components/trackHeaderLabelRows.tsx": 6,
|
|
80
|
-
"packages/studio/src/styles/studio.css":
|
|
79
|
+
"packages/studio/src/styles/studio.css": 63,
|
|
81
80
|
"packages/studio/src/telemetry/client.ts": 1,
|
|
82
81
|
"packages/studio/src/webmcp/webmcpTestUtils.ts": 1
|
|
83
82
|
}
|
package/src/styles/studio.css
CHANGED
|
@@ -200,8 +200,8 @@ body {
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
.timeline-clip {
|
|
203
|
-
background-color:
|
|
204
|
-
border: 1px solid
|
|
203
|
+
background-color: var(--clip-bg);
|
|
204
|
+
border: 1px solid var(--clip-border);
|
|
205
205
|
border-radius: 8px;
|
|
206
206
|
}
|
|
207
207
|
|
|
@@ -210,13 +210,13 @@ body {
|
|
|
210
210
|
position: absolute;
|
|
211
211
|
inset: 0;
|
|
212
212
|
border-radius: inherit;
|
|
213
|
-
background:
|
|
213
|
+
background: var(--clip-bg-active);
|
|
214
214
|
opacity: 0;
|
|
215
215
|
pointer-events: none;
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
.timeline-clip[data-active] {
|
|
219
|
-
border-color:
|
|
219
|
+
border-color: var(--clip-border-active);
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
.timeline-clip[data-active]::before {
|
|
@@ -240,11 +240,11 @@ body {
|
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
.timeline-clip.is-hovered {
|
|
243
|
-
background-color:
|
|
243
|
+
background-color: var(--clip-bg-hover);
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
.timeline-clip[data-active].is-hovered {
|
|
247
|
-
border-color:
|
|
247
|
+
border-color: var(--clip-border-hover);
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
.timeline-clip.is-selected {
|
|
@@ -258,7 +258,7 @@ body {
|
|
|
258
258
|
.timeline-clip.is-dragging {
|
|
259
259
|
/* Solid background so the picked-up clip reads clearly while dragging — audio
|
|
260
260
|
clips (waveform drawn on a separate layer) would otherwise look transparent. */
|
|
261
|
-
background-color:
|
|
261
|
+
background-color: var(--clip-bg-dragging);
|
|
262
262
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
|
|
263
263
|
}
|
|
264
264
|
|
package/src/styles/theme.css
CHANGED
|
@@ -46,6 +46,35 @@
|
|
|
46
46
|
--color-brand-gradient-from: #06e3fa;
|
|
47
47
|
--color-brand-gradient-to: #4fdb5e;
|
|
48
48
|
|
|
49
|
+
/* The timeline's own surfaces: darker and bluer than the shared scale, so they
|
|
50
|
+
* get their own names instead of snapping to the nearest --color-bg/-surface
|
|
51
|
+
* step (a host themes the timeline by overriding these). */
|
|
52
|
+
--timeline-shell-bg: #0a0a0b;
|
|
53
|
+
--timeline-shell-border: rgba(255, 255, 255, 0.05);
|
|
54
|
+
--timeline-ruler-border: rgba(255, 255, 255, 0.16);
|
|
55
|
+
--timeline-row-bg: #101014;
|
|
56
|
+
--timeline-row-border: rgba(255, 255, 255, 0.06);
|
|
57
|
+
--timeline-gutter-bg: #0e0f12;
|
|
58
|
+
--timeline-gutter-border: rgba(255, 255, 255, 0.1);
|
|
59
|
+
--timeline-text-primary: rgba(255, 255, 255, 0.92);
|
|
60
|
+
--timeline-text-secondary: rgba(255, 255, 255, 0.62);
|
|
61
|
+
--timeline-tick-text: rgba(255, 255, 255, 0.34);
|
|
62
|
+
--timeline-tick-major: rgba(255, 255, 255, 0.1);
|
|
63
|
+
--timeline-tick-minor: rgba(255, 255, 255, 0.06);
|
|
64
|
+
--timeline-clip-bg: rgba(255, 255, 255, 0.12);
|
|
65
|
+
--timeline-clip-bg-active: rgba(60, 230, 172, 0.2);
|
|
66
|
+
--timeline-clip-bg-hover: rgba(255, 255, 255, 0.16);
|
|
67
|
+
--timeline-clip-bg-dragging: rgba(38, 42, 52, 0.96);
|
|
68
|
+
--timeline-clip-border: rgba(255, 255, 255, 0.22);
|
|
69
|
+
--timeline-clip-border-hover: rgba(60, 230, 172, 0.75);
|
|
70
|
+
--timeline-clip-border-active: rgba(60, 230, 172, 0.55);
|
|
71
|
+
--timeline-handle: rgba(255, 255, 255, 0.55);
|
|
72
|
+
--timeline-resize-seam: rgba(255, 255, 255, 0.12);
|
|
73
|
+
--timeline-resize-active: rgba(255, 255, 255, 0.24);
|
|
74
|
+
--timeline-track-clip-fill: rgba(255, 255, 255, 0.055);
|
|
75
|
+
--timeline-track-clip-active: rgba(60, 230, 172, 0.16);
|
|
76
|
+
--timeline-track-label: rgba(255, 255, 255, 0.5);
|
|
77
|
+
|
|
49
78
|
/* -------------------------------------------------------------- geometry */
|
|
50
79
|
|
|
51
80
|
--radius-sm: 0.25rem;
|
|
@@ -165,9 +165,21 @@ export function buildStudioSaveFailureProperties(
|
|
|
165
165
|
target_id: input.targetId ?? undefined,
|
|
166
166
|
target_selector: input.targetSelector ?? undefined,
|
|
167
167
|
target_source_file: input.targetSourceFile ?? undefined,
|
|
168
|
+
block_detail: gsapBlockDetail(input.error),
|
|
168
169
|
};
|
|
169
170
|
}
|
|
170
171
|
|
|
172
|
+
/**
|
|
173
|
+
* The specific cause behind a blocked GSAP edit. `error_message` only carries
|
|
174
|
+
* the coarse copy, and one of those strings covers six different situations,
|
|
175
|
+
* so the message alone cannot say which one a user hit.
|
|
176
|
+
*/
|
|
177
|
+
function gsapBlockDetail(error: unknown): string | undefined {
|
|
178
|
+
if (!(error instanceof Error) || error.name !== "GsapEditBlockedError") return undefined;
|
|
179
|
+
const detail = (error as { detail?: unknown }).detail;
|
|
180
|
+
return typeof detail === "string" ? detail : undefined;
|
|
181
|
+
}
|
|
182
|
+
|
|
171
183
|
export function trackStudioSaveFailure(input: StudioSaveFailureInput): void {
|
|
172
184
|
trackStudioEvent("save_failure", buildStudioSaveFailureProperties(input));
|
|
173
185
|
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import type { TimelineElement } from "../store/playerStore";
|
|
3
|
-
import { selectTimelineRowElements } from "./useTimelineRowElements";
|
|
4
|
-
|
|
5
|
-
const el = (id: string, domId?: string): TimelineElement => ({
|
|
6
|
-
id,
|
|
7
|
-
domId,
|
|
8
|
-
start: 0,
|
|
9
|
-
duration: 1,
|
|
10
|
-
track: 0,
|
|
11
|
-
tag: "div",
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
describe("selectTimelineRowElements", () => {
|
|
15
|
-
it("drops an element the shared definition does not call top-level", () => {
|
|
16
|
-
const rows = selectTimelineRowElements([el("a", "a"), el("b", "b")], new Set(["a"]));
|
|
17
|
-
expect(rows.map((r) => r.id)).toEqual(["a"]);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("keeps everything until the document has been read", () => {
|
|
21
|
-
const all = [el("a", "a"), el("b", "b")];
|
|
22
|
-
expect(selectTimelineRowElements(all, null)).toBe(all);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("keeps an element with no DOM id", () => {
|
|
26
|
-
expect(selectTimelineRowElements([el("k")], new Set())).toHaveLength(1);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { useMemo } from "react";
|
|
2
|
-
import { usePlayerStore, type TimelineElement } from "../store/playerStore";
|
|
3
|
-
|
|
4
|
-
/** Rows are the ids `topLevelElements` names, as the lint does; id-less ones are kept. */
|
|
5
|
-
export function selectTimelineRowElements(
|
|
6
|
-
elements: TimelineElement[],
|
|
7
|
-
topLevelIds: ReadonlySet<string> | null,
|
|
8
|
-
): TimelineElement[] {
|
|
9
|
-
if (!topLevelIds) return elements;
|
|
10
|
-
return elements.filter((el) => el.domId === undefined || topLevelIds.has(el.domId));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function useTimelineRowElements(): TimelineElement[] {
|
|
14
|
-
const elements = usePlayerStore((s) => s.elements);
|
|
15
|
-
const topLevelIds = usePlayerStore((s) => s.topLevelIds);
|
|
16
|
-
return useMemo(() => selectTimelineRowElements(elements, topLevelIds), [elements, topLevelIds]);
|
|
17
|
-
}
|