@hyperframes/studio 0.8.194 → 0.8.196
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-DLOUZUct.js → hyperframes-player-DG3nZ1bE.js} +1 -1
- package/dist/assets/{index-CAQ7OcNJ.js → index-BS2__aBb.js} +134 -134
- package/dist/assets/{index-D9kA6JUX.js → index-C1r59TIq.js} +1 -1
- package/dist/index.html +1 -1
- package/dist/index.js +16 -8
- package/package.json +9 -9
- package/src/components/editor/useLayerRevealOverride.test.ts +28 -0
- package/src/components/editor/useLayerRevealOverride.ts +12 -7
- package/src/hooks/useGestureRecording.test.tsx +42 -0
- package/src/hooks/useGestureRecording.ts +6 -1
- package/src/utils/gsapSoftReload.test.ts +19 -0
package/dist/index.html
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
document.documentElement.dataset.theme = "paper";
|
|
15
15
|
}
|
|
16
16
|
</script>
|
|
17
|
-
<script type="module" crossorigin src="/assets/index-
|
|
17
|
+
<script type="module" crossorigin src="/assets/index-BS2__aBb.js"></script>
|
|
18
18
|
<link rel="stylesheet" crossorigin href="/assets/index-CYbvOVp-.css">
|
|
19
19
|
</head>
|
|
20
20
|
<body>
|
package/dist/index.js
CHANGED
|
@@ -43356,6 +43356,7 @@ import { useCallback as useCallback61 } from "react";
|
|
|
43356
43356
|
|
|
43357
43357
|
// src/components/editor/useLayerRevealOverride.ts
|
|
43358
43358
|
import { useCallback as useCallback60, useEffect as useEffect56, useRef as useRef73 } from "react";
|
|
43359
|
+
import { revealClip } from "@hyperframes/core/runtime/clip-reveal";
|
|
43359
43360
|
var LAYER_REVEAL_LIFT_Z = "2147483000";
|
|
43360
43361
|
var LAYER_REVEAL_PENDING_COMMIT_ATTR = "data-hf-studio-reveal-pending-commit";
|
|
43361
43362
|
var revealCommitSequence = 0;
|
|
@@ -43436,9 +43437,10 @@ function rollbackLayerRevealCommit(element, ownership) {
|
|
|
43436
43437
|
}
|
|
43437
43438
|
}
|
|
43438
43439
|
function restoreIfOurs(el, property, applied, prior) {
|
|
43439
|
-
if (applied == null) return;
|
|
43440
|
-
if (el.style.getPropertyValue(property) !== applied) return;
|
|
43440
|
+
if (applied == null) return false;
|
|
43441
|
+
if (el.style.getPropertyValue(property) !== applied) return false;
|
|
43441
43442
|
restoreInline(el, property, prior);
|
|
43443
|
+
return true;
|
|
43442
43444
|
}
|
|
43443
43445
|
function readHideSignals(el, win) {
|
|
43444
43446
|
const computed = win.getComputedStyle(el);
|
|
@@ -43456,20 +43458,21 @@ function revealNode(el, win, needs) {
|
|
|
43456
43458
|
opacity: el.style.opacity
|
|
43457
43459
|
};
|
|
43458
43460
|
const applied = {};
|
|
43461
|
+
let putMarkBack;
|
|
43459
43462
|
if (needs.display) {
|
|
43460
43463
|
el.style.removeProperty("display");
|
|
43461
43464
|
if (win.getComputedStyle(el).display === "none") el.style.display = "block";
|
|
43462
43465
|
applied.display = el.style.display;
|
|
43463
43466
|
}
|
|
43464
43467
|
if (needs.visibility) {
|
|
43465
|
-
|
|
43468
|
+
putMarkBack = revealClip(el);
|
|
43466
43469
|
applied.visibility = "visible";
|
|
43467
43470
|
}
|
|
43468
43471
|
if (needs.opacity) {
|
|
43469
43472
|
el.style.opacity = "1";
|
|
43470
43473
|
applied.opacity = "1";
|
|
43471
43474
|
}
|
|
43472
|
-
return { element: el, priors, applied };
|
|
43475
|
+
return { element: el, priors, applied, putMarkBack };
|
|
43473
43476
|
}
|
|
43474
43477
|
function revealHiddenChain(element) {
|
|
43475
43478
|
const doc = element.ownerDocument;
|
|
@@ -43538,10 +43541,11 @@ function useLayerRevealOverride({
|
|
|
43538
43541
|
const state = stateRef.current;
|
|
43539
43542
|
stateRef.current = null;
|
|
43540
43543
|
if (!state) return;
|
|
43541
|
-
for (const { element, priors, applied } of state.nodes) {
|
|
43544
|
+
for (const { element, priors, applied, putMarkBack } of state.nodes) {
|
|
43542
43545
|
if (!element.isConnected) continue;
|
|
43543
43546
|
restoreIfOurs(element, "display", applied.display, priors.display);
|
|
43544
|
-
restoreIfOurs(element, "visibility", applied.visibility, priors.visibility)
|
|
43547
|
+
if (restoreIfOurs(element, "visibility", applied.visibility, priors.visibility))
|
|
43548
|
+
putMarkBack?.();
|
|
43545
43549
|
restoreIfOurs(element, "opacity", applied.opacity, priors.opacity);
|
|
43546
43550
|
}
|
|
43547
43551
|
if (state.lift && state.base.isConnected) restoreLiftedElement(state.base, state.lift);
|
|
@@ -90886,6 +90890,7 @@ var StudioHeader = memo46(function StudioHeader2({
|
|
|
90886
90890
|
import { useState as useState136, useCallback as useCallback164, useRef as useRef169, useEffect as useEffect136 } from "react";
|
|
90887
90891
|
|
|
90888
90892
|
// src/hooks/useGestureRecording.ts
|
|
90893
|
+
import { revealClip as revealClip2 } from "@hyperframes/core/runtime/clip-reveal";
|
|
90889
90894
|
import { useCallback as useCallback163, useEffect as useEffect135, useRef as useRef168, useState as useState135 } from "react";
|
|
90890
90895
|
function readBasePosition(element, iframeEl) {
|
|
90891
90896
|
let baseOpacity = 1;
|
|
@@ -90926,7 +90931,8 @@ function connectGsapRuntime(element, iframeEl, elementEndTime) {
|
|
|
90926
90931
|
startTime: win.__player?.getTime() ?? 0,
|
|
90927
90932
|
maxSeekTime: elementEndTime != null && elementEndTime < tlDuration ? elementEndTime : tlDuration,
|
|
90928
90933
|
savedVisibility: element.style.visibility,
|
|
90929
|
-
savedTranslate: element.style.getPropertyValue("translate")
|
|
90934
|
+
savedTranslate: element.style.getPropertyValue("translate"),
|
|
90935
|
+
putMarkBack: null
|
|
90930
90936
|
};
|
|
90931
90937
|
}
|
|
90932
90938
|
} catch {
|
|
@@ -90938,7 +90944,8 @@ function applyRuntimePreview(runtime, time, properties) {
|
|
|
90938
90944
|
runtime.timeline.seek(seekTime);
|
|
90939
90945
|
runtime.element.style.setProperty("translate", "none");
|
|
90940
90946
|
runtime.gsap.set(runtime.element, { ...properties });
|
|
90941
|
-
runtime.element
|
|
90947
|
+
const putMarkBack = revealClip2(runtime.element);
|
|
90948
|
+
runtime.putMarkBack ??= putMarkBack;
|
|
90942
90949
|
liveTime.notify(seekTime);
|
|
90943
90950
|
usePlayerStore.getState().setCurrentTime(seekTime);
|
|
90944
90951
|
}
|
|
@@ -91014,6 +91021,7 @@ function releaseRuntimePreview(r) {
|
|
|
91014
91021
|
if (!runtime) return;
|
|
91015
91022
|
const { element, savedVisibility, savedTranslate } = runtime;
|
|
91016
91023
|
element.style.visibility = savedVisibility;
|
|
91024
|
+
runtime.putMarkBack?.();
|
|
91017
91025
|
element.style.setProperty("translate", savedTranslate || "");
|
|
91018
91026
|
try {
|
|
91019
91027
|
runtime.gsap.set(runtime.element, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/studio",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.196",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -60,12 +60,12 @@
|
|
|
60
60
|
"dockview-react": "8.3.1",
|
|
61
61
|
"gsap": "^3.13.0",
|
|
62
62
|
"mediabunny": "^1.45.3",
|
|
63
|
-
"@hyperframes/
|
|
64
|
-
"@hyperframes/
|
|
65
|
-
"@hyperframes/
|
|
66
|
-
"@hyperframes/
|
|
67
|
-
"@hyperframes/player": "0.8.
|
|
68
|
-
"@hyperframes/
|
|
63
|
+
"@hyperframes/sdk": "0.8.196",
|
|
64
|
+
"@hyperframes/parsers": "0.8.196",
|
|
65
|
+
"@hyperframes/core": "0.8.196",
|
|
66
|
+
"@hyperframes/studio-server": "0.8.196",
|
|
67
|
+
"@hyperframes/player": "0.8.196",
|
|
68
|
+
"@hyperframes/shader-transitions": "0.8.196"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@tailwindcss/vite": "^4.3.3",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"@types/react-dom": "19",
|
|
74
74
|
"@vitejs/plugin-react": "^4.0.0",
|
|
75
75
|
"chokidar": "^4.0.3",
|
|
76
|
-
"esbuild": "^0.
|
|
76
|
+
"esbuild": "^0.28.2",
|
|
77
77
|
"fake-indexeddb": "^6.2.5",
|
|
78
78
|
"puppeteer-core": "^25.2.1",
|
|
79
79
|
"tailwindcss": "^4.3.3",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"vite": "^6.4.2",
|
|
83
83
|
"vitest": "^4.1.11",
|
|
84
84
|
"zustand": "^5.0.0",
|
|
85
|
-
"@hyperframes/producer": "0.8.
|
|
85
|
+
"@hyperframes/producer": "0.8.196"
|
|
86
86
|
},
|
|
87
87
|
"peerDependencies": {
|
|
88
88
|
"react": "19",
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
readTimelineElementZIndex,
|
|
19
19
|
} from "../../player/lib/timelineElementHelpers";
|
|
20
20
|
import { installReactActEnvironment } from "../../hooks/domSelectionTestHarness";
|
|
21
|
+
import { CLIP_HIDDEN_ATTR } from "@hyperframes/core/runtime/clip-reveal";
|
|
21
22
|
|
|
22
23
|
installReactActEnvironment();
|
|
23
24
|
|
|
@@ -149,6 +150,33 @@ describe("useLayerRevealOverride — delayed reveal ownership", () => {
|
|
|
149
150
|
act(() => root.unmount());
|
|
150
151
|
});
|
|
151
152
|
|
|
153
|
+
it("lifts the runtime's hidden-clip mark with the visibility it forces, and puts both back", () => {
|
|
154
|
+
const host = document.createElement("div");
|
|
155
|
+
const clip = makeEl("2", "absolute");
|
|
156
|
+
clip.style.visibility = "hidden";
|
|
157
|
+
clip.setAttribute(CLIP_HIDDEN_ATTR, "");
|
|
158
|
+
document.body.appendChild(host);
|
|
159
|
+
const root = createRoot(host);
|
|
160
|
+
let scheduleReveal: ((element: HTMLElement, delayMs: number) => void) | undefined;
|
|
161
|
+
|
|
162
|
+
function Harness({ isPlaying }: { isPlaying: boolean }) {
|
|
163
|
+
({ scheduleReveal } = useLayerRevealOverride({ isPlaying, selectedElement: clip }));
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
act(() => root.render(React.createElement(Harness, { isPlaying: false })));
|
|
168
|
+
act(() => scheduleReveal!(clip, 0));
|
|
169
|
+
act(() => vi.advanceTimersByTime(0));
|
|
170
|
+
expect([clip.style.visibility, clip.hasAttribute(CLIP_HIDDEN_ATTR)]).toEqual([
|
|
171
|
+
"visible",
|
|
172
|
+
false,
|
|
173
|
+
]);
|
|
174
|
+
|
|
175
|
+
act(() => root.render(React.createElement(Harness, { isPlaying: true })));
|
|
176
|
+
expect([clip.style.visibility, clip.hasAttribute(CLIP_HIDDEN_ATTR)]).toEqual(["hidden", true]);
|
|
177
|
+
act(() => root.unmount());
|
|
178
|
+
});
|
|
179
|
+
|
|
152
180
|
it("revalidates the current selection before a delayed reveal runs", () => {
|
|
153
181
|
const host = document.createElement("div");
|
|
154
182
|
const selected = makeEl("2", "absolute");
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef } from "react";
|
|
2
|
+
import { revealClip } from "@hyperframes/core/runtime/clip-reveal";
|
|
2
3
|
import {
|
|
3
4
|
LAYER_REVEAL_PRIOR_POSITION_ATTR,
|
|
4
5
|
LAYER_REVEAL_PRIOR_Z_ATTR,
|
|
@@ -15,6 +16,7 @@ interface RevealedNode {
|
|
|
15
16
|
priors: { display: string; visibility: string; opacity: string };
|
|
16
17
|
/** Values THIS override wrote — restore only while they are still in place. */
|
|
17
18
|
applied: { display?: string; visibility?: string; opacity?: string };
|
|
19
|
+
putMarkBack?: () => void;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
interface RevealLift {
|
|
@@ -158,10 +160,11 @@ function restoreIfOurs(
|
|
|
158
160
|
property: "display" | "visibility" | "opacity",
|
|
159
161
|
applied: string | undefined,
|
|
160
162
|
prior: string,
|
|
161
|
-
):
|
|
162
|
-
if (applied == null) return;
|
|
163
|
-
if (el.style.getPropertyValue(property) !== applied) return;
|
|
163
|
+
): boolean {
|
|
164
|
+
if (applied == null) return false;
|
|
165
|
+
if (el.style.getPropertyValue(property) !== applied) return false;
|
|
164
166
|
restoreInline(el, property, prior);
|
|
167
|
+
return true;
|
|
165
168
|
}
|
|
166
169
|
|
|
167
170
|
/** What hides this node at the current frame, per computed style. */
|
|
@@ -187,6 +190,7 @@ function revealNode(
|
|
|
187
190
|
opacity: el.style.opacity,
|
|
188
191
|
};
|
|
189
192
|
const applied: RevealedNode["applied"] = {};
|
|
193
|
+
let putMarkBack: RevealedNode["putMarkBack"];
|
|
190
194
|
if (needs.display) {
|
|
191
195
|
// Prefer whatever the stylesheet says once the inline hide is lifted;
|
|
192
196
|
// only force block when the sheet itself hides it.
|
|
@@ -195,14 +199,14 @@ function revealNode(
|
|
|
195
199
|
applied.display = el.style.display;
|
|
196
200
|
}
|
|
197
201
|
if (needs.visibility) {
|
|
198
|
-
|
|
202
|
+
putMarkBack = revealClip(el);
|
|
199
203
|
applied.visibility = "visible";
|
|
200
204
|
}
|
|
201
205
|
if (needs.opacity) {
|
|
202
206
|
el.style.opacity = "1";
|
|
203
207
|
applied.opacity = "1";
|
|
204
208
|
}
|
|
205
|
-
return { element: el, priors, applied };
|
|
209
|
+
return { element: el, priors, applied, putMarkBack };
|
|
206
210
|
}
|
|
207
211
|
|
|
208
212
|
/** Walk `element` → body, force-revealing every hiding node; returns the touched nodes. */
|
|
@@ -317,10 +321,11 @@ export function useLayerRevealOverride({
|
|
|
317
321
|
const state = stateRef.current;
|
|
318
322
|
stateRef.current = null;
|
|
319
323
|
if (!state) return;
|
|
320
|
-
for (const { element, priors, applied } of state.nodes) {
|
|
324
|
+
for (const { element, priors, applied, putMarkBack } of state.nodes) {
|
|
321
325
|
if (!element.isConnected) continue;
|
|
322
326
|
restoreIfOurs(element, "display", applied.display, priors.display);
|
|
323
|
-
restoreIfOurs(element, "visibility", applied.visibility, priors.visibility)
|
|
327
|
+
if (restoreIfOurs(element, "visibility", applied.visibility, priors.visibility))
|
|
328
|
+
putMarkBack?.();
|
|
324
329
|
restoreIfOurs(element, "opacity", applied.opacity, priors.opacity);
|
|
325
330
|
}
|
|
326
331
|
if (state.lift && state.base.isConnected) restoreLiftedElement(state.base, state.lift);
|
|
@@ -4,6 +4,7 @@ import React, { act } from "react";
|
|
|
4
4
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
5
|
import { mountReactHarness } from "./domSelectionTestHarness";
|
|
6
6
|
import { useGestureRecording, type GestureSample } from "./useGestureRecording";
|
|
7
|
+
import { CLIP_HIDDEN_ATTR } from "@hyperframes/core/runtime/clip-reveal";
|
|
7
8
|
|
|
8
9
|
Reflect.set(globalThis, "IS_REACT_ACT_ENVIRONMENT", true);
|
|
9
10
|
|
|
@@ -65,6 +66,47 @@ describe("useGestureRecording", () => {
|
|
|
65
66
|
act(() => root.unmount());
|
|
66
67
|
});
|
|
67
68
|
|
|
69
|
+
it("lifts the runtime's hidden-clip mark while previewing a hidden clip and puts it back on release", () => {
|
|
70
|
+
const animationFrames: FrameRequestCallback[] = [];
|
|
71
|
+
vi.stubGlobal(
|
|
72
|
+
"requestAnimationFrame",
|
|
73
|
+
vi.fn((callback: FrameRequestCallback) => animationFrames.push(callback)),
|
|
74
|
+
);
|
|
75
|
+
vi.stubGlobal("cancelAnimationFrame", vi.fn());
|
|
76
|
+
const iframe = document.createElement("iframe");
|
|
77
|
+
document.body.append(iframe);
|
|
78
|
+
const element = iframe.contentDocument!.createElement("div");
|
|
79
|
+
element.id = "card";
|
|
80
|
+
element.style.visibility = "hidden";
|
|
81
|
+
element.setAttribute(CLIP_HIDDEN_ATTR, "");
|
|
82
|
+
iframe.contentDocument!.body.append(element);
|
|
83
|
+
Reflect.set(iframe.contentWindow!, "gsap", { getProperty: vi.fn(() => 0), set: vi.fn() });
|
|
84
|
+
Reflect.set(iframe.contentWindow!, "__timelines", {
|
|
85
|
+
main: { duration: () => 5, seek: vi.fn() },
|
|
86
|
+
});
|
|
87
|
+
Reflect.set(iframe.contentWindow!, "__player", { getTime: () => 1 });
|
|
88
|
+
|
|
89
|
+
let recording: ReturnType<typeof useGestureRecording> | null = null;
|
|
90
|
+
function Harness() {
|
|
91
|
+
recording = useGestureRecording();
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
const root = mountReactHarness(<Harness />);
|
|
95
|
+
act(() => recording?.startRecording(element, iframe, 4));
|
|
96
|
+
document.dispatchEvent(new MouseEvent("pointermove", { bubbles: true, clientX: 10 }));
|
|
97
|
+
act(() => animationFrames.shift()?.(1));
|
|
98
|
+
expect([element.style.visibility, element.hasAttribute(CLIP_HIDDEN_ATTR)]).toEqual([
|
|
99
|
+
"visible",
|
|
100
|
+
false,
|
|
101
|
+
]);
|
|
102
|
+
|
|
103
|
+
act(() => root.unmount());
|
|
104
|
+
expect([element.style.visibility, element.hasAttribute(CLIP_HIDDEN_ATTR)]).toEqual([
|
|
105
|
+
"hidden",
|
|
106
|
+
true,
|
|
107
|
+
]);
|
|
108
|
+
});
|
|
109
|
+
|
|
68
110
|
it("releases the preview runtime when unmounted during a recording", () => {
|
|
69
111
|
const cancelAnimationFrame = vi.fn();
|
|
70
112
|
vi.stubGlobal(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { revealClip } from "@hyperframes/core/runtime/clip-reveal";
|
|
1
2
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
3
|
import { usePlayerStore, liveTime } from "../player/store/playerStore";
|
|
3
4
|
import { frameToSeconds, secondsToFrame } from "../player/lib/time";
|
|
@@ -36,6 +37,7 @@ interface GsapRuntime {
|
|
|
36
37
|
maxSeekTime: number;
|
|
37
38
|
savedVisibility: string;
|
|
38
39
|
savedTranslate: string;
|
|
40
|
+
putMarkBack: (() => void) | null;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
// ---------------------------------------------------------------------------
|
|
@@ -107,6 +109,7 @@ function connectGsapRuntime(
|
|
|
107
109
|
elementEndTime != null && elementEndTime < tlDuration ? elementEndTime : tlDuration,
|
|
108
110
|
savedVisibility: element.style.visibility,
|
|
109
111
|
savedTranslate: element.style.getPropertyValue("translate"),
|
|
112
|
+
putMarkBack: null,
|
|
110
113
|
};
|
|
111
114
|
}
|
|
112
115
|
} catch {
|
|
@@ -124,7 +127,8 @@ function applyRuntimePreview(
|
|
|
124
127
|
runtime.timeline.seek(seekTime);
|
|
125
128
|
runtime.element.style.setProperty("translate", "none");
|
|
126
129
|
runtime.gsap.set(runtime.element, { ...properties });
|
|
127
|
-
runtime.element
|
|
130
|
+
const putMarkBack = revealClip(runtime.element);
|
|
131
|
+
runtime.putMarkBack ??= putMarkBack;
|
|
128
132
|
liveTime.notify(seekTime);
|
|
129
133
|
usePlayerStore.getState().setCurrentTime(seekTime);
|
|
130
134
|
}
|
|
@@ -251,6 +255,7 @@ function releaseRuntimePreview(r: RecordingRefs): void {
|
|
|
251
255
|
if (!runtime) return;
|
|
252
256
|
const { element, savedVisibility, savedTranslate } = runtime;
|
|
253
257
|
element.style.visibility = savedVisibility;
|
|
258
|
+
runtime.putMarkBack?.();
|
|
254
259
|
element.style.setProperty("translate", savedTranslate || "");
|
|
255
260
|
try {
|
|
256
261
|
runtime.gsap.set(runtime.element, {
|
|
@@ -532,6 +532,25 @@ describe("ensureMotionPathPluginLoaded", () => {
|
|
|
532
532
|
expect(appendedScripts).toHaveLength(1);
|
|
533
533
|
});
|
|
534
534
|
|
|
535
|
+
it.each([
|
|
536
|
+
["3.15.0", "/api/vendor/npm/gsap@3.15.0/dist/MotionPathPlugin.min.js"],
|
|
537
|
+
["3.14.2", "https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/MotionPathPlugin.min.js"],
|
|
538
|
+
])(
|
|
539
|
+
"preloads gsap %s from the host's bundled copy only when it holds that version",
|
|
540
|
+
(version, url) => {
|
|
541
|
+
const { iframe, appendedScripts } = buildBootstrapIframe({
|
|
542
|
+
gsap: { version, registerPlugin: vi.fn() },
|
|
543
|
+
});
|
|
544
|
+
const meta = document.createElement("meta");
|
|
545
|
+
meta.name = "hyperframes-gsap-base-url";
|
|
546
|
+
meta.content = "/api/vendor/npm";
|
|
547
|
+
iframe.contentDocument!.head.appendChild(meta);
|
|
548
|
+
ensureMotionPathPluginLoaded(iframe);
|
|
549
|
+
expect(appendedScripts).toHaveLength(1);
|
|
550
|
+
expect(appendedScripts[0]!.getAttribute("src")).toBe(url);
|
|
551
|
+
},
|
|
552
|
+
);
|
|
553
|
+
|
|
535
554
|
it("appends the plugin script once and registers it on load", () => {
|
|
536
555
|
const { iframe, contentWindow, appendedScripts, registerPlugin } = buildBootstrapIframe();
|
|
537
556
|
ensureMotionPathPluginLoaded(iframe);
|