@midscene/visualizer 0.5.2-beta-20241009023204.0 → 0.5.2

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.
@@ -91,7 +91,7 @@ const DetailPanel = () => {
91
91
  const options = availableViewTypes.map((type) => {
92
92
  if (type === VIEW_TYPE_REPLAY) {
93
93
  return {
94
- label: "Task Replay",
94
+ label: "Replay",
95
95
  value: type,
96
96
  icon: /* @__PURE__ */ jsx(VideoCameraOutlined, {})
97
97
  };
@@ -1,51 +1,97 @@
1
1
  .player-container {
2
- width: 100%;
3
- height: 100%;
2
+ width: fit-content;
3
+ max-width: 100%;
4
+ max-height: 100%;
5
+ padding: 12px;
6
+ padding-bottom: 0;
7
+ background: #434443DD;
8
+ box-sizing: border-box;
9
+ border: 1px solid #979797;
10
+ border-radius: 6px;
11
+ line-height: 100%;
12
+ margin: 0 auto;
4
13
  display: flex;
5
14
  flex-direction: column;
6
- justify-content: center;
7
- position: relative;
8
- }
9
- .player-container .player-top-placeholder {
10
- width: 100%;
11
- height: 1px;
15
+ overflow: hidden;
12
16
  }
13
17
  .player-container .canvas-container {
14
- width: 100%;
15
- height: 90%;
16
- text-align: center;
17
- position: relative;
18
+ flex-grow: 1;
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ overflow: hidden;
18
23
  }
19
- .player-container canvas {
20
- border: 1px solid #06B1AB;
24
+ .player-container .canvas-container canvas {
21
25
  max-width: 100%;
22
26
  max-height: 100%;
23
27
  box-sizing: border-box;
24
- position: absolute;
25
- top: 50%;
26
- left: 50%;
27
- transform: translate(-50%, -50%);
28
+ display: block;
29
+ margin: 0 auto;
28
30
  }
29
- .player-container .player-controls {
31
+ .player-container .player-timeline {
32
+ width: 100%;
33
+ height: 4px;
34
+ background: #666;
35
+ position: relative;
36
+ margin-top: -2px;
37
+ }
38
+ .player-container .player-timeline .player-timeline-progress {
39
+ transition-timing-function: linear;
30
40
  position: absolute;
31
- bottom: 20px;
41
+ top: 0;
32
42
  left: 0;
33
- width: 100%;
34
- background: rgba(0, 0, 0, 0.7);
35
- border-radius: 8px;
36
- padding: 20px 15px;
43
+ height: 4px;
44
+ background: #06b1ab;
45
+ }
46
+ .player-container .player-controls {
47
+ margin-top: calc(12px * 1.2);
48
+ margin-bottom: calc(12px * 1.2);
49
+ max-width: 100%;
50
+ overflow: hidden;
37
51
  color: #FFF;
38
- font-size: 18px;
39
- line-height: 1.2;
40
- transition: 0.2s;
52
+ font-size: 16px;
41
53
  box-sizing: border-box;
54
+ display: flex;
55
+ flex-direction: row;
56
+ flex-shrink: 0;
57
+ }
58
+ .player-container .player-controls .status-icon {
59
+ transition: 0.2s;
60
+ width: 40px;
61
+ height: 40px;
62
+ margin-right: 12px;
63
+ background: #666;
64
+ border-radius: 6px;
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ flex-shrink: 0;
69
+ }
70
+ .player-container .player-controls .status-text {
71
+ flex-grow: 1;
72
+ overflow: hidden;
73
+ position: relative;
42
74
  }
43
75
  .player-container .player-controls .title {
44
76
  font-weight: bold;
77
+ height: 20px;
78
+ line-height: 20px;
79
+ overflow: hidden;
80
+ text-overflow: ellipsis;
81
+ white-space: nowrap;
82
+ position: absolute;
83
+ top: 0;
84
+ left: 0;
85
+ width: 100%;
45
86
  }
46
87
  .player-container .player-controls .subtitle {
47
- white-space: nowrap;
48
- text-overflow: ellipsis;
49
- overflow: hidden;
88
+ height: 20px;
89
+ line-height: 20px;
50
90
  width: 100%;
91
+ overflow: hidden;
92
+ text-overflow: ellipsis;
93
+ white-space: nowrap;
94
+ position: absolute;
95
+ top: 18px;
96
+ left: 0;
51
97
  }
@@ -40,6 +40,11 @@ import * as PIXI from "pixi.js";
40
40
  import { useEffect, useMemo, useRef, useState } from "react";
41
41
  import "./player.css";
42
42
  import { mouseLoading, mousePointer } from "../utils";
43
+ import {
44
+ LoadingOutlined,
45
+ PlayCircleOutlined
46
+ } from "@ant-design/icons";
47
+ import { ConfigProvider, Spin } from "antd";
43
48
  import { rectMarkForItem } from "./blackboard";
44
49
  import { useExecutionDump } from "./store";
45
50
  const canvasPaddingLeft = 0;
@@ -49,7 +54,7 @@ const cubicBezier = (t, p0, p1, p2, p3) => {
49
54
  return p0 * t2 * t2 * t2 + 3 * p1 * t * t2 * t2 + 3 * p2 * t * t * t2 + p3 * t * t * t;
50
55
  };
51
56
  const cubicImage = (t) => {
52
- return cubicBezier(t, 0, 0.69, 0.43, 1);
57
+ return linear(t);
53
58
  };
54
59
  const cubicInsightElement = (t) => {
55
60
  return cubicBezier(t, 0, 0.5, 0.5, 1);
@@ -63,6 +68,38 @@ const linear = (t) => {
63
68
  const sleep = (ms) => {
64
69
  return new Promise((resolve) => setTimeout(resolve, ms));
65
70
  };
71
+ const ERROR_FRAME_CANCEL = "frame cancel";
72
+ const frameKit = () => {
73
+ let cancelFlag = false;
74
+ return {
75
+ frame: (callback) => {
76
+ if (cancelFlag) {
77
+ throw new Error(ERROR_FRAME_CANCEL);
78
+ }
79
+ requestAnimationFrame(() => {
80
+ if (cancelFlag) {
81
+ throw new Error(ERROR_FRAME_CANCEL);
82
+ }
83
+ callback(performance.now());
84
+ });
85
+ },
86
+ timeout: (callback, ms) => {
87
+ if (cancelFlag) {
88
+ throw new Error(ERROR_FRAME_CANCEL);
89
+ }
90
+ setTimeout(() => {
91
+ if (cancelFlag) {
92
+ throw new Error(ERROR_FRAME_CANCEL);
93
+ }
94
+ callback();
95
+ }, ms);
96
+ },
97
+ cancel: () => {
98
+ console.log("set frame cancel");
99
+ cancelFlag = true;
100
+ }
101
+ };
102
+ };
66
103
  const singleElementFadeInDuration = 80;
67
104
  const LAYER_ORDER_IMG = 0;
68
105
  const LAYER_ORDER_INSIGHT = 1;
@@ -87,6 +124,7 @@ const Player = () => {
87
124
  const imgSpriteMap = useRef(/* @__PURE__ */ new Map());
88
125
  const pointerSprite = useRef(null);
89
126
  const spinningPointerSprite = useRef(null);
127
+ const [replayMark, setReplayMark] = useState(0);
90
128
  const windowContentContainer = useMemo(() => {
91
129
  const container = new PIXI.Container();
92
130
  return container;
@@ -105,6 +143,7 @@ const Player = () => {
105
143
  top: imageHeight / 2
106
144
  }
107
145
  };
146
+ const [animationProgress, setAnimationProgress] = useState(-1);
108
147
  const cancelFlag = useRef(false);
109
148
  useEffect(() => {
110
149
  cancelFlag.current = false;
@@ -112,14 +151,6 @@ const Player = () => {
112
151
  cancelFlag.current = true;
113
152
  };
114
153
  }, []);
115
- const frame = (callback) => {
116
- requestAnimationFrame(() => {
117
- if (cancelFlag.current) {
118
- return;
119
- }
120
- callback(performance.now());
121
- });
122
- };
123
154
  const cameraState = useRef(__spreadValues({}, basicCameraState));
124
155
  const preloadImage = (img) => __async(void 0, null, function* () {
125
156
  if (imgSpriteMap.current.has(img))
@@ -151,7 +182,7 @@ const Player = () => {
151
182
  sprite.zIndex = LAYER_ORDER_IMG;
152
183
  windowContentContainer.addChild(sprite);
153
184
  });
154
- const spinningPointer = () => __async(void 0, null, function* () {
185
+ const spinningPointer = (frame) => {
155
186
  var _a2, _b;
156
187
  if (!spinningPointerSprite.current) {
157
188
  spinningPointerSprite.current = PIXI.Sprite.from(mouseLoading);
@@ -186,7 +217,7 @@ const Player = () => {
186
217
  isCancelled = true;
187
218
  };
188
219
  return stopFn;
189
- });
220
+ };
190
221
  const updatePointer = (img, x, y) => __async(void 0, null, function* () {
191
222
  var _a2, _b;
192
223
  if (!imgSpriteMap.current.has(img)) {
@@ -239,7 +270,7 @@ const Player = () => {
239
270
  pointer.scale.set(1 / newScale);
240
271
  }
241
272
  };
242
- const cameraAnimation = (targetState, duration) => __async(void 0, null, function* () {
273
+ const cameraAnimation = (targetState, duration, frame) => __async(void 0, null, function* () {
243
274
  const currentState = __spreadValues({}, cameraState.current);
244
275
  const startLeft = currentState.left;
245
276
  const startTop = currentState.top;
@@ -292,7 +323,7 @@ const Player = () => {
292
323
  frame(animate);
293
324
  });
294
325
  });
295
- const fadeInGraphics = (graphics, duration, targetAlpha = 1) => {
326
+ const fadeInGraphics = (graphics, duration, frame, targetAlpha = 1) => {
296
327
  return new Promise((resolve) => {
297
328
  const startTime = performance.now();
298
329
  const animate = (currentTime) => {
@@ -308,13 +339,14 @@ const Player = () => {
308
339
  frame(animate);
309
340
  });
310
341
  };
311
- const fadeOutItem = (graphics, duration) => __async(void 0, null, function* () {
312
- return fadeInGraphics(graphics, duration, 0);
342
+ const fadeOutItem = (graphics, duration, frame) => __async(void 0, null, function* () {
343
+ return fadeInGraphics(graphics, duration, frame, 0);
313
344
  });
314
- const insightElementsAnimation = (elements, highlightElements, duration) => __async(void 0, null, function* () {
345
+ const insightElementsAnimation = (elements, highlightElements, duration, frame) => __async(void 0, null, function* () {
315
346
  insightMarkContainer.removeChildren();
316
347
  const elementsToAdd = [...elements];
317
348
  const totalLength = elementsToAdd.length;
349
+ let childrenCount = 0;
318
350
  yield new Promise((resolve) => {
319
351
  const startTime = performance.now();
320
352
  const animate = (currentTime) => {
@@ -323,7 +355,7 @@ const Player = () => {
323
355
  Math.min(elapsedTime / duration, 1)
324
356
  );
325
357
  const elementsToAddNow = Math.floor(progress * totalLength);
326
- while (insightMarkContainer.children.length < elementsToAddNow) {
358
+ while (childrenCount < elementsToAddNow) {
327
359
  const randomIndex = Math.floor(Math.random() * elementsToAdd.length);
328
360
  const element = elementsToAdd.splice(randomIndex, 1)[0];
329
361
  if (element) {
@@ -334,7 +366,12 @@ const Player = () => {
334
366
  );
335
367
  insightMarkGraphic.alpha = 0;
336
368
  insightMarkContainer.addChild(insightMarkGraphic);
337
- fadeInGraphics(insightMarkGraphic, singleElementFadeInDuration);
369
+ childrenCount++;
370
+ fadeInGraphics(
371
+ insightMarkGraphic,
372
+ singleElementFadeInDuration,
373
+ frame
374
+ );
338
375
  }
339
376
  }
340
377
  if (elapsedTime < duration) {
@@ -368,30 +405,57 @@ const Player = () => {
368
405
  frame(animate);
369
406
  });
370
407
  });
371
- useEffect(() => {
408
+ const init = () => __async(void 0, null, function* () {
409
+ if (!divContainerRef.current || !scripts)
410
+ return;
411
+ yield app.init({
412
+ width: canvasWidth,
413
+ height: canvasHeight,
414
+ background: 16053492
415
+ });
416
+ divContainerRef.current.appendChild(app.canvas);
417
+ windowContentContainer.x = 0;
418
+ windowContentContainer.y = 0;
419
+ app.stage.addChild(windowContentContainer);
420
+ insightMarkContainer.x = 0;
421
+ insightMarkContainer.y = 0;
422
+ windowContentContainer.addChild(insightMarkContainer);
423
+ });
424
+ const play = () => {
372
425
  let cancelFn;
373
426
  Promise.resolve(
374
427
  (() => __async(void 0, null, function* () {
375
- if (!divContainerRef.current || !scripts || !app)
376
- return;
377
- yield app.init({
378
- width: canvasWidth,
379
- height: canvasHeight,
380
- background: 16053492
381
- });
382
- divContainerRef.current.appendChild(app.canvas);
428
+ if (!app) {
429
+ throw new Error("app is not initialized");
430
+ }
431
+ if (!scripts) {
432
+ throw new Error("scripts is required");
433
+ }
434
+ const { frame, cancel, timeout } = frameKit();
435
+ cancelFn = cancel;
383
436
  const allImages = scripts.filter((item) => !!item.img).map((item) => item.img);
384
437
  yield Promise.all([...allImages, mouseLoading].map(preloadImage));
385
- windowContentContainer.x = 0;
386
- windowContentContainer.y = 0;
387
- app.stage.addChild(windowContentContainer);
388
- insightMarkContainer.x = 0;
389
- insightMarkContainer.y = 0;
390
- windowContentContainer.addChild(insightMarkContainer);
438
+ insightMarkContainer.removeChildren();
391
439
  yield updatePointer(mousePointer, imageWidth / 2, imageHeight / 2);
392
440
  yield repaintImage();
393
- yield updateCamera(cameraState.current);
394
- for (const item of scripts) {
441
+ yield updateCamera(__spreadValues({}, basicCameraState));
442
+ const totalDuration = scripts.reduce((acc, item) => {
443
+ return acc + item.duration + (item.insightCameraDuration || 0);
444
+ }, 0);
445
+ const progressUpdateInterval = 300;
446
+ const startTime = performance.now();
447
+ setAnimationProgress(0);
448
+ const updateProgress = () => {
449
+ const progress = Math.min(
450
+ (performance.now() - startTime) / totalDuration,
451
+ 1
452
+ );
453
+ setAnimationProgress(progress);
454
+ return timeout(updateProgress, progressUpdateInterval);
455
+ };
456
+ frame(updateProgress);
457
+ for (const index in scripts) {
458
+ const item = scripts[index];
395
459
  setTitleText(item.title || "");
396
460
  setSubTitleText(item.subTitle || "");
397
461
  if (item.type === "sleep") {
@@ -407,13 +471,21 @@ const Player = () => {
407
471
  yield insightElementsAnimation(
408
472
  elements,
409
473
  highlightElements,
410
- item.duration
474
+ item.duration,
475
+ frame
411
476
  );
412
477
  if (item.camera) {
413
- yield cameraAnimation(item.camera, item.duration);
478
+ if (!item.insightCameraDuration) {
479
+ throw new Error("insightCameraDuration is required");
480
+ }
481
+ yield cameraAnimation(
482
+ item.camera,
483
+ item.insightCameraDuration,
484
+ frame
485
+ );
414
486
  }
415
487
  } else if (item.type === "clear-insight") {
416
- yield fadeOutItem(insightMarkContainer, item.duration);
488
+ yield fadeOutItem(insightMarkContainer, item.duration, frame);
417
489
  insightMarkContainer.removeChildren();
418
490
  insightMarkContainer.alpha = 1;
419
491
  } else if (item.type === "img") {
@@ -422,7 +494,7 @@ const Player = () => {
422
494
  yield repaintImage();
423
495
  }
424
496
  if (item.camera) {
425
- yield cameraAnimation(item.camera, item.duration);
497
+ yield cameraAnimation(item.camera, item.duration, frame);
426
498
  } else {
427
499
  yield sleep(item.duration);
428
500
  }
@@ -432,29 +504,98 @@ const Player = () => {
432
504
  }
433
505
  yield updatePointer(item.img);
434
506
  } else if (item.type === "spinning-pointer") {
435
- const cancelFn2 = yield spinningPointer();
507
+ const stop = spinningPointer(frame);
436
508
  yield sleep(item.duration);
437
- cancelFn2();
509
+ stop();
438
510
  }
439
511
  }
512
+ }))().catch((e) => {
513
+ console.error("player error", e);
514
+ })
515
+ );
516
+ return () => {
517
+ cancelFn == null ? void 0 : cancelFn();
518
+ };
519
+ };
520
+ useEffect(() => {
521
+ Promise.resolve(
522
+ (() => __async(void 0, null, function* () {
523
+ yield init();
524
+ setReplayMark(Date.now());
440
525
  }))()
441
526
  );
442
527
  return () => {
443
528
  try {
444
- cancelFn == null ? void 0 : cancelFn();
445
529
  app.destroy(true, { children: true, texture: true });
446
530
  } catch (e) {
447
531
  console.warn("destroy failed", e);
448
532
  }
449
533
  };
450
534
  }, []);
451
- const showControl = !!titleText;
535
+ useEffect(() => {
536
+ if (replayMark) {
537
+ return play();
538
+ }
539
+ }, [replayMark]);
540
+ const progressString = Math.round(animationProgress * 100);
541
+ const transitionStyle = animationProgress === 0 ? "none" : "0.3s";
542
+ const [mouseOverStatusIcon, setMouseOverStatusIcon] = useState(false);
543
+ let statusIconElement;
544
+ const statusStyle = {};
545
+ let statusOnClick = () => {
546
+ };
547
+ if (animationProgress < 1) {
548
+ statusIconElement = /* @__PURE__ */ jsx(Spin, { indicator: /* @__PURE__ */ jsx(LoadingOutlined, { spin: true }), size: "default" });
549
+ } else if (mouseOverStatusIcon) {
550
+ statusIconElement = /* @__PURE__ */ jsx(Spin, { indicator: /* @__PURE__ */ jsx(PlayCircleOutlined, {}), size: "default" });
551
+ statusStyle.cursor = "pointer";
552
+ statusStyle.background = "#888";
553
+ statusOnClick = () => setReplayMark(Date.now());
554
+ } else {
555
+ statusIconElement = // <Spin indicator={<CheckCircleOutlined />} size="default" />
556
+ /* @__PURE__ */ jsx(Spin, { indicator: /* @__PURE__ */ jsx(PlayCircleOutlined, {}), size: "default" });
557
+ }
452
558
  return /* @__PURE__ */ jsxs("div", { className: "player-container", children: [
453
- /* @__PURE__ */ jsx("div", { className: "player-top-placeholder", children: " " }),
454
559
  /* @__PURE__ */ jsx("div", { className: "canvas-container", ref: divContainerRef }),
455
- /* @__PURE__ */ jsxs("div", { className: "player-controls", style: { opacity: showControl ? 1 : 0 }, children: [
456
- /* @__PURE__ */ jsx("div", { className: "title", children: titleText }),
457
- /* @__PURE__ */ jsx("div", { className: "subtitle", children: subTitleText })
560
+ /* @__PURE__ */ jsx("div", { className: "player-timeline", children: /* @__PURE__ */ jsx(
561
+ "div",
562
+ {
563
+ className: "player-timeline-progress",
564
+ style: {
565
+ width: `${progressString}%`,
566
+ transition: transitionStyle
567
+ }
568
+ }
569
+ ) }),
570
+ /* @__PURE__ */ jsxs("div", { className: "player-controls", children: [
571
+ /* @__PURE__ */ jsx(
572
+ "div",
573
+ {
574
+ className: "status-icon",
575
+ onMouseEnter: () => setMouseOverStatusIcon(true),
576
+ onMouseLeave: () => setMouseOverStatusIcon(false),
577
+ style: statusStyle,
578
+ onClick: statusOnClick,
579
+ children: /* @__PURE__ */ jsx(
580
+ ConfigProvider,
581
+ {
582
+ theme: {
583
+ components: {
584
+ Spin: {
585
+ dotSize: 24,
586
+ colorPrimary: "rgb(6,177,171)"
587
+ }
588
+ }
589
+ },
590
+ children: statusIconElement
591
+ }
592
+ )
593
+ }
594
+ ),
595
+ /* @__PURE__ */ jsxs("div", { className: "status-text", children: [
596
+ /* @__PURE__ */ jsx("div", { className: "title", children: titleText }),
597
+ /* @__PURE__ */ jsx("div", { className: "subtitle", children: subTitleText })
598
+ ] })
458
599
  ] })
459
600
  ] });
460
601
  };
@@ -33,7 +33,7 @@ const cameraStateForRect = (rect, imageWidth, imageHeight) => {
33
33
  } else {
34
34
  rectWidthOnPage = rect.height / imageHeight * imageWidth;
35
35
  }
36
- const cameraPaddingRatio = rectWidthOnPage < 50 ? 0.3 : 0.2;
36
+ const cameraPaddingRatio = rectWidthOnPage > 400 ? 0.1 : rectWidthOnPage > 50 ? 0.2 : 0.3;
37
37
  const cameraWidth = Math.min(
38
38
  imageWidth,
39
39
  rectWidthOnPage + imageWidth * cameraPaddingRatio * 2
@@ -103,6 +103,7 @@ const generateAnimationScripts = (execution, imageWidth, imageHeight) => {
103
103
  let currentCameraState = fullPageCameraState;
104
104
  let insightOnTop = false;
105
105
  const taskCount = execution.tasks.length;
106
+ let initSubTitle = "";
106
107
  execution.tasks.forEach((task, index) => {
107
108
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
108
109
  if (task.type === "Planning") {
@@ -111,10 +112,12 @@ const generateAnimationScripts = (execution, imageWidth, imageHeight) => {
111
112
  scripts.push({
112
113
  type: "img",
113
114
  img: (_b = (_a = planningTask.recorder) == null ? void 0 : _a[0]) == null ? void 0 : _b.screenshot,
115
+ camera: fullPageCameraState,
114
116
  duration: stillDuration,
115
117
  title: typeStr(task),
116
118
  subTitle: paramStr(task)
117
119
  });
120
+ initSubTitle = paramStr(task);
118
121
  }
119
122
  } else if (task.type === "Insight") {
120
123
  const insightTask = task;
@@ -141,6 +144,7 @@ const generateAnimationScripts = (execution, imageWidth, imageHeight) => {
141
144
  insightDump,
142
145
  camera: currentCameraState === fullPageCameraState || !insightCameraState ? void 0 : mergeTwoCameraState(currentCameraState, insightCameraState),
143
146
  duration: insightContentLength > 20 ? locateDuration : locateDuration * 0.5,
147
+ insightCameraDuration: locateDuration,
144
148
  title,
145
149
  subTitle
146
150
  });
@@ -201,14 +205,12 @@ const generateAnimationScripts = (execution, imageWidth, imageHeight) => {
201
205
  }
202
206
  });
203
207
  scripts.push({
208
+ title: "Done",
209
+ subTitle: initSubTitle,
204
210
  type: "img",
205
211
  duration: stillDuration * 0.5,
206
212
  camera: fullPageCameraState
207
213
  });
208
- scripts.push({
209
- type: "sleep",
210
- duration: stillDuration
211
- });
212
214
  return scripts;
213
215
  };
214
216
  export {
@@ -18,7 +18,7 @@ var __spreadValues = (a, b) => {
18
18
  };
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
20
  import * as Z from "zustand";
21
- import { generateAnimationScripts } from "./player-scripts";
21
+ import { generateAnimationScripts } from "./replay-scripts";
22
22
  const { create } = Z;
23
23
  const useBlackboardPreference = create((set) => ({
24
24
  bgVisible: true,
package/dist/es/index.css CHANGED
@@ -125,7 +125,7 @@ footer.mt-8 {
125
125
  text-align: center;
126
126
  margin-top: 10px;
127
127
  }
128
- .main-right .main-canvas-container {
128
+ .main-right .main-content-container {
129
129
  flex-grow: 1;
130
130
  height: 100%;
131
131
  background: #ffffff;
package/dist/es/index.js CHANGED
@@ -148,7 +148,7 @@ function Visualizer(props) {
148
148
  autoSaveId: "page-detail-layout-v2",
149
149
  direction: "horizontal",
150
150
  children: [
151
- /* @__PURE__ */ jsx(Panel, { defaultSize: 75, maxSize: 95, children: /* @__PURE__ */ jsx("div", { className: "main-canvas-container", children: /* @__PURE__ */ jsx(DetailPanel, {}) }) }),
151
+ /* @__PURE__ */ jsx(Panel, { defaultSize: 75, maxSize: 95, children: /* @__PURE__ */ jsx("div", { className: "main-content-container", children: /* @__PURE__ */ jsx(DetailPanel, {}) }) }),
152
152
  /* @__PURE__ */ jsx(PanelResizeHandle, {}),
153
153
  /* @__PURE__ */ jsx(Panel, { maxSize: 95, children: /* @__PURE__ */ jsx("div", { className: "main-side", children: /* @__PURE__ */ jsx(DetailSide, {}) }) })
154
154
  ]