@gemx-dev/heatmap-react 3.5.38 → 3.5.40

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 (128) hide show
  1. package/dist/esm/components/Layout/ContentVizByMode.d.ts +2 -0
  2. package/dist/esm/components/Layout/ContentVizByMode.d.ts.map +1 -0
  3. package/dist/esm/components/Layout/LeftSidebar.d.ts.map +1 -1
  4. package/dist/esm/components/VizDom/VizContainer.d.ts +7 -0
  5. package/dist/esm/components/VizDom/VizContainer.d.ts.map +1 -0
  6. package/dist/esm/components/VizDom/VizDomHeatmap.d.ts +2 -0
  7. package/dist/esm/components/VizDom/VizDomHeatmap.d.ts.map +1 -0
  8. package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -1
  9. package/dist/esm/components/VizDom/VizLoading.d.ts +2 -0
  10. package/dist/esm/components/VizDom/VizLoading.d.ts.map +1 -0
  11. package/dist/esm/components/VizDom/WrapperVisual.d.ts +11 -0
  12. package/dist/esm/components/VizDom/WrapperVisual.d.ts.map +1 -0
  13. package/dist/esm/components/VizDom/index.d.ts +4 -1
  14. package/dist/esm/components/VizDom/index.d.ts.map +1 -1
  15. package/dist/esm/components/VizLive/VizLiveHeatmap.d.ts +2 -0
  16. package/dist/esm/components/VizLive/VizLiveHeatmap.d.ts.map +1 -0
  17. package/dist/esm/components/VizLive/VizLiveRenderer.d.ts +2 -0
  18. package/dist/esm/components/VizLive/VizLiveRenderer.d.ts.map +1 -0
  19. package/dist/esm/components/VizLive/index.d.ts +2 -0
  20. package/dist/esm/components/VizLive/index.d.ts.map +1 -0
  21. package/dist/esm/components/index.d.ts +0 -1
  22. package/dist/esm/components/index.d.ts.map +1 -1
  23. package/dist/esm/helpers/iframe.d.ts +16 -2
  24. package/dist/esm/helpers/iframe.d.ts.map +1 -1
  25. package/dist/esm/helpers/viewport-fixer.d.ts.map +1 -1
  26. package/dist/esm/helpers/viewport-replacer.d.ts +3 -4
  27. package/dist/esm/helpers/viewport-replacer.d.ts.map +1 -1
  28. package/dist/esm/hooks/index.d.ts +1 -0
  29. package/dist/esm/hooks/index.d.ts.map +1 -1
  30. package/dist/esm/hooks/register/useRegisterConfig.d.ts.map +1 -1
  31. package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -4
  32. package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
  33. package/dist/esm/hooks/viz-live/index.d.ts +2 -0
  34. package/dist/esm/hooks/viz-live/index.d.ts.map +1 -0
  35. package/dist/esm/hooks/viz-live/useIframeMessage.d.ts +27 -0
  36. package/dist/esm/hooks/viz-live/useIframeMessage.d.ts.map +1 -0
  37. package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  38. package/dist/esm/hooks/viz-scale/index.d.ts +1 -0
  39. package/dist/esm/hooks/viz-scale/index.d.ts.map +1 -1
  40. package/dist/esm/hooks/viz-scale/useContentDimensions.d.ts.map +1 -1
  41. package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts +2 -1
  42. package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
  43. package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts +2 -1
  44. package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts.map +1 -1
  45. package/dist/esm/hooks/viz-scale/useWrapperRefHeight.d.ts +11 -0
  46. package/dist/esm/hooks/viz-scale/useWrapperRefHeight.d.ts.map +1 -0
  47. package/dist/esm/index.js +428 -201
  48. package/dist/esm/index.mjs +428 -201
  49. package/dist/esm/stores/config.d.ts +7 -0
  50. package/dist/esm/stores/config.d.ts.map +1 -1
  51. package/dist/esm/stores/data.d.ts +1 -4
  52. package/dist/esm/stores/data.d.ts.map +1 -1
  53. package/dist/esm/stores/mode-live.d.ts +11 -1
  54. package/dist/esm/stores/mode-live.d.ts.map +1 -1
  55. package/dist/esm/types/viewport-fixer.d.ts +0 -1
  56. package/dist/esm/types/viewport-fixer.d.ts.map +1 -1
  57. package/dist/umd/components/Layout/ContentVizByMode.d.ts +2 -0
  58. package/dist/umd/components/Layout/ContentVizByMode.d.ts.map +1 -0
  59. package/dist/umd/components/Layout/LeftSidebar.d.ts.map +1 -1
  60. package/dist/umd/components/VizDom/VizContainer.d.ts +7 -0
  61. package/dist/umd/components/VizDom/VizContainer.d.ts.map +1 -0
  62. package/dist/umd/components/VizDom/VizDomHeatmap.d.ts +2 -0
  63. package/dist/umd/components/VizDom/VizDomHeatmap.d.ts.map +1 -0
  64. package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -1
  65. package/dist/umd/components/VizDom/VizLoading.d.ts +2 -0
  66. package/dist/umd/components/VizDom/VizLoading.d.ts.map +1 -0
  67. package/dist/umd/components/VizDom/WrapperVisual.d.ts +11 -0
  68. package/dist/umd/components/VizDom/WrapperVisual.d.ts.map +1 -0
  69. package/dist/umd/components/VizDom/index.d.ts +4 -1
  70. package/dist/umd/components/VizDom/index.d.ts.map +1 -1
  71. package/dist/umd/components/VizLive/VizLiveHeatmap.d.ts +2 -0
  72. package/dist/umd/components/VizLive/VizLiveHeatmap.d.ts.map +1 -0
  73. package/dist/umd/components/VizLive/VizLiveRenderer.d.ts +2 -0
  74. package/dist/umd/components/VizLive/VizLiveRenderer.d.ts.map +1 -0
  75. package/dist/umd/components/VizLive/index.d.ts +2 -0
  76. package/dist/umd/components/VizLive/index.d.ts.map +1 -0
  77. package/dist/umd/components/index.d.ts +0 -1
  78. package/dist/umd/components/index.d.ts.map +1 -1
  79. package/dist/umd/helpers/iframe.d.ts +16 -2
  80. package/dist/umd/helpers/iframe.d.ts.map +1 -1
  81. package/dist/umd/helpers/viewport-fixer.d.ts.map +1 -1
  82. package/dist/umd/helpers/viewport-replacer.d.ts +3 -4
  83. package/dist/umd/helpers/viewport-replacer.d.ts.map +1 -1
  84. package/dist/umd/hooks/index.d.ts +1 -0
  85. package/dist/umd/hooks/index.d.ts.map +1 -1
  86. package/dist/umd/hooks/register/useRegisterConfig.d.ts.map +1 -1
  87. package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -4
  88. package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
  89. package/dist/umd/hooks/viz-live/index.d.ts +2 -0
  90. package/dist/umd/hooks/viz-live/index.d.ts.map +1 -0
  91. package/dist/umd/hooks/viz-live/useIframeMessage.d.ts +27 -0
  92. package/dist/umd/hooks/viz-live/useIframeMessage.d.ts.map +1 -0
  93. package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  94. package/dist/umd/hooks/viz-scale/index.d.ts +1 -0
  95. package/dist/umd/hooks/viz-scale/index.d.ts.map +1 -1
  96. package/dist/umd/hooks/viz-scale/useContentDimensions.d.ts.map +1 -1
  97. package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts +2 -1
  98. package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
  99. package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts +2 -1
  100. package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts.map +1 -1
  101. package/dist/umd/hooks/viz-scale/useWrapperRefHeight.d.ts +11 -0
  102. package/dist/umd/hooks/viz-scale/useWrapperRefHeight.d.ts.map +1 -0
  103. package/dist/umd/index.js +2 -2
  104. package/dist/umd/stores/config.d.ts +7 -0
  105. package/dist/umd/stores/config.d.ts.map +1 -1
  106. package/dist/umd/stores/data.d.ts +1 -4
  107. package/dist/umd/stores/data.d.ts.map +1 -1
  108. package/dist/umd/stores/mode-live.d.ts +11 -1
  109. package/dist/umd/stores/mode-live.d.ts.map +1 -1
  110. package/dist/umd/types/viewport-fixer.d.ts +0 -1
  111. package/dist/umd/types/viewport-fixer.d.ts.map +1 -1
  112. package/package.json +1 -1
  113. package/dist/esm/components/Test.d.ts +0 -121
  114. package/dist/esm/components/Test.d.ts.map +0 -1
  115. package/dist/esm/components/VizDom/VizDomContainer.d.ts +0 -2
  116. package/dist/esm/components/VizDom/VizDomContainer.d.ts.map +0 -1
  117. package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts +0 -150
  118. package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts.map +0 -1
  119. package/dist/esm/components/VizElement/temp/VizElementRank.d.ts +0 -74
  120. package/dist/esm/components/VizElement/temp/VizElementRank.d.ts.map +0 -1
  121. package/dist/umd/components/Test.d.ts +0 -121
  122. package/dist/umd/components/Test.d.ts.map +0 -1
  123. package/dist/umd/components/VizDom/VizDomContainer.d.ts +0 -2
  124. package/dist/umd/components/VizDom/VizDomContainer.d.ts.map +0 -1
  125. package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts +0 -150
  126. package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts.map +0 -1
  127. package/dist/umd/components/VizElement/temp/VizElementRank.d.ts +0 -74
  128. package/dist/umd/components/VizElement/temp/VizElementRank.d.ts.map +0 -1
package/dist/esm/index.js CHANGED
@@ -3,6 +3,7 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
  import { useNodesState, ReactFlow, Controls, Background } from '@xyflow/react';
4
4
  import { useEffect, useCallback, useState, useRef, useMemo, forwardRef, Fragment as Fragment$1 } from 'react';
5
5
  import { create } from 'zustand';
6
+ import { decode } from '@gemx-dev/clarity-decode';
6
7
  import { Visualizer } from '@gemx-dev/clarity-visualize';
7
8
  import { createPortal } from 'react-dom';
8
9
 
@@ -85,37 +86,36 @@ const useHeatmapControlStore = create()((set, get) => {
85
86
  };
86
87
  });
87
88
 
89
+ var IHeatmapType;
90
+ (function (IHeatmapType) {
91
+ IHeatmapType["Click"] = "click";
92
+ IHeatmapType["Scroll"] = "scroll";
93
+ })(IHeatmapType || (IHeatmapType = {}));
94
+
88
95
  const useHeatmapConfigStore = create()((set, get) => {
89
96
  return {
90
97
  mode: 'single',
98
+ width: 1440,
99
+ sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
100
+ heatmapType: IHeatmapType.Click,
91
101
  setMode: (mode) => set({ mode }),
92
102
  resetMode: () => set({ mode: 'single' }),
103
+ setWidth: (width) => set({ width }),
104
+ setSidebarWidth: (sidebarWidth) => set({ sidebarWidth }),
105
+ setHeatmapType: (heatmapType) => set({ heatmapType }),
93
106
  };
94
107
  });
95
108
 
96
- var IHeatmapType;
97
- (function (IHeatmapType) {
98
- IHeatmapType["Click"] = "click";
99
- IHeatmapType["Scroll"] = "scroll";
100
- })(IHeatmapType || (IHeatmapType = {}));
101
-
102
109
  const useHeatmapDataStore = create()((set, get) => {
103
110
  return {
104
111
  data: undefined,
105
112
  clickmap: undefined,
106
- config: {
107
- sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
108
- width: 1440,
109
- heatmapType: IHeatmapType.Click,
110
- },
111
113
  dataInfo: undefined,
112
114
  isRendering: true,
113
115
  setIsRendering: (isRendering) => set({ isRendering }),
114
116
  setDataInfo: (dataInfo) => set({ dataInfo }),
115
117
  setData: (data) => set({ data }),
116
118
  setClickmap: (clickmap) => set({ clickmap }),
117
- setConfig: (value) => set({ config: { ...get().config, ...value } }),
118
- setConfigBy: (key, value) => set({ config: { ...get().config, [key]: value } }),
119
119
  };
120
120
  });
121
121
 
@@ -147,22 +147,33 @@ const useHeatmapVizStore = create()((set, get) => {
147
147
  };
148
148
  });
149
149
 
150
+ const initialState = {
151
+ htmlContent: '',
152
+ wrapperHeight: 0,
153
+ iframeHeight: 0,
154
+ };
150
155
  const useHeatmapLiveStore = create()((set, get) => {
151
156
  return {
152
- htmlContent: '',
157
+ ...initialState,
158
+ reset: () => set(initialState),
153
159
  setHtmlContent: (htmlContent) => set({ htmlContent }),
160
+ setWrapperHeight: (wrapperHeight) => set({ wrapperHeight }),
161
+ setIframeHeight: (iframeHeight) => set({ iframeHeight }),
154
162
  };
155
163
  });
156
164
 
157
165
  const useRegisterConfig = () => {
158
- const config = useHeatmapDataStore((state) => state.config);
166
+ const mode = useHeatmapConfigStore((state) => state.mode);
167
+ const width = useHeatmapConfigStore((state) => state.width);
168
+ const sidebarWidth = useHeatmapConfigStore((state) => state.sidebarWidth);
169
+ const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
159
170
  const setIsRendering = useHeatmapDataStore((state) => state.setIsRendering);
160
171
  useEffect(() => {
161
172
  setIsRendering(true);
162
173
  setTimeout(() => {
163
174
  setIsRendering(false);
164
175
  }, 1000);
165
- }, [config]);
176
+ }, [mode, width, sidebarWidth, heatmapType]);
166
177
  };
167
178
 
168
179
  const useRegisterControl = (control) => {
@@ -424,6 +435,43 @@ const buildElementInfo = (hash, rect, heatmapInfo) => {
424
435
  };
425
436
  };
426
437
 
438
+ function findLastSizeOfDom(data) {
439
+ const firstDoc = data.find((item) => item.envelope.sequence === 1)?.doc;
440
+ const docSorted = firstDoc?.sort(sort);
441
+ const firstEvent = docSorted?.[0];
442
+ const docSize = {
443
+ width: firstEvent?.data.width,
444
+ height: firstEvent?.data.height,
445
+ };
446
+ const newData = JSON.parse(JSON.stringify(data));
447
+ const reversedData = newData.reverse();
448
+ const lastResizeEvent = reversedData.find((item) => !!item.resize);
449
+ const firstEventResize = lastResizeEvent?.resize?.[0];
450
+ const resize = {
451
+ width: firstEventResize?.data.width,
452
+ height: firstEventResize?.data.height,
453
+ };
454
+ return {
455
+ doc: docSize,
456
+ resize: resize,
457
+ size: {
458
+ width: resize.width ?? docSize.width,
459
+ height: resize.height ?? docSize.height,
460
+ },
461
+ };
462
+ }
463
+ function sort(a, b) {
464
+ return a.time - b.time;
465
+ }
466
+ function decodePayloads(payload) {
467
+ try {
468
+ return decode(payload);
469
+ }
470
+ catch (error) {
471
+ return null;
472
+ }
473
+ }
474
+
427
475
  function calculateRankPosition(rect, widthScale) {
428
476
  const top = rect.top <= 18 ? rect.top + 3 : rect.top - 18;
429
477
  const left = rect.left <= 18 ? rect.left + 3 : rect.left - 18;
@@ -462,7 +510,8 @@ const getScriptInjectCode = async () => {
462
510
  (function() {
463
511
  'use strict';
464
512
  ${classCode}
465
- new ${classInstantiateCode}()
513
+ const replacer = new ${classInstantiateCode}();
514
+ replacer.init();
466
515
  })();
467
516
  `;
468
517
  return scriptCode;
@@ -492,21 +541,21 @@ class ViewportUnitsFixer {
492
541
  async injectScript() {
493
542
  if (!this.iframe?.contentWindow || !this.iframe.contentDocument)
494
543
  return;
495
- const win = this.iframe.contentWindow;
496
544
  const doc = this.iframe.contentDocument;
497
- win.__viewportConfig = this.config;
498
- const script = doc.createElement('script');
499
- const codeInject = await getScriptInjectCode();
500
- script.textContent = codeInject;
501
- script.type = 'text/javascript';
502
- script.id = 'viewport-replacer';
503
- script.onload = () => console.log('[Parent] Viewport replacer module loaded');
504
- script.onerror = () => {
505
- this.config.onSuccess?.({
506
- height: 1000,
507
- });
508
- };
509
- doc.head.appendChild(script);
545
+ const win = this.iframe.contentWindow;
546
+ try {
547
+ win.__viewportConfig = this.config;
548
+ const script = doc.createElement('script');
549
+ console.log(`🚀 🐥 ~ ViewportUnitsFixer ~ injectScript ~ script:`, script);
550
+ const scriptCode = await getScriptInjectCode();
551
+ console.log(`🚀 🐥 ~ ViewportUnitsFixer ~ injectScript ~ scriptCode:`, scriptCode);
552
+ script.textContent = scriptCode;
553
+ doc.head.appendChild(script);
554
+ console.log(`🚀 🐥 ~ ViewportUnitsFixer ~ injectScript ~ doc:`, doc);
555
+ }
556
+ catch (error) {
557
+ console.error('[Parent] Failed to inject script', error);
558
+ }
510
559
  }
511
560
  handleMessage(event) {
512
561
  const data = event.data;
@@ -529,15 +578,11 @@ function initViewportFixer(config) {
529
578
  }
530
579
 
531
580
  class ViewportUnitsReplacer {
532
- config;
533
- regex = /([-.\d]+)(vh|svh|lvh|dvh|vw|svw|lvw|dvw)/gi;
534
- constructor() {
535
- if (!window.__viewportConfig) {
536
- throw new Error('[Iframe] Do not have viewport config');
537
- }
538
- this.config = window.__viewportConfig;
539
- console.log('[Iframe] ViewportUnitsReplacer started with config:', this.config);
540
- this.init();
581
+ regex() {
582
+ return /([-.\d]+)(vh|svh|lvh|dvh|vw|svw|lvw|dvw)/gi;
583
+ }
584
+ config() {
585
+ return window.__viewportConfig;
541
586
  }
542
587
  px(value) {
543
588
  return `${value.toFixed(2)}px`;
@@ -547,25 +592,25 @@ class ViewportUnitsReplacer {
547
592
  if (isNaN(num))
548
593
  return value;
549
594
  const map = {
550
- vh: this.config.targetHeight,
551
- svh: this.config.targetHeight,
552
- lvh: this.config.targetHeight,
553
- dvh: this.config.targetHeight,
554
- vw: this.config.targetWidth,
555
- svw: this.config.targetWidth,
556
- lvw: this.config.targetWidth,
557
- dvw: this.config.targetWidth,
595
+ vh: this.config().targetHeight,
596
+ svh: this.config().targetHeight,
597
+ lvh: this.config().targetHeight,
598
+ dvh: this.config().targetHeight,
599
+ vw: this.config().targetWidth,
600
+ svw: this.config().targetWidth,
601
+ lvw: this.config().targetWidth,
602
+ dvw: this.config().targetWidth,
558
603
  };
559
604
  return this.px((num / 100) * (map[unit.toLowerCase()] || 0));
560
605
  }
561
606
  replaceInText(cssText) {
562
- return cssText.replace(this.regex, (_, value, unit) => this.convert(value, unit));
607
+ return cssText.replace(this.regex(), (_, value, unit) => this.convert(value, unit));
563
608
  }
564
609
  processInlineStyles() {
565
610
  let count = 0;
566
611
  document.querySelectorAll('[style]').forEach((el) => {
567
612
  const style = el.getAttribute('style');
568
- if (style && this.regex.test(style)) {
613
+ if (style && this.regex().test(style)) {
569
614
  el.setAttribute('style', this.replaceInText(style));
570
615
  count++;
571
616
  }
@@ -577,7 +622,7 @@ class ViewportUnitsReplacer {
577
622
  let count = 0;
578
623
  document.querySelectorAll('style').forEach((tag) => {
579
624
  const css = tag.textContent || '';
580
- if (this.regex.test(css)) {
625
+ if (this.regex().test(css)) {
581
626
  tag.textContent = this.replaceInText(css);
582
627
  count++;
583
628
  }
@@ -592,7 +637,7 @@ class ViewportUnitsReplacer {
592
637
  for (let i = 0; i < style.length; i++) {
593
638
  const prop = style[i];
594
639
  const value = style.getPropertyValue(prop);
595
- if (value && this.regex.test(value)) {
640
+ if (value && this.regex().test(value)) {
596
641
  style.setProperty(prop, this.replaceInText(value), style.getPropertyPriority(prop));
597
642
  count++;
598
643
  }
@@ -640,7 +685,7 @@ class ViewportUnitsReplacer {
640
685
  try {
641
686
  const res = await fetch(link.href);
642
687
  let css = await res.text();
643
- if (this.regex.test(css)) {
688
+ if (this.regex().test(css)) {
644
689
  css = this.replaceInText(css);
645
690
  const style = document.createElement('style');
646
691
  style.textContent = css;
@@ -699,6 +744,8 @@ class ViewportUnitsReplacer {
699
744
  }
700
745
  }
701
746
  init() {
747
+ if (!window.__viewportConfig)
748
+ return;
702
749
  if (document.readyState === 'loading') {
703
750
  document.addEventListener('DOMContentLoaded', () => this.run());
704
751
  }
@@ -826,7 +873,7 @@ const useHeatmapEffects = ({ isVisible, isElementSidebarOpen, setShouldShowCallo
826
873
  const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
827
874
  const widthScale = useHeatmapVizStore((state) => state.scale);
828
875
  const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
829
- const heatmapWidth = useHeatmapDataStore((state) => state.config?.width);
876
+ const heatmapWidth = useHeatmapConfigStore((state) => state.width);
830
877
  return useCallback((element) => {
831
878
  const hash = element?.hash;
832
879
  if (!iframeRef.current?.contentDocument || !hash || !visualizer)
@@ -964,9 +1011,122 @@ const isValidElement = (element, heatmapInfo) => {
964
1011
  return !!heatmapInfo?.elementMapInfo?.[hash];
965
1012
  };
966
1013
 
1014
+ var MessageType;
1015
+ (function (MessageType) {
1016
+ MessageType["GX_DOM_TRACKING_PAYLOAD"] = "GX_DOM_TRACKING_PAYLOAD";
1017
+ MessageType["CLARITY_READY"] = "CLARITY_READY";
1018
+ })(MessageType || (MessageType = {}));
1019
+ function useIframeMessage(options = {}) {
1020
+ const { trustedOrigins = [], onMessage } = options;
1021
+ const [payloads, setPayloads] = useState([]);
1022
+ const [isReady, setIsReady] = useState(false);
1023
+ const iframeRef = useRef(null);
1024
+ const isValidOrigin = useCallback((origin) => {
1025
+ if (trustedOrigins.length === 0)
1026
+ return true;
1027
+ return trustedOrigins.includes(origin);
1028
+ }, [trustedOrigins]);
1029
+ const handleMessage = useCallback((event) => {
1030
+ if (!isValidOrigin(event.origin)) {
1031
+ console.warn('Message from untrusted origin:', event.origin);
1032
+ return;
1033
+ }
1034
+ if (!event.data || typeof event.data !== 'object' || !event.data.type) {
1035
+ return;
1036
+ }
1037
+ const message = event.data;
1038
+ if (!Object.values(MessageType).includes(message.type)) {
1039
+ return;
1040
+ }
1041
+ if (onMessage) {
1042
+ onMessage(message);
1043
+ }
1044
+ switch (message.type) {
1045
+ case MessageType.GX_DOM_TRACKING_PAYLOAD:
1046
+ if (message.payload) {
1047
+ const decodedPayloads = decodePayloads(message.payload);
1048
+ if (decodedPayloads) {
1049
+ setPayloads((prev) => [...prev, decodedPayloads]);
1050
+ }
1051
+ }
1052
+ break;
1053
+ case MessageType.CLARITY_READY:
1054
+ setIsReady(true);
1055
+ break;
1056
+ }
1057
+ }, [isValidOrigin, onMessage]);
1058
+ useEffect(() => {
1059
+ window.addEventListener('message', handleMessage);
1060
+ return () => {
1061
+ window.removeEventListener('message', handleMessage);
1062
+ };
1063
+ }, [handleMessage]);
1064
+ const clearPayloads = useCallback(() => {
1065
+ setPayloads([]);
1066
+ }, []);
1067
+ const reset = useCallback(() => {
1068
+ setPayloads([]);
1069
+ setIsReady(false);
1070
+ }, []);
1071
+ return {
1072
+ iframeRef,
1073
+ payloads,
1074
+ isReady,
1075
+ clearPayloads,
1076
+ reset,
1077
+ };
1078
+ }
1079
+ function useIframeRender() {
1080
+ const wrapperHeight = useHeatmapLiveStore((state) => state.wrapperHeight);
1081
+ const contentWidth = useHeatmapConfigStore((state) => state.width);
1082
+ const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
1083
+ const htmlContent = useHeatmapLiveStore((state) => state.htmlContent);
1084
+ const { iframeRef, payloads, isReady } = useIframeMessage();
1085
+ useEffect(() => {
1086
+ if (!htmlContent || !iframeRef.current)
1087
+ return;
1088
+ const iframe = iframeRef.current;
1089
+ const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document;
1090
+ if (iframeDoc) {
1091
+ iframeDoc.open();
1092
+ iframeDoc.writeln(htmlContent);
1093
+ iframeDoc.close();
1094
+ }
1095
+ }, [htmlContent]);
1096
+ useEffect(() => {
1097
+ if (!isReady)
1098
+ return;
1099
+ if (!iframeRef.current)
1100
+ return;
1101
+ const iframe = iframeRef.current;
1102
+ if (!iframe || !htmlContent)
1103
+ return;
1104
+ reset$1(iframe, { width: contentWidth, height: wrapperHeight }, (height) => {
1105
+ setIframeHeight(height);
1106
+ });
1107
+ }, [isReady, contentWidth, wrapperHeight]);
1108
+ return {
1109
+ iframeRef,
1110
+ payloads,
1111
+ isReady,
1112
+ };
1113
+ }
1114
+ function reset$1(iframe, payloads, onSuccess) {
1115
+ const viewportFixer = initViewportFixer({
1116
+ targetWidth: payloads.width,
1117
+ targetHeight: payloads.height,
1118
+ iframe: iframe,
1119
+ onSuccess: (data) => {
1120
+ onSuccess(data.height);
1121
+ iframe.height = `${data.height}px`;
1122
+ },
1123
+ });
1124
+ viewportFixer.recalculate();
1125
+ return iframe;
1126
+ }
1127
+
967
1128
  const useHeatmapRender = () => {
968
1129
  const data = useHeatmapDataStore((state) => state.data);
969
- const config = useHeatmapDataStore((state) => state.config);
970
1130
  const setVizRef = useHeatmapVizStore((state) => state.setVizRef);
971
1131
  const setIsRenderViz = useHeatmapVizStore((state) => state.setIsRenderViz);
972
1132
  const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
@@ -993,39 +1153,11 @@ const useHeatmapRender = () => {
993
1153
  return () => {
994
1154
  setVizRef(null);
995
1155
  };
996
- }, [config, data]);
1156
+ }, [data]);
997
1157
  return {
998
1158
  iframeRef,
999
1159
  };
1000
1160
  };
1001
- function sort(a, b) {
1002
- return a.time - b.time;
1003
- }
1004
- function findLastSizeOfDom(data) {
1005
- const firstDoc = data.find((item) => item.envelope.sequence === 1)?.doc;
1006
- const docSorted = firstDoc?.sort(sort);
1007
- const firstEvent = docSorted?.[0];
1008
- const docSize = {
1009
- width: firstEvent?.data.width,
1010
- height: firstEvent?.data.height,
1011
- };
1012
- const newData = JSON.parse(JSON.stringify(data));
1013
- const reversedData = newData.reverse();
1014
- const lastResizeEvent = reversedData.find((item) => !!item.resize);
1015
- const firstEventResize = lastResizeEvent?.resize?.[0];
1016
- const resize = {
1017
- width: firstEventResize?.data.width,
1018
- height: firstEventResize?.data.height,
1019
- };
1020
- return {
1021
- doc: docSize,
1022
- resize: resize,
1023
- size: {
1024
- width: resize.width ?? docSize.width,
1025
- height: resize.height ?? docSize.height,
1026
- },
1027
- };
1028
- }
1029
1161
  function reset(iframe, payloads, onSuccess) {
1030
1162
  const { size } = findLastSizeOfDom(payloads);
1031
1163
  const docWidth = size.width ?? 0;
@@ -1055,7 +1187,7 @@ function sortEvents(a, b) {
1055
1187
 
1056
1188
  const useReplayRender = () => {
1057
1189
  const data = useHeatmapDataStore((state) => state.data);
1058
- const setConfig = useHeatmapDataStore((state) => state.setConfig);
1190
+ const setWidth = useHeatmapConfigStore((state) => state.setWidth);
1059
1191
  const visualizerRef = useRef(null);
1060
1192
  const iframeRef = useRef(null);
1061
1193
  const eventsRef = useRef([]);
@@ -1073,14 +1205,14 @@ const useReplayRender = () => {
1073
1205
  visualizer.setup(iframe.contentWindow, {
1074
1206
  version: envelope.version,
1075
1207
  onresize: (width) => {
1076
- setConfig({ width });
1208
+ setWidth(width);
1077
1209
  },
1078
1210
  mobile,
1079
1211
  vNext: true,
1080
1212
  locale: 'en-us',
1081
1213
  });
1082
1214
  return visualizer;
1083
- }, [setConfig]);
1215
+ }, [setWidth]);
1084
1216
  // Animation loop for replay
1085
1217
  const replayLoop = useCallback(() => {
1086
1218
  if (!isPlayingRef.current)
@@ -1214,8 +1346,7 @@ const useContainerDimensions = (props) => {
1214
1346
  };
1215
1347
 
1216
1348
  const useContentDimensions = ({ iframeRef, }) => {
1217
- const config = useHeatmapDataStore((state) => state.config);
1218
- const contentWidth = config?.width ?? 0;
1349
+ const contentWidth = useHeatmapConfigStore((state) => state.width);
1219
1350
  useEffect(() => {
1220
1351
  if (!contentWidth)
1221
1352
  return;
@@ -1227,9 +1358,7 @@ const useContentDimensions = ({ iframeRef, }) => {
1227
1358
  };
1228
1359
 
1229
1360
  const useIframeHeight = (props) => {
1230
- const { iframeRef } = props;
1231
- const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
1232
- const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
1361
+ const { iframeRef, setIframeHeight } = props;
1233
1362
  const isRenderViz = useHeatmapVizStore((state) => state.isRenderViz);
1234
1363
  const resizeObserverRef = useRef(null);
1235
1364
  const mutationObserverRef = useRef(null);
@@ -1307,7 +1436,7 @@ const useIframeHeight = (props) => {
1307
1436
  iframe.removeEventListener('load', setupObservers);
1308
1437
  };
1309
1438
  }, [iframeRef, isRenderViz, updateIframeHeight]);
1310
- return { iframeHeight };
1439
+ return {};
1311
1440
  };
1312
1441
 
1313
1442
  const useScaleCalculation = (props) => {
@@ -1346,14 +1475,13 @@ const useScrollSync = ({ iframeRef }) => {
1346
1475
  };
1347
1476
 
1348
1477
  const useHeatmapScale = (props) => {
1349
- // const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
1350
- const { wrapperRef, iframeRef, visualRef } = props;
1478
+ const { wrapperRef, iframeRef, iframeHeight, setIframeHeight } = props;
1351
1479
  // 1. Observe container dimensions
1352
1480
  const { containerWidth, containerHeight } = useContainerDimensions({ wrapperRef });
1353
1481
  // 2. Get content dimensions from config
1354
1482
  const { contentWidth } = useContentDimensions({ iframeRef });
1355
1483
  // 3. Observe iframe height (now reacts to width changes)
1356
- const { iframeHeight } = useIframeHeight({ iframeRef });
1484
+ useIframeHeight({ iframeRef, setIframeHeight });
1357
1485
  // 4. Calculate scale
1358
1486
  const { scale } = useScaleCalculation({ containerWidth, contentWidth });
1359
1487
  // 5. Setup scroll sync
@@ -1361,13 +1489,81 @@ const useHeatmapScale = (props) => {
1361
1489
  return {
1362
1490
  containerWidth,
1363
1491
  containerHeight,
1364
- iframeHeight,
1365
1492
  scaledWidth: contentWidth * scale,
1366
1493
  scaledHeight: iframeHeight * scale,
1367
1494
  handleScroll,
1368
1495
  };
1369
1496
  };
1370
1497
 
1498
+ const useWrapperRefHeight = (props) => {
1499
+ const { isActive, wrapperRef, setWrapperHeight } = props;
1500
+ const isRenderViz = useHeatmapVizStore((state) => state.isRenderViz);
1501
+ const resizeObserverRef = useRef(null);
1502
+ const mutationObserverRef = useRef(null);
1503
+ const updateWrapperHeight = useCallback(() => {
1504
+ const wrapper = wrapperRef.current;
1505
+ if (!wrapper)
1506
+ return;
1507
+ try {
1508
+ const wrapperHeight = wrapper.offsetHeight;
1509
+ if (wrapperHeight > 0) {
1510
+ setWrapperHeight?.(wrapperHeight);
1511
+ }
1512
+ }
1513
+ catch (error) {
1514
+ console.warn('Cannot measure iframe content:', error);
1515
+ }
1516
+ }, [wrapperRef, setWrapperHeight]);
1517
+ useEffect(() => {
1518
+ const wrapper = wrapperRef.current;
1519
+ if (!wrapper || !isRenderViz)
1520
+ return;
1521
+ const setupObservers = () => {
1522
+ try {
1523
+ // Cleanup existing observers
1524
+ if (resizeObserverRef.current) {
1525
+ resizeObserverRef.current.disconnect();
1526
+ }
1527
+ if (mutationObserverRef.current) {
1528
+ mutationObserverRef.current.disconnect();
1529
+ }
1530
+ // ResizeObserver for size changes
1531
+ if (typeof window.ResizeObserver !== 'undefined') {
1532
+ resizeObserverRef.current = new ResizeObserver(updateWrapperHeight);
1533
+ resizeObserverRef.current.observe(wrapper);
1534
+ }
1535
+ // MutationObserver for DOM changes
1536
+ if (typeof window.MutationObserver !== 'undefined') {
1537
+ mutationObserverRef.current = new MutationObserver(updateWrapperHeight);
1538
+ mutationObserverRef.current.observe(wrapper, {
1539
+ childList: true,
1540
+ subtree: true,
1541
+ attributes: true,
1542
+ characterData: true,
1543
+ });
1544
+ }
1545
+ // Initial measurement
1546
+ updateWrapperHeight();
1547
+ }
1548
+ catch (error) {
1549
+ console.warn('Cannot access wrapper content:', error);
1550
+ }
1551
+ };
1552
+ if (isActive) {
1553
+ setupObservers();
1554
+ }
1555
+ return () => {
1556
+ if (resizeObserverRef.current) {
1557
+ resizeObserverRef.current.disconnect();
1558
+ }
1559
+ if (mutationObserverRef.current) {
1560
+ mutationObserverRef.current.disconnect();
1561
+ }
1562
+ };
1563
+ }, [wrapperRef, isRenderViz, updateWrapperHeight, isActive]);
1564
+ return {};
1565
+ };
1566
+
1371
1567
  const BoxStack = forwardRef(({ children, ...props }, ref) => {
1372
1568
  const id = props.id;
1373
1569
  const flexDirection = props.flexDirection;
@@ -1419,6 +1615,38 @@ const ContentTopBar = () => {
1419
1615
  }, children: TopBar && jsx(TopBar, {}) }));
1420
1616
  };
1421
1617
 
1618
+ const ContentMetricBar = () => {
1619
+ const controls = useHeatmapControlStore((state) => state.controls);
1620
+ return (jsx(BoxStack, { id: "gx-hm-content-metric-bar", flexDirection: "row", alignItems: "center", overflow: "auto", zIndex: 1, backgroundColor: "white", style: {
1621
+ borderBottom: `${HEATMAP_CONFIG.borderWidth}px solid ${HEATMAP_CONFIG.borderColor}`,
1622
+ }, children: controls.MetricBar ?? null }));
1623
+ };
1624
+
1625
+ const ContentToolbar = () => {
1626
+ const controls = useHeatmapControlStore((state) => state.controls);
1627
+ return (jsx("div", { id: "gx-hm-content-toolbar", style: {
1628
+ zIndex: 2,
1629
+ position: 'absolute',
1630
+ bottom: 0,
1631
+ left: '8px',
1632
+ right: '24px',
1633
+ padding: '8px',
1634
+ paddingBlock: '16px',
1635
+ }, children: controls.Toolbar ?? null }));
1636
+ };
1637
+
1638
+ const VizContainer = ({ children, setWrapperHeight }) => {
1639
+ const wrapperRef = useRef(null);
1640
+ useWrapperRefHeight({
1641
+ isActive: !!setWrapperHeight,
1642
+ wrapperRef,
1643
+ setWrapperHeight,
1644
+ });
1645
+ return (jsx(BoxStack, { ref: wrapperRef, id: "gx-hm-viz-container", flexDirection: "column", flex: "1 1 auto", overflow: "auto", zIndex: 1, children: jsx(BoxStack, { id: "gx-hm-content", flexDirection: "column", flex: "1 1 auto", overflow: "hidden", style: {
1646
+ minWidth: '394px',
1647
+ }, children: children }) }));
1648
+ };
1649
+
1422
1650
  const useClickmap = () => {
1423
1651
  const [isInitialized, setIsInitialized] = useState(false);
1424
1652
  const clickmap = useHeatmapDataStore((state) => state.clickmap);
@@ -1440,15 +1668,16 @@ const useScrollmap = () => {
1440
1668
  return {};
1441
1669
  };
1442
1670
 
1443
- const useHeatmapVizCanvas = ({ type }) => {
1671
+ const useHeatmapVizCanvas = () => {
1672
+ const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
1444
1673
  const heatmapRender = useMemo(() => {
1445
- switch (type) {
1674
+ switch (heatmapType) {
1446
1675
  case IHeatmapType.Click:
1447
1676
  return useClickmap;
1448
1677
  case IHeatmapType.Scroll:
1449
1678
  return useScrollmap;
1450
1679
  }
1451
- }, [type]);
1680
+ }, [heatmapType]);
1452
1681
  return heatmapRender?.();
1453
1682
  };
1454
1683
 
@@ -1612,7 +1841,7 @@ const HeatmapElements = (props) => {
1612
1841
 
1613
1842
  const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
1614
1843
  const heatmapInfo = useHeatmapDataStore((state) => state.dataInfo);
1615
- const contentWidth = useHeatmapDataStore((state) => state.config?.width ?? 0);
1844
+ const contentWidth = useHeatmapConfigStore((state) => state.width);
1616
1845
  const visualizer = {
1617
1846
  get: (hash) => {
1618
1847
  const doc = iframeRef.current?.contentDocument;
@@ -1640,57 +1869,59 @@ const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
1640
1869
  } }));
1641
1870
  };
1642
1871
 
1643
- const ReplayControls = () => {
1644
- const replayResult = useReplayRender();
1645
- return (jsxs("div", { style: {
1646
- position: 'absolute',
1647
- bottom: 20,
1648
- left: '50%',
1649
- transform: 'translateX(-50%)',
1872
+ const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHeight, onScroll, }) => {
1873
+ const contentWidth = useHeatmapConfigStore((state) => state.width);
1874
+ const widthScale = useHeatmapVizStore((state) => state.scale);
1875
+ const contentHeight = scaledHeight > 0
1876
+ ? `${scaledHeight + HEATMAP_CONFIG['heightToolbar'] + HEATMAP_CONFIG['padding'] * 2}px`
1877
+ : 'auto';
1878
+ return (jsx("div", { ref: visualRef, className: "gx-hm-visual", onScroll: onScroll, style: {
1879
+ overflow: 'hidden auto',
1650
1880
  display: 'flex',
1651
- gap: 10,
1652
- backgroundColor: 'rgba(0, 0, 0, 0.7)',
1653
- padding: '10px 20px',
1654
- borderRadius: 8,
1655
- }, children: [jsx("button", { onClick: replayResult.play, style: {
1656
- padding: '8px 16px',
1657
- backgroundColor: '#4CAF50',
1658
- color: 'white',
1659
- border: 'none',
1660
- borderRadius: 4,
1661
- cursor: 'pointer',
1662
- }, children: "Play" }), jsx("button", { onClick: replayResult.pause, style: {
1663
- padding: '8px 16px',
1664
- backgroundColor: '#f44336',
1665
- color: 'white',
1666
- border: 'none',
1667
- borderRadius: 4,
1668
- cursor: 'pointer',
1669
- }, children: "Pause" })] }));
1881
+ position: 'relative',
1882
+ justifyContent: 'center',
1883
+ flex: 1,
1884
+ // paddingBottom: HEATMAP_STYLE['viz']['paddingBottom'],
1885
+ background: '#fff',
1886
+ }, children: jsx("div", { className: "gx-hm-visual-unscaled", style: {
1887
+ width: '100%',
1888
+ display: 'flex',
1889
+ justifyContent: 'center',
1890
+ alignItems: 'flex-start',
1891
+ height: contentHeight,
1892
+ padding: HEATMAP_STYLE['wrapper']['padding'],
1893
+ paddingBottom: HEATMAP_STYLE['viz']['paddingBottom'],
1894
+ background: HEATMAP_STYLE['viz']['background'],
1895
+ }, children: jsx("div", { className: "gx-hm-wrapper", ref: wrapperRef, style: {
1896
+ width: contentWidth,
1897
+ height: iframeHeight,
1898
+ transform: `scale(${widthScale})`,
1899
+ transformOrigin: 'top center',
1900
+ paddingBlockEnd: '0',
1901
+ }, children: children }) }) }));
1670
1902
  };
1671
1903
 
1672
1904
  const VizDomRenderer = ({ mode = 'heatmap' }) => {
1673
- const config = useHeatmapDataStore((state) => state.config);
1905
+ const width = useHeatmapConfigStore((state) => state.width);
1906
+ const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
1674
1907
  const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
1675
- const widthScale = useHeatmapVizStore((state) => state.scale);
1676
1908
  const setSelectedElement = useHeatmapInteractionStore((state) => state.setSelectedElement);
1677
1909
  const wrapperRef = useRef(null);
1678
1910
  const visualRef = useRef(null);
1679
1911
  const { iframeRef } = useHeatmapVizRender(mode);
1680
- const { iframeHeight, scaledHeight, handleScroll } = useHeatmapScale({
1912
+ const { scaledHeight, handleScroll } = useHeatmapScale({
1681
1913
  wrapperRef,
1682
1914
  iframeRef,
1683
1915
  visualRef,
1916
+ iframeHeight,
1917
+ setIframeHeight,
1684
1918
  });
1685
- const contentWidth = config?.width ?? 0;
1686
- const contentHeight = scaledHeight > 0
1687
- ? `${scaledHeight + HEATMAP_CONFIG['heightToolbar'] + HEATMAP_CONFIG['padding'] * 2}px`
1688
- : 'auto';
1919
+ const contentWidth = width ?? 0;
1689
1920
  const onScroll = (e) => {
1690
1921
  const scrollTop = e.currentTarget.scrollTop;
1691
1922
  handleScroll(scrollTop);
1692
1923
  };
1693
- useHeatmapVizCanvas({ type: config?.heatmapType });
1924
+ useHeatmapVizCanvas();
1694
1925
  const cleanUp = () => {
1695
1926
  setIframeHeight(0);
1696
1927
  setSelectedElement(null);
@@ -1698,68 +1929,82 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
1698
1929
  useEffect(() => {
1699
1930
  return cleanUp;
1700
1931
  }, []);
1701
- return (jsxs("div", { ref: visualRef, className: "gx-hm-visual", onScroll: onScroll, style: {
1702
- overflow: 'hidden auto',
1703
- display: 'flex',
1704
- position: 'relative',
1705
- justifyContent: 'center',
1706
- flex: 1,
1707
- // paddingBottom: HEATMAP_STYLE['viz']['paddingBottom'],
1708
- background: '#fff',
1709
- }, children: [jsx("div", { className: "gx-hm-visual-unscaled", style: {
1710
- width: '100%',
1711
- display: 'flex',
1712
- justifyContent: 'center',
1713
- alignItems: 'flex-start',
1714
- height: contentHeight,
1715
- padding: HEATMAP_STYLE['wrapper']['padding'],
1716
- paddingBottom: HEATMAP_STYLE['viz']['paddingBottom'],
1717
- background: HEATMAP_STYLE['viz']['background'],
1718
- }, children: jsxs("div", { className: "gx-hm-wrapper", ref: wrapperRef, style: {
1719
- width: contentWidth,
1720
- height: iframeHeight,
1721
- transform: `scale(${widthScale})`,
1722
- transformOrigin: 'top center',
1723
- paddingBlockEnd: '0',
1724
- }, children: [jsx(VizElements, { iframeRef: iframeRef, visualRef: visualRef, wrapperRef: wrapperRef }), jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: contentWidth, height: iframeHeight, scrolling: "no" })] }) }), mode === 'replay' && jsx(ReplayControls, {})] }));
1725
- };
1726
-
1727
- const VizDomContainer = () => {
1932
+ return (jsxs(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, onScroll: onScroll, iframeHeight: iframeHeight, children: [jsx(VizElements, { iframeRef: iframeRef, visualRef: visualRef, wrapperRef: wrapperRef }), jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: contentWidth, height: iframeHeight, scrolling: "no" })] }));
1933
+ };
1934
+
1935
+ const VizLoading = () => {
1936
+ return (jsxs("div", { className: "gx-hm-loading", children: [jsx("div", { className: "gx-hm-loading--spinner" }), jsx("p", { className: "gx-hm-loading--text", children: "Loading visualization..." })] }));
1937
+ };
1938
+
1939
+ const VizDomHeatmap = () => {
1728
1940
  const controls = useHeatmapControlStore((state) => state.controls);
1729
1941
  const isRendering = useHeatmapDataStore((state) => state.isRendering);
1730
1942
  const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
1943
+ const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
1944
+ const setVizRef = useHeatmapVizStore((state) => state.setVizRef);
1945
+ useEffect(() => {
1946
+ return () => {
1947
+ setVizRef(undefined);
1948
+ setIframeHeight(0);
1949
+ };
1950
+ }, []);
1731
1951
  if (isRendering)
1732
1952
  return controls.VizLoading ?? null;
1733
- return (jsx(BoxStack, { id: "gx-hm-viz-container", flexDirection: "column", flex: "1 1 auto", overflow: "auto", zIndex: 1, children: jsxs(BoxStack, { id: "gx-hm-content", flexDirection: "column", flex: "1 1 auto", overflow: "hidden", style: {
1734
- minWidth: '394px',
1735
- }, children: [jsx(VizDomRenderer, {}), iframeHeight === 0 && (jsxs("div", { className: "gx-hm-loading", children: [jsx("div", { className: "gx-hm-loading--spinner" }), jsx("p", { className: "gx-hm-loading--text", children: "Loading visualization..." })] }))] }) }));
1953
+ return (jsxs(VizContainer, { children: [jsx(VizDomRenderer, {}), iframeHeight === 0 && jsx(VizLoading, {})] }));
1736
1954
  };
1737
1955
 
1738
- const ContentMetricBar = () => {
1739
- const controls = useHeatmapControlStore((state) => state.controls);
1740
- return (jsx(BoxStack, { id: "gx-hm-content-metric-bar", flexDirection: "row", alignItems: "center", overflow: "auto", zIndex: 1, backgroundColor: "white", style: {
1741
- borderBottom: `${HEATMAP_CONFIG.borderWidth}px solid ${HEATMAP_CONFIG.borderColor}`,
1742
- }, children: controls.MetricBar ?? null }));
1956
+ const VizLiveRenderer = () => {
1957
+ const contentWidth = useHeatmapConfigStore((state) => state.width);
1958
+ const iframeHeight = useHeatmapLiveStore((state) => state.iframeHeight);
1959
+ const setIframeHeight = useHeatmapLiveStore((state) => state.setIframeHeight);
1960
+ const visualRef = useRef(null);
1961
+ const wrapperRef = useRef(null);
1962
+ const { iframeRef } = useIframeRender();
1963
+ const { scaledHeight, handleScroll } = useHeatmapScale({
1964
+ wrapperRef,
1965
+ iframeRef,
1966
+ visualRef,
1967
+ iframeHeight,
1968
+ setIframeHeight,
1969
+ });
1970
+ const onScroll = (e) => {
1971
+ const scrollTop = e.currentTarget.scrollTop;
1972
+ handleScroll(scrollTop);
1973
+ };
1974
+ return (jsx(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, iframeHeight: iframeHeight, onScroll: onScroll, children: jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: contentWidth, height: iframeHeight, scrolling: "no", sandbox: "allow-scripts allow-same-origin" }) }));
1743
1975
  };
1744
1976
 
1745
- const ContentToolbar = () => {
1977
+ const VizLiveHeatmap = () => {
1746
1978
  const controls = useHeatmapControlStore((state) => state.controls);
1747
- return (jsx("div", { id: "gx-hm-content-toolbar", style: {
1748
- zIndex: 2,
1749
- position: 'absolute',
1750
- bottom: 0,
1751
- left: '8px',
1752
- right: '24px',
1753
- padding: '8px',
1754
- paddingBlock: '16px',
1755
- }, children: controls.Toolbar ?? null }));
1979
+ const isRendering = useHeatmapDataStore((state) => state.isRendering);
1980
+ const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
1981
+ const wrapperHeight = useHeatmapLiveStore((state) => state.wrapperHeight);
1982
+ const setWrapperHeight = useHeatmapLiveStore((state) => state.setWrapperHeight);
1983
+ const reset = useHeatmapLiveStore((state) => state.reset);
1984
+ useEffect(() => {
1985
+ return () => {
1986
+ reset();
1987
+ };
1988
+ }, [reset]);
1989
+ if (isRendering)
1990
+ return controls.VizLoading ?? null;
1991
+ return (jsxs(VizContainer, { setWrapperHeight: setWrapperHeight, children: [jsx(VizLiveRenderer, {}), (!iframeHeight || !wrapperHeight) && jsx(VizLoading, {})] }));
1992
+ };
1993
+
1994
+ const ContentVizByMode = () => {
1995
+ const mode = useHeatmapConfigStore((state) => state.mode);
1996
+ switch (mode) {
1997
+ case 'live':
1998
+ return jsx(VizLiveHeatmap, {});
1999
+ default:
2000
+ return jsx(VizDomHeatmap, {});
2001
+ }
1756
2002
  };
1757
2003
 
1758
2004
  const LeftSidebar = () => {
1759
2005
  const controls = useHeatmapControlStore((state) => state.controls);
1760
2006
  const isHideSidebar = useHeatmapInteractionStore((state) => state.state.hideSidebar);
1761
- const config = useHeatmapDataStore((state) => state.config);
1762
- const sidebarWidth = config?.sidebarWidth || DEFAULT_SIDEBAR_WIDTH;
2007
+ const sidebarWidth = useHeatmapConfigStore((state) => state.sidebarWidth);
1763
2008
  if (isHideSidebar) {
1764
2009
  return null;
1765
2010
  }
@@ -1782,7 +2027,7 @@ const LeftSidebar = () => {
1782
2027
  };
1783
2028
 
1784
2029
  const WrapperPreview = () => {
1785
- return (jsxs(BoxStack, { id: "gx-hm-container", flexDirection: "row", overflow: "hidden", flex: "1", position: "relative", children: [jsx(LeftSidebar, {}), jsxs(BoxStack, { flexDirection: "column", flex: "1", children: [jsx(ContentMetricBar, {}), jsx(VizDomContainer, {}), jsx(ContentToolbar, {})] })] }));
2030
+ return (jsxs(BoxStack, { id: "gx-hm-container", flexDirection: "row", overflow: "hidden", flex: "1", position: "relative", children: [jsx(LeftSidebar, {}), jsxs(BoxStack, { flexDirection: "column", flex: "1", children: [jsx(ContentMetricBar, {}), jsx(ContentVizByMode, {}), jsx(ContentToolbar, {})] })] }));
1786
2031
  };
1787
2032
 
1788
2033
  const WrapperLayout = () => {
@@ -1807,22 +2052,4 @@ const HeatmapLayout = ({ data, clickmap, controls, dataInfo, }) => {
1807
2052
  }
1808
2053
  };
1809
2054
 
1810
- var PanelContent;
1811
- (function (PanelContent) {
1812
- PanelContent["Sessions"] = "Sessions";
1813
- PanelContent["Timeline"] = "Timeline";
1814
- PanelContent["Area"] = "Area";
1815
- PanelContent["Click"] = "Click";
1816
- PanelContent["Scroll"] = "Scroll";
1817
- PanelContent["Attention"] = "Attention";
1818
- })(PanelContent || (PanelContent = {}));
1819
- var ErrorType;
1820
- (function (ErrorType) {
1821
- ErrorType["NoResults"] = "NoResults";
1822
- ErrorType["NoClicks"] = "NoClicks";
1823
- ErrorType["NoScroll"] = "NoScroll";
1824
- ErrorType["ServerError"] = "ServerError";
1825
- ErrorType["DataError"] = "DataError";
1826
- })(ErrorType || (ErrorType = {}));
1827
-
1828
2055
  export { GraphView, HeatmapLayout, IHeatmapType, useHeatmapConfigStore, useHeatmapDataStore, useHeatmapInteractionStore, useHeatmapLiveStore };