@gemx-dev/heatmap-react 3.5.37 → 3.5.39

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 (142) hide show
  1. package/dist/esm/components/Layout/ContentTopBar.d.ts.map +1 -1
  2. package/dist/esm/components/Layout/ContentVizByMode.d.ts +2 -0
  3. package/dist/esm/components/Layout/ContentVizByMode.d.ts.map +1 -0
  4. package/dist/esm/components/Layout/LeftSidebar.d.ts.map +1 -1
  5. package/dist/esm/components/VizDom/VizContainer.d.ts +7 -0
  6. package/dist/esm/components/VizDom/VizContainer.d.ts.map +1 -0
  7. package/dist/esm/components/VizDom/VizDomHeatmap.d.ts +2 -0
  8. package/dist/esm/components/VizDom/VizDomHeatmap.d.ts.map +1 -0
  9. package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -1
  10. package/dist/esm/components/VizDom/VizLoading.d.ts +2 -0
  11. package/dist/esm/components/VizDom/VizLoading.d.ts.map +1 -0
  12. package/dist/esm/components/VizDom/WrapperVisual.d.ts +11 -0
  13. package/dist/esm/components/VizDom/WrapperVisual.d.ts.map +1 -0
  14. package/dist/esm/components/VizDom/index.d.ts +4 -1
  15. package/dist/esm/components/VizDom/index.d.ts.map +1 -1
  16. package/dist/esm/components/VizLive/VizLiveHeatmap.d.ts +2 -0
  17. package/dist/esm/components/VizLive/VizLiveHeatmap.d.ts.map +1 -0
  18. package/dist/esm/components/VizLive/VizLiveRenderer.d.ts +2 -0
  19. package/dist/esm/components/VizLive/VizLiveRenderer.d.ts.map +1 -0
  20. package/dist/esm/components/VizLive/index.d.ts +2 -0
  21. package/dist/esm/components/VizLive/index.d.ts.map +1 -0
  22. package/dist/esm/components/index.d.ts +0 -1
  23. package/dist/esm/components/index.d.ts.map +1 -1
  24. package/dist/esm/helpers/iframe.d.ts +16 -2
  25. package/dist/esm/helpers/iframe.d.ts.map +1 -1
  26. package/dist/esm/helpers/viewport-fixer.d.ts.map +1 -1
  27. package/dist/esm/helpers/viewport-replacer.d.ts +5 -5
  28. package/dist/esm/helpers/viewport-replacer.d.ts.map +1 -1
  29. package/dist/esm/hooks/index.d.ts +1 -0
  30. package/dist/esm/hooks/index.d.ts.map +1 -1
  31. package/dist/esm/hooks/register/useRegisterConfig.d.ts.map +1 -1
  32. package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -4
  33. package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
  34. package/dist/esm/hooks/viz-live/index.d.ts +2 -0
  35. package/dist/esm/hooks/viz-live/index.d.ts.map +1 -0
  36. package/dist/esm/hooks/viz-live/useIframeMessage.d.ts +27 -0
  37. package/dist/esm/hooks/viz-live/useIframeMessage.d.ts.map +1 -0
  38. package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  39. package/dist/esm/hooks/viz-scale/index.d.ts +1 -0
  40. package/dist/esm/hooks/viz-scale/index.d.ts.map +1 -1
  41. package/dist/esm/hooks/viz-scale/useContentDimensions.d.ts.map +1 -1
  42. package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts +2 -1
  43. package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
  44. package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts +2 -1
  45. package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts.map +1 -1
  46. package/dist/esm/hooks/viz-scale/useWrapperRefHeight.d.ts +11 -0
  47. package/dist/esm/hooks/viz-scale/useWrapperRefHeight.d.ts.map +1 -0
  48. package/dist/esm/index.d.ts +1 -1
  49. package/dist/esm/index.d.ts.map +1 -1
  50. package/dist/esm/index.js +451 -195
  51. package/dist/esm/index.mjs +451 -195
  52. package/dist/esm/stores/config.d.ts +14 -0
  53. package/dist/esm/stores/config.d.ts.map +1 -0
  54. package/dist/esm/stores/data.d.ts +1 -4
  55. package/dist/esm/stores/data.d.ts.map +1 -1
  56. package/dist/esm/stores/index.d.ts +2 -0
  57. package/dist/esm/stores/index.d.ts.map +1 -1
  58. package/dist/esm/stores/mode-live.d.ts +16 -0
  59. package/dist/esm/stores/mode-live.d.ts.map +1 -0
  60. package/dist/esm/types/control.d.ts +1 -1
  61. package/dist/esm/types/control.d.ts.map +1 -1
  62. package/dist/esm/types/viewport-fixer.d.ts +4 -2
  63. package/dist/esm/types/viewport-fixer.d.ts.map +1 -1
  64. package/dist/umd/components/Layout/ContentTopBar.d.ts.map +1 -1
  65. package/dist/umd/components/Layout/ContentVizByMode.d.ts +2 -0
  66. package/dist/umd/components/Layout/ContentVizByMode.d.ts.map +1 -0
  67. package/dist/umd/components/Layout/LeftSidebar.d.ts.map +1 -1
  68. package/dist/umd/components/VizDom/VizContainer.d.ts +7 -0
  69. package/dist/umd/components/VizDom/VizContainer.d.ts.map +1 -0
  70. package/dist/umd/components/VizDom/VizDomHeatmap.d.ts +2 -0
  71. package/dist/umd/components/VizDom/VizDomHeatmap.d.ts.map +1 -0
  72. package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -1
  73. package/dist/umd/components/VizDom/VizLoading.d.ts +2 -0
  74. package/dist/umd/components/VizDom/VizLoading.d.ts.map +1 -0
  75. package/dist/umd/components/VizDom/WrapperVisual.d.ts +11 -0
  76. package/dist/umd/components/VizDom/WrapperVisual.d.ts.map +1 -0
  77. package/dist/umd/components/VizDom/index.d.ts +4 -1
  78. package/dist/umd/components/VizDom/index.d.ts.map +1 -1
  79. package/dist/umd/components/VizLive/VizLiveHeatmap.d.ts +2 -0
  80. package/dist/umd/components/VizLive/VizLiveHeatmap.d.ts.map +1 -0
  81. package/dist/umd/components/VizLive/VizLiveRenderer.d.ts +2 -0
  82. package/dist/umd/components/VizLive/VizLiveRenderer.d.ts.map +1 -0
  83. package/dist/umd/components/VizLive/index.d.ts +2 -0
  84. package/dist/umd/components/VizLive/index.d.ts.map +1 -0
  85. package/dist/umd/components/index.d.ts +0 -1
  86. package/dist/umd/components/index.d.ts.map +1 -1
  87. package/dist/umd/helpers/iframe.d.ts +16 -2
  88. package/dist/umd/helpers/iframe.d.ts.map +1 -1
  89. package/dist/umd/helpers/viewport-fixer.d.ts.map +1 -1
  90. package/dist/umd/helpers/viewport-replacer.d.ts +5 -5
  91. package/dist/umd/helpers/viewport-replacer.d.ts.map +1 -1
  92. package/dist/umd/hooks/index.d.ts +1 -0
  93. package/dist/umd/hooks/index.d.ts.map +1 -1
  94. package/dist/umd/hooks/register/useRegisterConfig.d.ts.map +1 -1
  95. package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -4
  96. package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
  97. package/dist/umd/hooks/viz-live/index.d.ts +2 -0
  98. package/dist/umd/hooks/viz-live/index.d.ts.map +1 -0
  99. package/dist/umd/hooks/viz-live/useIframeMessage.d.ts +27 -0
  100. package/dist/umd/hooks/viz-live/useIframeMessage.d.ts.map +1 -0
  101. package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  102. package/dist/umd/hooks/viz-scale/index.d.ts +1 -0
  103. package/dist/umd/hooks/viz-scale/index.d.ts.map +1 -1
  104. package/dist/umd/hooks/viz-scale/useContentDimensions.d.ts.map +1 -1
  105. package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts +2 -1
  106. package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
  107. package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts +2 -1
  108. package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts.map +1 -1
  109. package/dist/umd/hooks/viz-scale/useWrapperRefHeight.d.ts +11 -0
  110. package/dist/umd/hooks/viz-scale/useWrapperRefHeight.d.ts.map +1 -0
  111. package/dist/umd/index.d.ts +1 -1
  112. package/dist/umd/index.d.ts.map +1 -1
  113. package/dist/umd/index.js +2 -2
  114. package/dist/umd/stores/config.d.ts +14 -0
  115. package/dist/umd/stores/config.d.ts.map +1 -0
  116. package/dist/umd/stores/data.d.ts +1 -4
  117. package/dist/umd/stores/data.d.ts.map +1 -1
  118. package/dist/umd/stores/index.d.ts +2 -0
  119. package/dist/umd/stores/index.d.ts.map +1 -1
  120. package/dist/umd/stores/mode-live.d.ts +16 -0
  121. package/dist/umd/stores/mode-live.d.ts.map +1 -0
  122. package/dist/umd/types/control.d.ts +1 -1
  123. package/dist/umd/types/control.d.ts.map +1 -1
  124. package/dist/umd/types/viewport-fixer.d.ts +4 -2
  125. package/dist/umd/types/viewport-fixer.d.ts.map +1 -1
  126. package/package.json +1 -1
  127. package/dist/esm/components/Test.d.ts +0 -121
  128. package/dist/esm/components/Test.d.ts.map +0 -1
  129. package/dist/esm/components/VizDom/VizDomContainer.d.ts +0 -2
  130. package/dist/esm/components/VizDom/VizDomContainer.d.ts.map +0 -1
  131. package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts +0 -150
  132. package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts.map +0 -1
  133. package/dist/esm/components/VizElement/temp/VizElementRank.d.ts +0 -74
  134. package/dist/esm/components/VizElement/temp/VizElementRank.d.ts.map +0 -1
  135. package/dist/umd/components/Test.d.ts +0 -121
  136. package/dist/umd/components/Test.d.ts.map +0 -1
  137. package/dist/umd/components/VizDom/VizDomContainer.d.ts +0 -2
  138. package/dist/umd/components/VizDom/VizDomContainer.d.ts.map +0 -1
  139. package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts +0 -150
  140. package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts.map +0 -1
  141. package/dist/umd/components/VizElement/temp/VizElementRank.d.ts +0 -74
  142. 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
 
@@ -91,23 +92,30 @@ var IHeatmapType;
91
92
  IHeatmapType["Scroll"] = "scroll";
92
93
  })(IHeatmapType || (IHeatmapType = {}));
93
94
 
95
+ const useHeatmapConfigStore = create()((set, get) => {
96
+ return {
97
+ mode: 'single',
98
+ width: 1440,
99
+ sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
100
+ heatmapType: IHeatmapType.Click,
101
+ setMode: (mode) => set({ mode }),
102
+ resetMode: () => set({ mode: 'single' }),
103
+ setWidth: (width) => set({ width }),
104
+ setSidebarWidth: (sidebarWidth) => set({ sidebarWidth }),
105
+ setHeatmapType: (heatmapType) => set({ heatmapType }),
106
+ };
107
+ });
108
+
94
109
  const useHeatmapDataStore = create()((set, get) => {
95
110
  return {
96
111
  data: undefined,
97
112
  clickmap: undefined,
98
- config: {
99
- sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
100
- width: 1440,
101
- heatmapType: IHeatmapType.Click,
102
- },
103
113
  dataInfo: undefined,
104
114
  isRendering: true,
105
115
  setIsRendering: (isRendering) => set({ isRendering }),
106
116
  setDataInfo: (dataInfo) => set({ dataInfo }),
107
117
  setData: (data) => set({ data }),
108
118
  setClickmap: (clickmap) => set({ clickmap }),
109
- setConfig: (value) => set({ config: { ...get().config, ...value } }),
110
- setConfigBy: (key, value) => set({ config: { ...get().config, [key]: value } }),
111
119
  };
112
120
  });
113
121
 
@@ -139,15 +147,33 @@ const useHeatmapVizStore = create()((set, get) => {
139
147
  };
140
148
  });
141
149
 
150
+ const initialState = {
151
+ htmlContent: '',
152
+ wrapperHeight: 0,
153
+ iframeHeight: 0,
154
+ };
155
+ const useHeatmapLiveStore = create()((set, get) => {
156
+ return {
157
+ ...initialState,
158
+ reset: () => set(initialState),
159
+ setHtmlContent: (htmlContent) => set({ htmlContent }),
160
+ setWrapperHeight: (wrapperHeight) => set({ wrapperHeight }),
161
+ setIframeHeight: (iframeHeight) => set({ iframeHeight }),
162
+ };
163
+ });
164
+
142
165
  const useRegisterConfig = () => {
143
- 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);
144
170
  const setIsRendering = useHeatmapDataStore((state) => state.setIsRendering);
145
171
  useEffect(() => {
146
172
  setIsRendering(true);
147
173
  setTimeout(() => {
148
174
  setIsRendering(false);
149
175
  }, 1000);
150
- }, [config]);
176
+ }, [mode, width, sidebarWidth, heatmapType]);
151
177
  };
152
178
 
153
179
  const useRegisterControl = (control) => {
@@ -409,6 +435,43 @@ const buildElementInfo = (hash, rect, heatmapInfo) => {
409
435
  };
410
436
  };
411
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
+
412
475
  function calculateRankPosition(rect, widthScale) {
413
476
  const top = rect.top <= 18 ? rect.top + 3 : rect.top - 18;
414
477
  const left = rect.left <= 18 ? rect.left + 3 : rect.left - 18;
@@ -438,6 +501,21 @@ function isElementInViewport(elementRect, visualRef, scale) {
438
501
  return elementBottom > viewportTop && elementTop < viewportBottom;
439
502
  }
440
503
 
504
+ const getScriptInjectCode = async () => {
505
+ const moduleResult = (await Promise.resolve().then(function () { return viewportReplacer; }));
506
+ const ActualClass = moduleResult.default;
507
+ const classCode = ActualClass.toString();
508
+ const classInstantiateCode = ActualClass.name;
509
+ const scriptCode = `
510
+ (function() {
511
+ 'use strict';
512
+ ${classCode}
513
+ const replacer = new ${classInstantiateCode}();
514
+ replacer.init();
515
+ })();
516
+ `;
517
+ return scriptCode;
518
+ };
441
519
  class ViewportUnitsFixer {
442
520
  iframe = null;
443
521
  config;
@@ -463,22 +541,21 @@ class ViewportUnitsFixer {
463
541
  async injectScript() {
464
542
  if (!this.iframe?.contentWindow || !this.iframe.contentDocument)
465
543
  return;
466
- const win = this.iframe.contentWindow;
467
544
  const doc = this.iframe.contentDocument;
468
- win.__viewportConfig = this.config;
469
- const script = doc.createElement('script');
470
- script.textContent = `
471
- (function() {
472
- 'use strict';
473
- ${(await Promise.resolve().then(function () { return viewportReplacer; })).default}
474
- new ViewportUnitsReplacer()
475
- })();
476
- `;
477
- script.type = 'text/javascript';
478
- script.id = 'viewport-replacer';
479
- script.onload = () => console.log('[Parent] Viewport replacer module loaded');
480
- script.onerror = () => console.error('[Parent] Không load được replacer script');
481
- 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
+ }
482
559
  }
483
560
  handleMessage(event) {
484
561
  const data = event.data;
@@ -501,15 +578,11 @@ function initViewportFixer(config) {
501
578
  }
502
579
 
503
580
  class ViewportUnitsReplacer {
504
- config;
505
- regex = /([-.\d]+)(vh|svh|lvh|dvh|vw|svw|lvw|dvw)/gi;
506
- constructor() {
507
- if (!window.__viewportConfig) {
508
- throw new Error('[Iframe] Do not have viewport config');
509
- }
510
- this.config = window.__viewportConfig;
511
- console.log('[Iframe] ViewportUnitsReplacer started with config:', this.config);
512
- this.init();
581
+ regex() {
582
+ return /([-.\d]+)(vh|svh|lvh|dvh|vw|svw|lvw|dvw)/gi;
583
+ }
584
+ config() {
585
+ return window.__viewportConfig;
513
586
  }
514
587
  px(value) {
515
588
  return `${value.toFixed(2)}px`;
@@ -519,25 +592,25 @@ class ViewportUnitsReplacer {
519
592
  if (isNaN(num))
520
593
  return value;
521
594
  const map = {
522
- vh: this.config.targetHeight,
523
- svh: this.config.targetHeight,
524
- lvh: this.config.targetHeight,
525
- dvh: this.config.targetHeight,
526
- vw: this.config.targetWidth,
527
- svw: this.config.targetWidth,
528
- lvw: this.config.targetWidth,
529
- 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,
530
603
  };
531
604
  return this.px((num / 100) * (map[unit.toLowerCase()] || 0));
532
605
  }
533
606
  replaceInText(cssText) {
534
- return cssText.replace(this.regex, (_, value, unit) => this.convert(value, unit));
607
+ return cssText.replace(this.regex(), (_, value, unit) => this.convert(value, unit));
535
608
  }
536
609
  processInlineStyles() {
537
610
  let count = 0;
538
611
  document.querySelectorAll('[style]').forEach((el) => {
539
612
  const style = el.getAttribute('style');
540
- if (style && this.regex.test(style)) {
613
+ if (style && this.regex().test(style)) {
541
614
  el.setAttribute('style', this.replaceInText(style));
542
615
  count++;
543
616
  }
@@ -549,7 +622,7 @@ class ViewportUnitsReplacer {
549
622
  let count = 0;
550
623
  document.querySelectorAll('style').forEach((tag) => {
551
624
  const css = tag.textContent || '';
552
- if (this.regex.test(css)) {
625
+ if (this.regex().test(css)) {
553
626
  tag.textContent = this.replaceInText(css);
554
627
  count++;
555
628
  }
@@ -564,7 +637,7 @@ class ViewportUnitsReplacer {
564
637
  for (let i = 0; i < style.length; i++) {
565
638
  const prop = style[i];
566
639
  const value = style.getPropertyValue(prop);
567
- if (value && this.regex.test(value)) {
640
+ if (value && this.regex().test(value)) {
568
641
  style.setProperty(prop, this.replaceInText(value), style.getPropertyPriority(prop));
569
642
  count++;
570
643
  }
@@ -612,7 +685,7 @@ class ViewportUnitsReplacer {
612
685
  try {
613
686
  const res = await fetch(link.href);
614
687
  let css = await res.text();
615
- if (this.regex.test(css)) {
688
+ if (this.regex().test(css)) {
616
689
  css = this.replaceInText(css);
617
690
  const style = document.createElement('style');
618
691
  style.textContent = css;
@@ -671,6 +744,8 @@ class ViewportUnitsReplacer {
671
744
  }
672
745
  }
673
746
  init() {
747
+ if (!window.__viewportConfig)
748
+ return;
674
749
  if (document.readyState === 'loading') {
675
750
  document.addEventListener('DOMContentLoaded', () => this.run());
676
751
  }
@@ -798,7 +873,7 @@ const useHeatmapEffects = ({ isVisible, isElementSidebarOpen, setShouldShowCallo
798
873
  const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
799
874
  const widthScale = useHeatmapVizStore((state) => state.scale);
800
875
  const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
801
- const heatmapWidth = useHeatmapDataStore((state) => state.config?.width);
876
+ const heatmapWidth = useHeatmapConfigStore((state) => state.width);
802
877
  return useCallback((element) => {
803
878
  const hash = element?.hash;
804
879
  if (!iframeRef.current?.contentDocument || !hash || !visualizer)
@@ -936,9 +1011,122 @@ const isValidElement = (element, heatmapInfo) => {
936
1011
  return !!heatmapInfo?.elementMapInfo?.[hash];
937
1012
  };
938
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
+
939
1128
  const useHeatmapRender = () => {
940
1129
  const data = useHeatmapDataStore((state) => state.data);
941
- const config = useHeatmapDataStore((state) => state.config);
942
1130
  const setVizRef = useHeatmapVizStore((state) => state.setVizRef);
943
1131
  const setIsRenderViz = useHeatmapVizStore((state) => state.setIsRenderViz);
944
1132
  const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
@@ -965,39 +1153,11 @@ const useHeatmapRender = () => {
965
1153
  return () => {
966
1154
  setVizRef(null);
967
1155
  };
968
- }, [config, data]);
1156
+ }, [data]);
969
1157
  return {
970
1158
  iframeRef,
971
1159
  };
972
1160
  };
973
- function sort(a, b) {
974
- return a.time - b.time;
975
- }
976
- function findLastSizeOfDom(data) {
977
- const firstDoc = data.find((item) => item.envelope.sequence === 1)?.doc;
978
- const docSorted = firstDoc?.sort(sort);
979
- const firstEvent = docSorted?.[0];
980
- const docSize = {
981
- width: firstEvent?.data.width,
982
- height: firstEvent?.data.height,
983
- };
984
- const newData = JSON.parse(JSON.stringify(data));
985
- const reversedData = newData.reverse();
986
- const lastResizeEvent = reversedData.find((item) => !!item.resize);
987
- const firstEventResize = lastResizeEvent?.resize?.[0];
988
- const resize = {
989
- width: firstEventResize?.data.width,
990
- height: firstEventResize?.data.height,
991
- };
992
- return {
993
- doc: docSize,
994
- resize: resize,
995
- size: {
996
- width: resize.width ?? docSize.width,
997
- height: resize.height ?? docSize.height,
998
- },
999
- };
1000
- }
1001
1161
  function reset(iframe, payloads, onSuccess) {
1002
1162
  const { size } = findLastSizeOfDom(payloads);
1003
1163
  const docWidth = size.width ?? 0;
@@ -1027,7 +1187,7 @@ function sortEvents(a, b) {
1027
1187
 
1028
1188
  const useReplayRender = () => {
1029
1189
  const data = useHeatmapDataStore((state) => state.data);
1030
- const setConfig = useHeatmapDataStore((state) => state.setConfig);
1190
+ const setWidth = useHeatmapConfigStore((state) => state.setWidth);
1031
1191
  const visualizerRef = useRef(null);
1032
1192
  const iframeRef = useRef(null);
1033
1193
  const eventsRef = useRef([]);
@@ -1045,14 +1205,14 @@ const useReplayRender = () => {
1045
1205
  visualizer.setup(iframe.contentWindow, {
1046
1206
  version: envelope.version,
1047
1207
  onresize: (width) => {
1048
- setConfig({ width });
1208
+ setWidth(width);
1049
1209
  },
1050
1210
  mobile,
1051
1211
  vNext: true,
1052
1212
  locale: 'en-us',
1053
1213
  });
1054
1214
  return visualizer;
1055
- }, [setConfig]);
1215
+ }, [setWidth]);
1056
1216
  // Animation loop for replay
1057
1217
  const replayLoop = useCallback(() => {
1058
1218
  if (!isPlayingRef.current)
@@ -1186,8 +1346,7 @@ const useContainerDimensions = (props) => {
1186
1346
  };
1187
1347
 
1188
1348
  const useContentDimensions = ({ iframeRef, }) => {
1189
- const config = useHeatmapDataStore((state) => state.config);
1190
- const contentWidth = config?.width ?? 0;
1349
+ const contentWidth = useHeatmapConfigStore((state) => state.width);
1191
1350
  useEffect(() => {
1192
1351
  if (!contentWidth)
1193
1352
  return;
@@ -1199,9 +1358,7 @@ const useContentDimensions = ({ iframeRef, }) => {
1199
1358
  };
1200
1359
 
1201
1360
  const useIframeHeight = (props) => {
1202
- const { iframeRef } = props;
1203
- const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
1204
- const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
1361
+ const { iframeRef, setIframeHeight } = props;
1205
1362
  const isRenderViz = useHeatmapVizStore((state) => state.isRenderViz);
1206
1363
  const resizeObserverRef = useRef(null);
1207
1364
  const mutationObserverRef = useRef(null);
@@ -1279,7 +1436,7 @@ const useIframeHeight = (props) => {
1279
1436
  iframe.removeEventListener('load', setupObservers);
1280
1437
  };
1281
1438
  }, [iframeRef, isRenderViz, updateIframeHeight]);
1282
- return { iframeHeight };
1439
+ return {};
1283
1440
  };
1284
1441
 
1285
1442
  const useScaleCalculation = (props) => {
@@ -1318,14 +1475,13 @@ const useScrollSync = ({ iframeRef }) => {
1318
1475
  };
1319
1476
 
1320
1477
  const useHeatmapScale = (props) => {
1321
- // const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
1322
- const { wrapperRef, iframeRef, visualRef } = props;
1478
+ const { wrapperRef, iframeRef, iframeHeight, setIframeHeight } = props;
1323
1479
  // 1. Observe container dimensions
1324
1480
  const { containerWidth, containerHeight } = useContainerDimensions({ wrapperRef });
1325
1481
  // 2. Get content dimensions from config
1326
1482
  const { contentWidth } = useContentDimensions({ iframeRef });
1327
1483
  // 3. Observe iframe height (now reacts to width changes)
1328
- const { iframeHeight } = useIframeHeight({ iframeRef });
1484
+ useIframeHeight({ iframeRef, setIframeHeight });
1329
1485
  // 4. Calculate scale
1330
1486
  const { scale } = useScaleCalculation({ containerWidth, contentWidth });
1331
1487
  // 5. Setup scroll sync
@@ -1333,13 +1489,81 @@ const useHeatmapScale = (props) => {
1333
1489
  return {
1334
1490
  containerWidth,
1335
1491
  containerHeight,
1336
- iframeHeight,
1337
1492
  scaledWidth: contentWidth * scale,
1338
1493
  scaledHeight: iframeHeight * scale,
1339
1494
  handleScroll,
1340
1495
  };
1341
1496
  };
1342
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
+
1343
1567
  const BoxStack = forwardRef(({ children, ...props }, ref) => {
1344
1568
  const id = props.id;
1345
1569
  const flexDirection = props.flexDirection;
@@ -1385,9 +1609,42 @@ const BoxStack = forwardRef(({ children, ...props }, ref) => {
1385
1609
 
1386
1610
  const ContentTopBar = () => {
1387
1611
  const controls = useHeatmapControlStore((state) => state.controls);
1612
+ const TopBar = controls.TopBar;
1388
1613
  return (jsx(BoxStack, { id: "gx-hm-content-header", flexDirection: "row", alignItems: "center", overflow: "auto", zIndex: 1, backgroundColor: "white", style: {
1389
1614
  borderBottom: `${HEATMAP_CONFIG.borderWidth}px solid ${HEATMAP_CONFIG.borderColor}`,
1390
- }, children: controls.TopBar ?? null }));
1615
+ }, children: TopBar && jsx(TopBar, {}) }));
1616
+ };
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 }) }));
1391
1648
  };
1392
1649
 
1393
1650
  const useClickmap = () => {
@@ -1411,15 +1668,16 @@ const useScrollmap = () => {
1411
1668
  return {};
1412
1669
  };
1413
1670
 
1414
- const useHeatmapVizCanvas = ({ type }) => {
1671
+ const useHeatmapVizCanvas = () => {
1672
+ const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
1415
1673
  const heatmapRender = useMemo(() => {
1416
- switch (type) {
1674
+ switch (heatmapType) {
1417
1675
  case IHeatmapType.Click:
1418
1676
  return useClickmap;
1419
1677
  case IHeatmapType.Scroll:
1420
1678
  return useScrollmap;
1421
1679
  }
1422
- }, [type]);
1680
+ }, [heatmapType]);
1423
1681
  return heatmapRender?.();
1424
1682
  };
1425
1683
 
@@ -1611,57 +1869,59 @@ const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
1611
1869
  } }));
1612
1870
  };
1613
1871
 
1614
- const ReplayControls = () => {
1615
- const replayResult = useReplayRender();
1616
- return (jsxs("div", { style: {
1617
- position: 'absolute',
1618
- bottom: 20,
1619
- left: '50%',
1620
- 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',
1621
1880
  display: 'flex',
1622
- gap: 10,
1623
- backgroundColor: 'rgba(0, 0, 0, 0.7)',
1624
- padding: '10px 20px',
1625
- borderRadius: 8,
1626
- }, children: [jsx("button", { onClick: replayResult.play, style: {
1627
- padding: '8px 16px',
1628
- backgroundColor: '#4CAF50',
1629
- color: 'white',
1630
- border: 'none',
1631
- borderRadius: 4,
1632
- cursor: 'pointer',
1633
- }, children: "Play" }), jsx("button", { onClick: replayResult.pause, style: {
1634
- padding: '8px 16px',
1635
- backgroundColor: '#f44336',
1636
- color: 'white',
1637
- border: 'none',
1638
- borderRadius: 4,
1639
- cursor: 'pointer',
1640
- }, 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 }) }) }));
1641
1902
  };
1642
1903
 
1643
1904
  const VizDomRenderer = ({ mode = 'heatmap' }) => {
1644
- const config = useHeatmapDataStore((state) => state.config);
1905
+ const width = useHeatmapConfigStore((state) => state.width);
1906
+ const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
1645
1907
  const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
1646
- const widthScale = useHeatmapVizStore((state) => state.scale);
1647
1908
  const setSelectedElement = useHeatmapInteractionStore((state) => state.setSelectedElement);
1648
1909
  const wrapperRef = useRef(null);
1649
1910
  const visualRef = useRef(null);
1650
1911
  const { iframeRef } = useHeatmapVizRender(mode);
1651
- const { iframeHeight, scaledHeight, handleScroll } = useHeatmapScale({
1912
+ const { scaledHeight, handleScroll } = useHeatmapScale({
1652
1913
  wrapperRef,
1653
1914
  iframeRef,
1654
1915
  visualRef,
1916
+ iframeHeight,
1917
+ setIframeHeight,
1655
1918
  });
1656
- const contentWidth = config?.width ?? 0;
1657
- const contentHeight = scaledHeight > 0
1658
- ? `${scaledHeight + HEATMAP_CONFIG['heightToolbar'] + HEATMAP_CONFIG['padding'] * 2}px`
1659
- : 'auto';
1919
+ const contentWidth = width ?? 0;
1660
1920
  const onScroll = (e) => {
1661
1921
  const scrollTop = e.currentTarget.scrollTop;
1662
1922
  handleScroll(scrollTop);
1663
1923
  };
1664
- useHeatmapVizCanvas({ type: config?.heatmapType });
1924
+ useHeatmapVizCanvas();
1665
1925
  const cleanUp = () => {
1666
1926
  setIframeHeight(0);
1667
1927
  setSelectedElement(null);
@@ -1669,68 +1929,82 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
1669
1929
  useEffect(() => {
1670
1930
  return cleanUp;
1671
1931
  }, []);
1672
- return (jsxs("div", { ref: visualRef, className: "gx-hm-visual", onScroll: onScroll, style: {
1673
- overflow: 'hidden auto',
1674
- display: 'flex',
1675
- position: 'relative',
1676
- justifyContent: 'center',
1677
- flex: 1,
1678
- // paddingBottom: HEATMAP_STYLE['viz']['paddingBottom'],
1679
- background: '#fff',
1680
- }, children: [jsx("div", { className: "gx-hm-visual-unscaled", style: {
1681
- width: '100%',
1682
- display: 'flex',
1683
- justifyContent: 'center',
1684
- alignItems: 'flex-start',
1685
- height: contentHeight,
1686
- padding: HEATMAP_STYLE['wrapper']['padding'],
1687
- paddingBottom: HEATMAP_STYLE['viz']['paddingBottom'],
1688
- background: HEATMAP_STYLE['viz']['background'],
1689
- }, children: jsxs("div", { className: "gx-hm-wrapper", ref: wrapperRef, style: {
1690
- width: contentWidth,
1691
- height: iframeHeight,
1692
- transform: `scale(${widthScale})`,
1693
- transformOrigin: 'top center',
1694
- paddingBlockEnd: '0',
1695
- }, 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, {})] }));
1696
- };
1697
-
1698
- 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 = () => {
1699
1940
  const controls = useHeatmapControlStore((state) => state.controls);
1700
1941
  const isRendering = useHeatmapDataStore((state) => state.isRendering);
1701
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
+ }, []);
1702
1951
  if (isRendering)
1703
1952
  return controls.VizLoading ?? null;
1704
- 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: {
1705
- minWidth: '394px',
1706
- }, 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, {})] }));
1707
1954
  };
1708
1955
 
1709
- const ContentMetricBar = () => {
1710
- const controls = useHeatmapControlStore((state) => state.controls);
1711
- return (jsx(BoxStack, { id: "gx-hm-content-metric-bar", flexDirection: "row", alignItems: "center", overflow: "auto", zIndex: 1, backgroundColor: "white", style: {
1712
- borderBottom: `${HEATMAP_CONFIG.borderWidth}px solid ${HEATMAP_CONFIG.borderColor}`,
1713
- }, 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" }) }));
1714
1975
  };
1715
1976
 
1716
- const ContentToolbar = () => {
1977
+ const VizLiveHeatmap = () => {
1717
1978
  const controls = useHeatmapControlStore((state) => state.controls);
1718
- return (jsx("div", { id: "gx-hm-content-toolbar", style: {
1719
- zIndex: 2,
1720
- position: 'absolute',
1721
- bottom: 0,
1722
- left: '8px',
1723
- right: '24px',
1724
- padding: '8px',
1725
- paddingBlock: '16px',
1726
- }, 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
+ }
1727
2002
  };
1728
2003
 
1729
2004
  const LeftSidebar = () => {
1730
2005
  const controls = useHeatmapControlStore((state) => state.controls);
1731
2006
  const isHideSidebar = useHeatmapInteractionStore((state) => state.state.hideSidebar);
1732
- const config = useHeatmapDataStore((state) => state.config);
1733
- const sidebarWidth = config?.sidebarWidth || DEFAULT_SIDEBAR_WIDTH;
2007
+ const sidebarWidth = useHeatmapConfigStore((state) => state.sidebarWidth);
1734
2008
  if (isHideSidebar) {
1735
2009
  return null;
1736
2010
  }
@@ -1753,7 +2027,7 @@ const LeftSidebar = () => {
1753
2027
  };
1754
2028
 
1755
2029
  const WrapperPreview = () => {
1756
- 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, {})] })] }));
1757
2031
  };
1758
2032
 
1759
2033
  const WrapperLayout = () => {
@@ -1778,22 +2052,4 @@ const HeatmapLayout = ({ data, clickmap, controls, dataInfo, }) => {
1778
2052
  }
1779
2053
  };
1780
2054
 
1781
- var PanelContent;
1782
- (function (PanelContent) {
1783
- PanelContent["Sessions"] = "Sessions";
1784
- PanelContent["Timeline"] = "Timeline";
1785
- PanelContent["Area"] = "Area";
1786
- PanelContent["Click"] = "Click";
1787
- PanelContent["Scroll"] = "Scroll";
1788
- PanelContent["Attention"] = "Attention";
1789
- })(PanelContent || (PanelContent = {}));
1790
- var ErrorType;
1791
- (function (ErrorType) {
1792
- ErrorType["NoResults"] = "NoResults";
1793
- ErrorType["NoClicks"] = "NoClicks";
1794
- ErrorType["NoScroll"] = "NoScroll";
1795
- ErrorType["ServerError"] = "ServerError";
1796
- ErrorType["DataError"] = "DataError";
1797
- })(ErrorType || (ErrorType = {}));
1798
-
1799
- export { GraphView, HeatmapLayout, IHeatmapType, useHeatmapDataStore, useHeatmapInteractionStore };
2055
+ export { GraphView, HeatmapLayout, IHeatmapType, useHeatmapConfigStore, useHeatmapDataStore, useHeatmapInteractionStore, useHeatmapLiveStore };