@midscene/visualizer 1.5.2 → 1.5.3-beta-20260305031416.0

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 (43) hide show
  1. package/dist/es/component/blackboard/index.css +82 -4
  2. package/dist/es/component/blackboard/index.mjs +73 -301
  3. package/dist/es/component/player/index.css +144 -119
  4. package/dist/es/component/player/index.mjs +468 -830
  5. package/dist/es/component/player/remotion/StepScene.mjs +190 -0
  6. package/dist/es/component/player/remotion/derive-frame-state.mjs +207 -0
  7. package/dist/es/component/player/remotion/export-branded-video.mjs +210 -0
  8. package/dist/es/component/player/remotion/frame-calculator.mjs +149 -0
  9. package/dist/es/component/player/use-frame-player.mjs +88 -0
  10. package/dist/es/component/universal-playground/index.mjs +14 -1
  11. package/dist/es/hooks/usePlaygroundExecution.mjs +11 -7
  12. package/dist/es/index.mjs +2 -2
  13. package/dist/es/store/store.mjs +9 -0
  14. package/dist/es/utils/replay-scripts.mjs +78 -59
  15. package/dist/lib/component/blackboard/index.css +82 -4
  16. package/dist/lib/component/blackboard/index.js +73 -307
  17. package/dist/lib/component/player/index.css +144 -119
  18. package/dist/lib/component/player/index.js +466 -828
  19. package/dist/lib/component/player/remotion/StepScene.js +224 -0
  20. package/dist/lib/component/player/remotion/derive-frame-state.js +241 -0
  21. package/dist/lib/component/player/remotion/export-branded-video.js +244 -0
  22. package/dist/lib/component/player/remotion/frame-calculator.js +186 -0
  23. package/dist/lib/component/player/use-frame-player.js +122 -0
  24. package/dist/lib/component/universal-playground/index.js +14 -1
  25. package/dist/lib/hooks/usePlaygroundExecution.js +11 -7
  26. package/dist/lib/index.js +3 -0
  27. package/dist/lib/store/store.js +9 -0
  28. package/dist/lib/utils/replay-scripts.js +80 -58
  29. package/dist/types/component/blackboard/index.d.ts +0 -4
  30. package/dist/types/component/player/index.d.ts +0 -1
  31. package/dist/types/component/player/remotion/StepScene.d.ts +9 -0
  32. package/dist/types/component/player/remotion/derive-frame-state.d.ts +38 -0
  33. package/dist/types/component/player/remotion/export-branded-video.d.ts +2 -0
  34. package/dist/types/component/player/remotion/frame-calculator.d.ts +35 -0
  35. package/dist/types/component/player/use-frame-player.d.ts +17 -0
  36. package/dist/types/hooks/usePlaygroundExecution.d.ts +15 -1
  37. package/dist/types/index.d.ts +1 -1
  38. package/dist/types/store/store.d.ts +2 -0
  39. package/dist/types/utils/replay-scripts.d.ts +16 -1
  40. package/package.json +5 -8
  41. package/dist/es/utils/pixi-loader.mjs +0 -42
  42. package/dist/lib/utils/pixi-loader.js +0 -82
  43. package/dist/types/utils/pixi-loader.d.ts +0 -5
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ exportBrandedVideo: ()=>exportBrandedVideo
28
+ });
29
+ const index_js_namespaceObject = require("../../../utils/index.js");
30
+ const external_derive_frame_state_js_namespaceObject = require("./derive-frame-state.js");
31
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
32
+ try {
33
+ var info = gen[key](arg);
34
+ var value = info.value;
35
+ } catch (error) {
36
+ reject(error);
37
+ return;
38
+ }
39
+ if (info.done) resolve(value);
40
+ else Promise.resolve(value).then(_next, _throw);
41
+ }
42
+ function _async_to_generator(fn) {
43
+ return function() {
44
+ var self = this, args = arguments;
45
+ return new Promise(function(resolve, reject) {
46
+ var gen = fn.apply(self, args);
47
+ function _next(value) {
48
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
49
+ }
50
+ function _throw(err) {
51
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
52
+ }
53
+ _next(void 0);
54
+ });
55
+ };
56
+ }
57
+ const W = 960;
58
+ const H = 540;
59
+ const POINTER_PHASE = 0.375;
60
+ const CROSSFADE_FRAMES = 10;
61
+ function clamp(v, lo, hi) {
62
+ return Math.min(Math.max(v, lo), hi);
63
+ }
64
+ function lerp(a, b, t) {
65
+ return a + (b - a) * t;
66
+ }
67
+ function loadImage(src) {
68
+ return new Promise((resolve, reject)=>{
69
+ const img = new Image();
70
+ img.crossOrigin = 'anonymous';
71
+ img.onload = ()=>resolve(img);
72
+ img.onerror = reject;
73
+ img.src = src;
74
+ });
75
+ }
76
+ function drawInsightOverlays(ctx, insights, cameraTransform, bx, contentY) {
77
+ for (const insight of insights)if (!(insight.alpha <= 0)) {
78
+ ctx.save();
79
+ ctx.globalAlpha *= insight.alpha;
80
+ if (insight.highlightElement) {
81
+ const r = insight.highlightElement.rect;
82
+ const rx = bx + (r.left * cameraTransform.zoom + cameraTransform.tx * cameraTransform.zoom);
83
+ const ry = contentY + (r.top * cameraTransform.zoom + cameraTransform.ty * cameraTransform.zoom);
84
+ const rw = r.width * cameraTransform.zoom;
85
+ const rh = r.height * cameraTransform.zoom;
86
+ ctx.fillStyle = 'rgba(253, 89, 7, 0.4)';
87
+ ctx.fillRect(rx, ry, rw, rh);
88
+ ctx.strokeStyle = '#fd5907';
89
+ ctx.lineWidth = 1;
90
+ ctx.strokeRect(rx, ry, rw, rh);
91
+ ctx.shadowColor = 'rgba(51, 51, 51, 0.4)';
92
+ ctx.shadowBlur = 2;
93
+ ctx.shadowOffsetX = 4;
94
+ ctx.shadowOffsetY = 4;
95
+ ctx.strokeRect(rx, ry, rw, rh);
96
+ ctx.shadowBlur = 0;
97
+ ctx.shadowOffsetX = 0;
98
+ ctx.shadowOffsetY = 0;
99
+ }
100
+ if (insight.searchArea) {
101
+ const r = insight.searchArea;
102
+ const rx = bx + (r.left * cameraTransform.zoom + cameraTransform.tx * cameraTransform.zoom);
103
+ const ry = contentY + (r.top * cameraTransform.zoom + cameraTransform.ty * cameraTransform.zoom);
104
+ const rw = r.width * cameraTransform.zoom;
105
+ const rh = r.height * cameraTransform.zoom;
106
+ ctx.fillStyle = 'rgba(2, 131, 145, 0.4)';
107
+ ctx.fillRect(rx, ry, rw, rh);
108
+ ctx.strokeStyle = '#028391';
109
+ ctx.lineWidth = 1;
110
+ ctx.strokeRect(rx, ry, rw, rh);
111
+ }
112
+ ctx.restore();
113
+ }
114
+ }
115
+ function drawSpinningPointer(ctx, img, x, y, elapsedMs) {
116
+ const progress = (Math.sin(elapsedMs / 500 - Math.PI / 2) + 1) / 2;
117
+ const rotation = progress * Math.PI * 2;
118
+ ctx.save();
119
+ ctx.translate(x, y);
120
+ ctx.rotate(rotation);
121
+ ctx.drawImage(img, -11, -14, 22, 28);
122
+ ctx.restore();
123
+ }
124
+ function drawSteps(ctx, stepsFrame, frameMap, imgCache, cursorImg, spinnerImg) {
125
+ const { scriptFrames, imageWidth: baseW, imageHeight: baseH, fps } = frameMap;
126
+ const st = (0, external_derive_frame_state_js_namespaceObject.deriveFrameState)(scriptFrames, stepsFrame, baseW, baseH, fps);
127
+ if (!st.img) return;
128
+ const { img, prevImg, imageWidth: imgW, imageHeight: imgH, camera, prevCamera, pointerMoved, imageChanged, rawProgress, frameInScript: fInScript, spinning, spinningElapsedMs, insights } = st;
129
+ const pT = pointerMoved ? Math.min(rawProgress / POINTER_PHASE, 1) : rawProgress;
130
+ const cT = pointerMoved ? rawProgress <= POINTER_PHASE ? 0 : Math.min((rawProgress - POINTER_PHASE) / (1 - POINTER_PHASE), 1) : rawProgress;
131
+ const camL = lerp(prevCamera.left, camera.left, cT);
132
+ const camT2 = lerp(prevCamera.top, camera.top, cT);
133
+ const camW = lerp(prevCamera.width, camera.width, cT);
134
+ const ptrX = lerp(prevCamera.pointerLeft, camera.pointerLeft, pT);
135
+ const ptrY = lerp(prevCamera.pointerTop, camera.pointerTop, pT);
136
+ const zoom = imgW / camW;
137
+ const tx = W / imgW * -camL;
138
+ const ty = H / imgH * -camT2;
139
+ const crossAlpha = imageChanged ? clamp(fInScript / CROSSFADE_FRAMES, 0, 1) : 1;
140
+ ctx.fillStyle = '#000';
141
+ ctx.fillRect(0, 0, W, H);
142
+ const drawImg = (src, alpha)=>{
143
+ const imgEl = imgCache.get(src);
144
+ if (!imgEl || alpha <= 0) return;
145
+ ctx.save();
146
+ ctx.globalAlpha = alpha;
147
+ ctx.beginPath();
148
+ ctx.rect(0, 0, W, H);
149
+ ctx.clip();
150
+ ctx.translate(tx * zoom, ty * zoom);
151
+ ctx.scale(zoom, zoom);
152
+ ctx.drawImage(imgEl, 0, 0, W, H);
153
+ ctx.restore();
154
+ };
155
+ if (imageChanged && prevImg && crossAlpha < 1) drawImg(prevImg, 1 - crossAlpha);
156
+ drawImg(img, imageChanged ? crossAlpha : 1);
157
+ if (insights.length > 0) drawInsightOverlays(ctx, insights, {
158
+ zoom,
159
+ tx,
160
+ ty
161
+ }, 0, 0);
162
+ const camH = imgH / imgW * camW;
163
+ const sX = (ptrX - camL) / camW * W;
164
+ const sY = (ptrY - camT2) / camH * H;
165
+ const hasPtrData = Math.abs(camera.pointerLeft - Math.round(baseW / 2)) > 1 || Math.abs(camera.pointerTop - Math.round(baseH / 2)) > 1 || Math.abs(prevCamera.pointerLeft - Math.round(baseW / 2)) > 1 || Math.abs(prevCamera.pointerTop - Math.round(baseH / 2)) > 1;
166
+ if (spinning && spinnerImg) drawSpinningPointer(ctx, spinnerImg, sX, sY, spinningElapsedMs);
167
+ if (!spinning && hasPtrData && cursorImg) ctx.drawImage(cursorImg, sX - 3, sY - 2, 22, 28);
168
+ }
169
+ function exportBrandedVideo(frameMap, onProgress) {
170
+ return _async_to_generator(function*() {
171
+ const { totalDurationInFrames: total, fps } = frameMap;
172
+ const imgSrcs = new Set();
173
+ for (const sf of frameMap.scriptFrames)if (sf.img) imgSrcs.add(sf.img);
174
+ const imgCache = new Map();
175
+ yield Promise.all([
176
+ ...imgSrcs
177
+ ].map((src)=>_async_to_generator(function*() {
178
+ try {
179
+ imgCache.set(src, (yield loadImage(src)));
180
+ } catch (e) {}
181
+ })()));
182
+ let cursorImg = null;
183
+ let spinnerImg = null;
184
+ try {
185
+ cursorImg = yield loadImage(index_js_namespaceObject.mousePointer);
186
+ } catch (e) {}
187
+ try {
188
+ spinnerImg = yield loadImage(index_js_namespaceObject.mouseLoading);
189
+ } catch (e) {}
190
+ const canvas = document.createElement('canvas');
191
+ canvas.width = W;
192
+ canvas.height = H;
193
+ const ctx = canvas.getContext('2d');
194
+ const stream = canvas.captureStream(fps);
195
+ const recorder = new MediaRecorder(stream, {
196
+ mimeType: 'video/webm'
197
+ });
198
+ const chunks = [];
199
+ recorder.ondataavailable = (e)=>{
200
+ if (e.data.size > 0) chunks.push(e.data);
201
+ };
202
+ return new Promise((resolve, reject)=>{
203
+ recorder.onerror = ()=>reject(new Error('MediaRecorder error'));
204
+ recorder.onstop = ()=>{
205
+ if (0 === chunks.length) return void reject(new Error('No video data'));
206
+ const blob = new Blob(chunks, {
207
+ type: 'video/webm'
208
+ });
209
+ const url = URL.createObjectURL(blob);
210
+ const a = document.createElement('a');
211
+ a.href = url;
212
+ a.download = 'midscene_replay.webm';
213
+ a.click();
214
+ stream.getTracks().forEach((track)=>track.stop());
215
+ setTimeout(()=>URL.revokeObjectURL(url), 1000);
216
+ resolve();
217
+ };
218
+ recorder.start();
219
+ const frameDuration = 1000 / fps;
220
+ const startTime = performance.now();
221
+ let lastFrame = -1;
222
+ const tick = ()=>{
223
+ const elapsed = performance.now() - startTime;
224
+ const targetFrame = Math.min(Math.floor(elapsed / frameDuration), total - 1);
225
+ if (targetFrame > lastFrame) {
226
+ lastFrame = targetFrame;
227
+ ctx.clearRect(0, 0, W, H);
228
+ drawSteps(ctx, targetFrame, frameMap, imgCache, cursorImg, spinnerImg);
229
+ null == onProgress || onProgress((targetFrame + 1) / total);
230
+ }
231
+ if (targetFrame < total - 1) requestAnimationFrame(tick);
232
+ else setTimeout(()=>recorder.stop(), 2 * frameDuration);
233
+ };
234
+ requestAnimationFrame(tick);
235
+ });
236
+ })();
237
+ }
238
+ exports.exportBrandedVideo = __webpack_exports__.exportBrandedVideo;
239
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
240
+ "exportBrandedVideo"
241
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
242
+ Object.defineProperty(exports, '__esModule', {
243
+ value: true
244
+ });
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ FPS: ()=>FPS,
28
+ calculateFrameMap: ()=>calculateFrameMap
29
+ });
30
+ const FPS = 30;
31
+ function calculateFrameMap(scripts) {
32
+ let baseImageWidth = 1920;
33
+ let baseImageHeight = 1080;
34
+ for (const s of scripts)if (('img' === s.type || 'insight' === s.type) && s.img) {
35
+ baseImageWidth = s.imageWidth || 1920;
36
+ baseImageHeight = s.imageHeight || 1080;
37
+ break;
38
+ }
39
+ const scriptFrames = [];
40
+ let currentFrame = 0;
41
+ for (const script of scripts){
42
+ const durationMs = script.duration;
43
+ switch(script.type){
44
+ case 'sleep':
45
+ {
46
+ const frames = Math.ceil(durationMs / 1000 * FPS);
47
+ scriptFrames.push({
48
+ type: 'sleep',
49
+ startFrame: currentFrame,
50
+ durationInFrames: frames,
51
+ title: script.title,
52
+ subTitle: script.subTitle,
53
+ taskId: script.taskId
54
+ });
55
+ currentFrame += frames;
56
+ break;
57
+ }
58
+ case 'img':
59
+ {
60
+ const frames = Math.max(Math.ceil(durationMs / 1000 * FPS), 1);
61
+ const camera = script.camera;
62
+ const iw = script.imageWidth || baseImageWidth;
63
+ const ih = script.imageHeight || baseImageHeight;
64
+ const sf = {
65
+ type: 'img',
66
+ startFrame: currentFrame,
67
+ durationInFrames: frames,
68
+ img: script.img,
69
+ imageWidth: iw,
70
+ imageHeight: ih,
71
+ title: script.title,
72
+ subTitle: script.subTitle,
73
+ taskId: script.taskId
74
+ };
75
+ if (camera) {
76
+ var _camera_pointerLeft, _camera_pointerTop;
77
+ sf.cameraTarget = {
78
+ left: camera.left,
79
+ top: camera.top,
80
+ width: camera.width,
81
+ pointerLeft: null != (_camera_pointerLeft = camera.pointerLeft) ? _camera_pointerLeft : Math.round(iw / 2),
82
+ pointerTop: null != (_camera_pointerTop = camera.pointerTop) ? _camera_pointerTop : Math.round(ih / 2)
83
+ };
84
+ }
85
+ scriptFrames.push(sf);
86
+ currentFrame += frames;
87
+ break;
88
+ }
89
+ case 'insight':
90
+ {
91
+ const insightPhaseFrames = Math.max(Math.ceil(durationMs / 1000 * FPS), 1);
92
+ const cameraDurationMs = script.insightCameraDuration || 0;
93
+ const cameraPhaseFrames = Math.ceil(cameraDurationMs / 1000 * FPS);
94
+ const totalFrames = insightPhaseFrames + cameraPhaseFrames;
95
+ const iw = script.imageWidth || baseImageWidth;
96
+ const ih = script.imageHeight || baseImageHeight;
97
+ const camera = script.camera;
98
+ const sf = {
99
+ type: 'insight',
100
+ startFrame: currentFrame,
101
+ durationInFrames: totalFrames,
102
+ img: script.img,
103
+ imageWidth: iw,
104
+ imageHeight: ih,
105
+ insightPhaseFrames,
106
+ cameraPhaseFrames,
107
+ highlightElement: script.highlightElement,
108
+ searchArea: script.searchArea,
109
+ title: script.title,
110
+ subTitle: script.subTitle,
111
+ taskId: script.taskId
112
+ };
113
+ if (camera) {
114
+ var _camera_pointerLeft1, _camera_pointerTop1;
115
+ sf.cameraTarget = {
116
+ left: camera.left,
117
+ top: camera.top,
118
+ width: camera.width,
119
+ pointerLeft: null != (_camera_pointerLeft1 = camera.pointerLeft) ? _camera_pointerLeft1 : Math.round(iw / 2),
120
+ pointerTop: null != (_camera_pointerTop1 = camera.pointerTop) ? _camera_pointerTop1 : Math.round(ih / 2)
121
+ };
122
+ }
123
+ scriptFrames.push(sf);
124
+ currentFrame += totalFrames;
125
+ break;
126
+ }
127
+ case 'clear-insight':
128
+ {
129
+ const frames = Math.max(Math.ceil(durationMs / 1000 * FPS), 1);
130
+ scriptFrames.push({
131
+ type: 'clear-insight',
132
+ startFrame: currentFrame,
133
+ durationInFrames: frames,
134
+ title: script.title,
135
+ subTitle: script.subTitle,
136
+ taskId: script.taskId
137
+ });
138
+ currentFrame += frames;
139
+ break;
140
+ }
141
+ case 'spinning-pointer':
142
+ {
143
+ const frames = Math.max(Math.ceil(durationMs / 1000 * FPS), 1);
144
+ scriptFrames.push({
145
+ type: 'spinning-pointer',
146
+ startFrame: currentFrame,
147
+ durationInFrames: frames,
148
+ title: script.title,
149
+ subTitle: script.subTitle,
150
+ taskId: script.taskId
151
+ });
152
+ currentFrame += frames;
153
+ break;
154
+ }
155
+ case 'pointer':
156
+ scriptFrames.push({
157
+ type: 'pointer',
158
+ startFrame: currentFrame,
159
+ durationInFrames: 0,
160
+ pointerImg: script.img,
161
+ title: script.title,
162
+ subTitle: script.subTitle,
163
+ taskId: script.taskId
164
+ });
165
+ break;
166
+ }
167
+ }
168
+ const stepsDurationInFrames = Math.max(currentFrame, 1);
169
+ return {
170
+ scriptFrames,
171
+ totalDurationInFrames: stepsDurationInFrames,
172
+ fps: FPS,
173
+ stepsDurationInFrames,
174
+ imageWidth: baseImageWidth,
175
+ imageHeight: baseImageHeight
176
+ };
177
+ }
178
+ exports.FPS = __webpack_exports__.FPS;
179
+ exports.calculateFrameMap = __webpack_exports__.calculateFrameMap;
180
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
181
+ "FPS",
182
+ "calculateFrameMap"
183
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
184
+ Object.defineProperty(exports, '__esModule', {
185
+ value: true
186
+ });
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ useFramePlayer: ()=>useFramePlayer
28
+ });
29
+ const external_react_namespaceObject = require("react");
30
+ function useFramePlayer(options) {
31
+ const { durationInFrames, fps, autoPlay = false, loop = false } = options;
32
+ const [currentFrame, setCurrentFrame] = (0, external_react_namespaceObject.useState)(0);
33
+ const [playing, setPlaying] = (0, external_react_namespaceObject.useState)(autoPlay);
34
+ const playingRef = (0, external_react_namespaceObject.useRef)(playing);
35
+ const frameRef = (0, external_react_namespaceObject.useRef)(currentFrame);
36
+ var _options_playbackRate;
37
+ const rateRef = (0, external_react_namespaceObject.useRef)(null != (_options_playbackRate = options.playbackRate) ? _options_playbackRate : 1);
38
+ const durationRef = (0, external_react_namespaceObject.useRef)(durationInFrames);
39
+ const fpsRef = (0, external_react_namespaceObject.useRef)(fps);
40
+ const loopRef = (0, external_react_namespaceObject.useRef)(loop);
41
+ playingRef.current = playing;
42
+ frameRef.current = currentFrame;
43
+ var _options_playbackRate1;
44
+ rateRef.current = null != (_options_playbackRate1 = options.playbackRate) ? _options_playbackRate1 : 1;
45
+ durationRef.current = durationInFrames;
46
+ fpsRef.current = fps;
47
+ loopRef.current = loop;
48
+ (0, external_react_namespaceObject.useEffect)(()=>{
49
+ if (!playing) return;
50
+ let rafId;
51
+ let lastTime = null;
52
+ let accumulated = 0;
53
+ const tick = (now)=>{
54
+ if (null !== lastTime) {
55
+ const delta = (now - lastTime) * rateRef.current;
56
+ accumulated += delta;
57
+ const frameDuration = 1000 / fpsRef.current;
58
+ while(accumulated >= frameDuration){
59
+ accumulated -= frameDuration;
60
+ const next = frameRef.current + 1;
61
+ if (next >= durationRef.current) if (loopRef.current) {
62
+ frameRef.current = 0;
63
+ setCurrentFrame(0);
64
+ } else {
65
+ frameRef.current = durationRef.current - 1;
66
+ setCurrentFrame(durationRef.current - 1);
67
+ setPlaying(false);
68
+ return;
69
+ }
70
+ else {
71
+ frameRef.current = next;
72
+ setCurrentFrame(next);
73
+ }
74
+ }
75
+ }
76
+ lastTime = now;
77
+ rafId = requestAnimationFrame(tick);
78
+ };
79
+ rafId = requestAnimationFrame(tick);
80
+ return ()=>cancelAnimationFrame(rafId);
81
+ }, [
82
+ playing
83
+ ]);
84
+ const play = (0, external_react_namespaceObject.useCallback)(()=>{
85
+ if (frameRef.current >= durationRef.current - 1) {
86
+ frameRef.current = 0;
87
+ setCurrentFrame(0);
88
+ }
89
+ setPlaying(true);
90
+ }, []);
91
+ const pause = (0, external_react_namespaceObject.useCallback)(()=>setPlaying(false), []);
92
+ const toggle = (0, external_react_namespaceObject.useCallback)(()=>{
93
+ if (playingRef.current) setPlaying(false);
94
+ else {
95
+ if (frameRef.current >= durationRef.current - 1) {
96
+ frameRef.current = 0;
97
+ setCurrentFrame(0);
98
+ }
99
+ setPlaying(true);
100
+ }
101
+ }, []);
102
+ const seekTo = (0, external_react_namespaceObject.useCallback)((frame)=>{
103
+ const clamped = Math.max(0, Math.min(frame, durationRef.current - 1));
104
+ frameRef.current = clamped;
105
+ setCurrentFrame(clamped);
106
+ }, []);
107
+ return {
108
+ currentFrame,
109
+ playing,
110
+ play,
111
+ pause,
112
+ toggle,
113
+ seekTo
114
+ };
115
+ }
116
+ exports.useFramePlayer = __webpack_exports__.useFramePlayer;
117
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
118
+ "useFramePlayer"
119
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
120
+ Object.defineProperty(exports, '__esModule', {
121
+ value: true
122
+ });
@@ -141,7 +141,20 @@ function UniversalPlayground({ playgroundSDK, storage, contextProvider, config:
141
141
  playgroundSDK
142
142
  ]);
143
143
  const { loading, setLoading, infoList, setInfoList, actionSpace, actionSpaceLoading, uiContextPreview, setUiContextPreview, showScrollToBottomButton, verticalMode, replayCounter, setReplayCounter, infoListRef, currentRunningIdRef, interruptedFlagRef, clearInfoList, handleScrollToBottom } = (0, usePlaygroundState_js_namespaceObject.usePlaygroundState)(playgroundSDK, effectiveStorage, contextProvider, branding.targetName);
144
- const { handleRun: executeAction, handleStop, canStop } = (0, usePlaygroundExecution_js_namespaceObject.usePlaygroundExecution)(playgroundSDK, effectiveStorage, actionSpace, loading, setLoading, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef);
144
+ const { handleRun: executeAction, handleStop, canStop } = (0, usePlaygroundExecution_js_namespaceObject.usePlaygroundExecution)({
145
+ playgroundSDK,
146
+ storage: effectiveStorage,
147
+ actionSpace,
148
+ loading,
149
+ setLoading,
150
+ setInfoList,
151
+ replayCounter,
152
+ setReplayCounter,
153
+ verticalMode,
154
+ currentRunningIdRef,
155
+ interruptedFlagRef,
156
+ deviceType: componentConfig.deviceType
157
+ });
145
158
  (0, external_react_namespaceObject.useEffect)(()=>{
146
159
  if ((null == playgroundSDK ? void 0 : playgroundSDK.overrideConfig) && config) playgroundSDK.overrideConfig(config).catch((error)=>{
147
160
  console.error('Failed to override SDK config:', error);
@@ -116,7 +116,7 @@ function buildProgressContent(task) {
116
116
  const description = (0, agent_namespaceObject.paramStr)(task);
117
117
  return description ? `${action} - ${description}` : action;
118
118
  }
119
- function wrapExecutionDumpForReplay(dump) {
119
+ function wrapExecutionDumpForReplay(dump, deviceType) {
120
120
  const modelBriefsSet = new Set();
121
121
  if ((null == dump ? void 0 : dump.tasks) && Array.isArray(dump.tasks)) dump.tasks.forEach((task)=>{
122
122
  if (task.usage) {
@@ -134,10 +134,12 @@ function wrapExecutionDumpForReplay(dump) {
134
134
  modelBriefs,
135
135
  executions: [
136
136
  dump
137
- ]
137
+ ],
138
+ deviceType
138
139
  };
139
140
  }
140
- function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, setLoading, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef) {
141
+ function usePlaygroundExecution(options) {
142
+ const { playgroundSDK, storage, actionSpace, loading, setLoading, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef, deviceType } = options;
141
143
  const { deepLocate, deepThink, screenshotIncluded, domIncluded } = (0, store_js_namespaceObject.useEnvConfig)();
142
144
  const handleRun = (0, external_react_namespaceObject.useCallback)((value)=>_async_to_generator(function*() {
143
145
  if (!playgroundSDK) return void console.warn('PlaygroundSDK is not available');
@@ -234,7 +236,7 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
234
236
  let counter = replayCounter;
235
237
  if (null == result ? void 0 : result.dump) {
236
238
  if (result.dump.tasks && Array.isArray(result.dump.tasks)) {
237
- const groupedDump = wrapExecutionDumpForReplay(result.dump);
239
+ const groupedDump = wrapExecutionDumpForReplay(result.dump, deviceType);
238
240
  const info = (0, replay_scripts_js_namespaceObject.allScriptsFromDump)(groupedDump);
239
241
  setReplayCounter((c)=>c + 1);
240
242
  replayInfo = info;
@@ -292,7 +294,8 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
292
294
  deepLocate,
293
295
  deepThink,
294
296
  screenshotIncluded,
295
- domIncluded
297
+ domIncluded,
298
+ deviceType
296
299
  ]);
297
300
  const handleStop = (0, external_react_namespaceObject.useCallback)(()=>_async_to_generator(function*() {
298
301
  const thisRunningId = currentRunningIdRef.current;
@@ -319,7 +322,7 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
319
322
  let replayInfo = null;
320
323
  let counter = replayCounter;
321
324
  if ((null == (_executionData_dump = executionData.dump) ? void 0 : _executionData_dump.tasks) && Array.isArray(executionData.dump.tasks)) {
322
- const groupedDump = wrapExecutionDumpForReplay(executionData.dump);
325
+ const groupedDump = wrapExecutionDumpForReplay(executionData.dump, deviceType);
323
326
  replayInfo = (0, replay_scripts_js_namespaceObject.allScriptsFromDump)(groupedDump);
324
327
  setReplayCounter((c)=>c + 1);
325
328
  counter = replayCounter + 1;
@@ -377,7 +380,8 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
377
380
  setLoading,
378
381
  setInfoList,
379
382
  verticalMode,
380
- replayCounter
383
+ replayCounter,
384
+ deviceType
381
385
  ]);
382
386
  const canStop = loading && !!currentRunningIdRef.current && !!playgroundSDK && !!playgroundSDK.cancelExecution;
383
387
  return {
package/dist/lib/index.js CHANGED
@@ -68,6 +68,7 @@ __webpack_require__.d(__webpack_exports__, {
68
68
  globalThemeConfig: ()=>color_js_namespaceObject.globalThemeConfig,
69
69
  ContextPreview: ()=>context_preview_index_js_namespaceObject.ContextPreview,
70
70
  createStorageProvider: ()=>storage_provider_js_namespaceObject.createStorageProvider,
71
+ extractDumpMetaInfo: ()=>replay_scripts_js_namespaceObject.extractDumpMetaInfo,
71
72
  useTheme: ()=>useTheme_js_namespaceObject.useTheme,
72
73
  UniversalPlayground: ()=>universal_playground_index_js_namespaceObject.UniversalPlayground,
73
74
  Player: ()=>player_index_js_namespaceObject.Player,
@@ -132,6 +133,7 @@ exports.allScriptsFromDump = __webpack_exports__.allScriptsFromDump;
132
133
  exports.colorForName = __webpack_exports__.colorForName;
133
134
  exports.createStorageProvider = __webpack_exports__.createStorageProvider;
134
135
  exports.detectBestStorageType = __webpack_exports__.detectBestStorageType;
136
+ exports.extractDumpMetaInfo = __webpack_exports__.extractDumpMetaInfo;
135
137
  exports.filterBase64Value = __webpack_exports__.filterBase64Value;
136
138
  exports.generateAnimationScripts = __webpack_exports__.generateAnimationScripts;
137
139
  exports.getPlaceholderForType = __webpack_exports__.getPlaceholderForType;
@@ -176,6 +178,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
176
178
  "colorForName",
177
179
  "createStorageProvider",
178
180
  "detectBestStorageType",
181
+ "extractDumpMetaInfo",
179
182
  "filterBase64Value",
180
183
  "generateAnimationScripts",
181
184
  "getPlaceholderForType",