@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.
Files changed (90) hide show
  1. package/dist/assets/{hyperframes-player-Cy_AwUa8.js → hyperframes-player-k8LzMtXX.js} +1 -1
  2. package/dist/assets/{index-DPUJoO8n.js → index-BlkJ_Axe.js} +192 -192
  3. package/dist/assets/{index-CTa-6Kso.js → index-CxR7F2YQ.js} +1 -1
  4. package/dist/assets/{index-DkAzKuPZ.js → index-DFlILHJe.js} +1 -1
  5. package/dist/assets/{index-DrHQAuGO.css → index-ZmBtVrEm.css} +1 -1
  6. package/dist/index.d.ts +16 -8
  7. package/dist/index.html +2 -2
  8. package/dist/index.js +3152 -3010
  9. package/dist/index.js.map +1 -1
  10. package/dist/styles.css +1 -1
  11. package/package.json +7 -7
  12. package/src/App.tsx +14 -1
  13. package/src/components/EditorShell.readOnlyHostMount.test.tsx +116 -0
  14. package/src/components/EditorShell.selectionSync.test.tsx +57 -67
  15. package/src/components/EditorShell.tsx +59 -50
  16. package/src/components/EditorShellTestMocks.ts +46 -0
  17. package/src/components/editor/DomEditOverlay.tsx +19 -40
  18. package/src/components/editor/DomEditOverlayHover.test.tsx +1 -15
  19. package/src/components/editor/DomEditSelectionChrome.tsx +11 -9
  20. package/src/components/editor/PropertyPanel.deselect.test.tsx +71 -0
  21. package/src/components/editor/PropertyPanel.tsx +4 -3
  22. package/src/components/editor/SnapToolbar.test.tsx +1 -0
  23. package/src/components/editor/domEditOverlayTestMocks.ts +16 -0
  24. package/src/components/editor/previewReadOnly.overlay.test.tsx +260 -0
  25. package/src/components/editor/previewReadOnlyContext.tsx +59 -0
  26. package/src/components/editor/propertyPanelFlatLayoutSection.tsx +9 -0
  27. package/src/components/editor/propertyPanelFlatPrimitives.tsx +4 -1
  28. package/src/components/editor/propertyPanelInputCoverage.test.tsx +3 -13
  29. package/src/components/editor/useDomEditNudge.ts +9 -0
  30. package/src/components/editor/useDomEditOverlayGestures.ts +4 -0
  31. package/src/components/editor/useOffCanvasIndicators.ts +50 -0
  32. package/src/components/nle/PreviewOverlays.topologyLens.test.tsx +4 -35
  33. package/src/components/nle/PreviewOverlays.tsx +15 -8
  34. package/src/components/nle/PreviewOverlaysTestMocks.ts +40 -0
  35. package/src/components/nle/TimelinePane.tsx +5 -1
  36. package/src/components/nle/previewReadOnly.test.tsx +128 -0
  37. package/src/components/nle/useCanvasZOrderTimelineMirror.test.tsx +1 -1
  38. package/src/components/nle/useCanvasZOrderTimelineMirror.ts +3 -6
  39. package/src/components/nle/usePreviewBlockDrop.ts +3 -1
  40. package/src/hooks/appHotkeysDispatch.ts +16 -1
  41. package/src/hooks/gsapDragCommit.ts +1 -1
  42. package/src/hooks/gsapEditOutcome.test.ts +115 -0
  43. package/src/hooks/gsapEditOutcome.ts +39 -10
  44. package/src/hooks/gsapResizeIntercept.test.ts +42 -3
  45. package/src/hooks/gsapResizeIntercept.ts +12 -2
  46. package/src/hooks/gsapRuntimeBridge.test.ts +10 -2
  47. package/src/hooks/gsapRuntimeBridge.ts +14 -3
  48. package/src/hooks/newTweenTargetHooks.test.tsx +1 -0
  49. package/src/hooks/timelineAudioGroupCreate.ts +3 -4
  50. package/src/hooks/timelineTrackVisibility.ts +7 -8
  51. package/src/hooks/useAppHotkeys.test.ts +71 -3
  52. package/src/hooks/useAppHotkeys.textEditing.test.tsx +1 -0
  53. package/src/hooks/useAppHotkeys.ts +4 -0
  54. package/src/hooks/useDomEditCommits.test.tsx +1 -0
  55. package/src/hooks/useDomEditCommits.ts +3 -0
  56. package/src/hooks/useDomEditSession.test.tsx +1 -0
  57. package/src/hooks/useDomEditSession.ts +7 -4
  58. package/src/hooks/useDomEditWiring.ts +40 -40
  59. package/src/hooks/useDomGeometryCommits.test.tsx +85 -2
  60. package/src/hooks/useDomGeometryCommits.ts +26 -20
  61. package/src/hooks/useGestureCommit.test.tsx +29 -0
  62. package/src/hooks/useGestureCommit.ts +23 -0
  63. package/src/hooks/useInlineTextEdit.test.tsx +23 -2
  64. package/src/hooks/useInlineTextEdit.ts +11 -2
  65. package/src/hooks/useTimelineAssetDropOps.test.tsx +3 -4
  66. package/src/hooks/useTimelineAssetDropOps.ts +1 -6
  67. package/src/hooks/useTimelineEditing.test.tsx +10 -7
  68. package/src/hooks/useTimelineEditing.ts +2 -7
  69. package/src/player/components/Timeline.tsx +22 -23
  70. package/src/player/components/TimelineClip.test.tsx +52 -0
  71. package/src/player/components/TimelineClip.tsx +13 -2
  72. package/src/player/components/TimelineTrackHeader.test.tsx +26 -5
  73. package/src/player/components/TimelineTrackHeader.tsx +1 -1
  74. package/src/player/components/timelineMotionStyles.test.ts +3 -3
  75. package/src/player/components/timelineTheme.test.ts +4 -4
  76. package/src/player/components/timelineTheme.ts +34 -30
  77. package/src/player/components/timelineTrackDisplay.ts +1 -4
  78. package/src/player/components/useTimelineTrackDerivations.ts +2 -2
  79. package/src/player/hooks/timelineSyncHydration.test.ts +0 -18
  80. package/src/player/hooks/timelineSyncHydration.ts +0 -23
  81. package/src/player/hooks/useTimelineSyncCallbacks.ts +0 -3
  82. package/src/player/store/playerStore.ts +0 -4
  83. package/src/player/store/timelineElement.ts +2 -4
  84. package/src/player/store/timelineResetState.ts +0 -1
  85. package/src/styles/hex-baseline.json +3 -4
  86. package/src/styles/studio.css +7 -7
  87. package/src/styles/theme.css +29 -0
  88. package/src/utils/studioSaveDiagnostics.ts +12 -0
  89. package/src/player/hooks/useTimelineRowElements.test.ts +0 -28
  90. package/src/player/hooks/useTimelineRowElements.ts +0 -17
@@ -1,5 +1,5 @@
1
1
  {
2
- "total": 418,
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": 29,
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": 70,
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
  }
@@ -200,8 +200,8 @@ body {
200
200
  }
201
201
 
202
202
  .timeline-clip {
203
- background-color: rgba(255, 255, 255, 0.055);
204
- border: 1px solid rgba(255, 255, 255, 0.09);
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: rgba(60, 230, 172, 0.2);
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: rgba(60, 230, 172, 0.55);
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: rgba(255, 255, 255, 0.09);
243
+ background-color: var(--clip-bg-hover);
244
244
  }
245
245
 
246
246
  .timeline-clip[data-active].is-hovered {
247
- border-color: rgba(60, 230, 172, 0.75);
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: rgba(38, 42, 52, 0.96);
261
+ background-color: var(--clip-bg-dragging);
262
262
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
263
263
  }
264
264
 
@@ -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
- }