@gemx-dev/heatmap-react 3.5.40 → 3.5.42

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 (86) hide show
  1. package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -1
  2. package/dist/esm/components/VizElement/HeatmapElements.d.ts.map +1 -1
  3. package/dist/esm/components/VizElement/VizElements.d.ts.map +1 -1
  4. package/dist/esm/components/VizLive/VizLiveRenderer.d.ts.map +1 -1
  5. package/dist/esm/configs/style.d.ts +2 -0
  6. package/dist/esm/configs/style.d.ts.map +1 -1
  7. package/dist/esm/helpers/viewport-fixer.d.ts.map +1 -1
  8. package/dist/esm/hooks/vix-elements/useHeatmapMouseHandler.d.ts +34 -0
  9. package/dist/esm/hooks/vix-elements/useHeatmapMouseHandler.d.ts.map +1 -0
  10. package/dist/esm/hooks/vix-elements/useHoveredElement.d.ts.map +1 -1
  11. package/dist/esm/hooks/viz-canvas/useClickmap.d.ts +3 -1
  12. package/dist/esm/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
  13. package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -1
  14. package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
  15. package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts +3 -1
  16. package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
  17. package/dist/esm/hooks/viz-live/index.d.ts +1 -1
  18. package/dist/esm/hooks/viz-live/{useIframeMessage.d.ts → useVizLiveIframeMsg.d.ts} +2 -10
  19. package/dist/esm/hooks/viz-live/useVizLiveIframeMsg.d.ts.map +1 -0
  20. package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts +4 -0
  21. package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts.map +1 -0
  22. package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  23. package/dist/esm/hooks/viz-scale/useContainerDimensions.d.ts.map +1 -1
  24. package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts +1 -1
  25. package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
  26. package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts +10 -0
  27. package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts.map +1 -0
  28. package/dist/esm/index.d.ts +1 -1
  29. package/dist/esm/index.d.ts.map +1 -1
  30. package/dist/esm/index.js +476 -86
  31. package/dist/esm/index.mjs +476 -86
  32. package/dist/esm/stores/index.d.ts +1 -0
  33. package/dist/esm/stores/index.d.ts.map +1 -1
  34. package/dist/esm/stores/interaction.d.ts.map +1 -1
  35. package/dist/esm/stores/mode-live.d.ts +4 -0
  36. package/dist/esm/stores/mode-live.d.ts.map +1 -1
  37. package/dist/esm/stores/mode-single.d.ts +9 -0
  38. package/dist/esm/stores/mode-single.d.ts.map +1 -0
  39. package/dist/esm/stores/viz.d.ts +0 -4
  40. package/dist/esm/stores/viz.d.ts.map +1 -1
  41. package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -1
  42. package/dist/umd/components/VizElement/HeatmapElements.d.ts.map +1 -1
  43. package/dist/umd/components/VizElement/VizElements.d.ts.map +1 -1
  44. package/dist/umd/components/VizLive/VizLiveRenderer.d.ts.map +1 -1
  45. package/dist/umd/configs/style.d.ts +2 -0
  46. package/dist/umd/configs/style.d.ts.map +1 -1
  47. package/dist/umd/helpers/viewport-fixer.d.ts.map +1 -1
  48. package/dist/umd/hooks/vix-elements/useHeatmapMouseHandler.d.ts +34 -0
  49. package/dist/umd/hooks/vix-elements/useHeatmapMouseHandler.d.ts.map +1 -0
  50. package/dist/umd/hooks/vix-elements/useHoveredElement.d.ts.map +1 -1
  51. package/dist/umd/hooks/viz-canvas/useClickmap.d.ts +3 -1
  52. package/dist/umd/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
  53. package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -1
  54. package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
  55. package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts +3 -1
  56. package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
  57. package/dist/umd/hooks/viz-live/index.d.ts +1 -1
  58. package/dist/umd/hooks/viz-live/{useIframeMessage.d.ts → useVizLiveIframeMsg.d.ts} +2 -10
  59. package/dist/umd/hooks/viz-live/useVizLiveIframeMsg.d.ts.map +1 -0
  60. package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts +4 -0
  61. package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts.map +1 -0
  62. package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  63. package/dist/umd/hooks/viz-scale/useContainerDimensions.d.ts.map +1 -1
  64. package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts +1 -1
  65. package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
  66. package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts +10 -0
  67. package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts.map +1 -0
  68. package/dist/umd/index.d.ts +1 -1
  69. package/dist/umd/index.d.ts.map +1 -1
  70. package/dist/umd/index.js +2 -2
  71. package/dist/umd/stores/index.d.ts +1 -0
  72. package/dist/umd/stores/index.d.ts.map +1 -1
  73. package/dist/umd/stores/interaction.d.ts.map +1 -1
  74. package/dist/umd/stores/mode-live.d.ts +4 -0
  75. package/dist/umd/stores/mode-live.d.ts.map +1 -1
  76. package/dist/umd/stores/mode-single.d.ts +9 -0
  77. package/dist/umd/stores/mode-single.d.ts.map +1 -0
  78. package/dist/umd/stores/viz.d.ts +0 -4
  79. package/dist/umd/stores/viz.d.ts.map +1 -1
  80. package/package.json +1 -1
  81. package/dist/esm/hooks/viz-live/useIframeMessage.d.ts.map +0 -1
  82. package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts +0 -10
  83. package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts.map +0 -1
  84. package/dist/umd/hooks/viz-live/useIframeMessage.d.ts.map +0 -1
  85. package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts +0 -10
  86. package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts.map +0 -1
@@ -61,6 +61,8 @@ const HEATMAP_STYLE = {
61
61
  },
62
62
  wrapper: {
63
63
  padding: `${HEATMAP_CONFIG.padding}px 0`,
64
+ paddingBlock: `${HEATMAP_CONFIG.padding}px`,
65
+ paddingInline: `${HEATMAP_CONFIG.padding}px`,
64
66
  },
65
67
  };
66
68
  const DEFAULT_SIDEBAR_WIDTH = 260;
@@ -139,15 +141,12 @@ const useHeatmapVizStore = create()((set, get) => {
139
141
  isRenderViz: false,
140
142
  setIsRenderViz: (isRenderViz) => set({ isRenderViz }),
141
143
  scale: 1,
142
- vizRef: undefined,
143
- iframeHeight: 0,
144
144
  setScale: (scale) => set({ scale }),
145
- setVizRef: (vizRef) => set({ vizRef }),
146
- setIframeHeight: (iframeHeight) => set({ iframeHeight }),
147
145
  };
148
146
  });
149
147
 
150
148
  const initialState = {
149
+ payloads: [],
151
150
  htmlContent: '',
152
151
  wrapperHeight: 0,
153
152
  iframeHeight: 0,
@@ -156,12 +155,23 @@ const useHeatmapLiveStore = create()((set, get) => {
156
155
  return {
157
156
  ...initialState,
158
157
  reset: () => set(initialState),
158
+ setPayloads: (payloads) => set({ payloads }),
159
+ addPayload: (payload) => set((state) => ({ payloads: [...state.payloads, payload] })),
159
160
  setHtmlContent: (htmlContent) => set({ htmlContent }),
160
161
  setWrapperHeight: (wrapperHeight) => set({ wrapperHeight }),
161
162
  setIframeHeight: (iframeHeight) => set({ iframeHeight }),
162
163
  };
163
164
  });
164
165
 
166
+ const useHeatmapSingleStore = create()((set, get) => {
167
+ return {
168
+ vizRef: null,
169
+ iframeHeight: 0,
170
+ setVizRef: (vizRef) => set({ vizRef }),
171
+ setIframeHeight: (iframeHeight) => set({ iframeHeight }),
172
+ };
173
+ });
174
+
165
175
  const useRegisterConfig = () => {
166
176
  const mode = useHeatmapConfigStore((state) => state.mode);
167
177
  const width = useHeatmapConfigStore((state) => state.width);
@@ -546,12 +556,9 @@ class ViewportUnitsFixer {
546
556
  try {
547
557
  win.__viewportConfig = this.config;
548
558
  const script = doc.createElement('script');
549
- console.log(`🚀 🐥 ~ ViewportUnitsFixer ~ injectScript ~ script:`, script);
550
559
  const scriptCode = await getScriptInjectCode();
551
- console.log(`🚀 🐥 ~ ViewportUnitsFixer ~ injectScript ~ scriptCode:`, scriptCode);
552
560
  script.textContent = scriptCode;
553
561
  doc.head.appendChild(script);
554
- console.log(`🚀 🐥 ~ ViewportUnitsFixer ~ injectScript ~ doc:`, doc);
555
562
  }
556
563
  catch (error) {
557
564
  console.error('[Parent] Failed to inject script', error);
@@ -872,7 +879,7 @@ const useHeatmapEffects = ({ isVisible, isElementSidebarOpen, setShouldShowCallo
872
879
 
873
880
  const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
874
881
  const widthScale = useHeatmapVizStore((state) => state.scale);
875
- const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
882
+ const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
876
883
  const heatmapWidth = useHeatmapConfigStore((state) => state.width);
877
884
  return useCallback((element) => {
878
885
  const hash = element?.hash;
@@ -920,6 +927,179 @@ const debounce = (fn, delay) => {
920
927
  };
921
928
  };
922
929
 
930
+ // ===================== CONSTANTS =====================
931
+ const HEATMAP_ELEMENT_ATTRIBUTE = 'data-clarity-hashalpha'; // Hoặc attribute bạn đang dùng
932
+ // ===================== UTILITY FUNCTIONS =====================
933
+ /**
934
+ * Lấy bounding box tuyệt đối của element (relative to document)
935
+ */
936
+ function getBoundingBox(element) {
937
+ if (typeof element.getBoundingClientRect !== 'function') {
938
+ return null;
939
+ }
940
+ const rect = element.getBoundingClientRect();
941
+ // Lấy scroll offset (hỗ trợ cả cách cũ và mới)
942
+ const scrollLeft = 'pageXOffset' in window ? window.pageXOffset : document.documentElement.scrollLeft;
943
+ const scrollTop = 'pageYOffset' in window ? window.pageYOffset : document.documentElement.scrollTop;
944
+ // Kiểm tra element có kích thước hợp lệ
945
+ if (!rect || (rect.height === 0 && rect.width === 0)) {
946
+ return null;
947
+ }
948
+ // Trả về vị trí tuyệt đối
949
+ return {
950
+ left: Math.floor(rect.left + scrollLeft),
951
+ top: Math.floor(rect.top + scrollTop),
952
+ width: Math.floor(rect.width),
953
+ height: Math.floor(rect.height),
954
+ };
955
+ }
956
+ /**
957
+ * Lấy tất cả elements tại tọa độ (x, y), hỗ trợ Shadow DOM
958
+ */
959
+ function getElementsAtPoint(documentOrShadowRoot, x, y, filterFunction, visitedShadowRoots = new Set()) {
960
+ // Lấy tất cả elements tại vị trí
961
+ const elementsAtPoint = documentOrShadowRoot.elementsFromPoint(x, y);
962
+ if (!filterFunction) {
963
+ return elementsAtPoint;
964
+ }
965
+ // Tìm element đầu tiên match với filter
966
+ const matchedElement = elementsAtPoint.find(filterFunction);
967
+ // Nếu element có Shadow DOM và chưa visit -> đệ quy vào
968
+ if (matchedElement?.shadowRoot && !visitedShadowRoots.has(matchedElement.shadowRoot)) {
969
+ visitedShadowRoots.add(matchedElement.shadowRoot);
970
+ return getElementsAtPoint(matchedElement.shadowRoot, x, y, filterFunction, visitedShadowRoots);
971
+ }
972
+ return elementsAtPoint;
973
+ }
974
+ // ===================== MAIN HOOK =====================
975
+ function useHeatmapMouseHandler(props) {
976
+ const { heatmapWrapperRef, iframeRef, parentRef, heatmapInfo, scaleRatio, onElementHover } = props;
977
+ const handleMouseMove = useCallback((event) => {
978
+ // Kiểm tra tất cả refs và data cần thiết
979
+ if (!heatmapWrapperRef?.current ||
980
+ !iframeRef?.current ||
981
+ !iframeRef.current.contentDocument ||
982
+ !heatmapInfo?.elementMapInfo ||
983
+ !parentRef?.current) {
984
+ return;
985
+ }
986
+ try {
987
+ // Tính toán scroll position (đã scale)
988
+ const scrollTop = parentRef.current.scrollTop / scaleRatio;
989
+ console.log(`🚀 🐥 ~ useHeatmapMouseHandler ~ scrollTop:`, scrollTop);
990
+ // Lấy vị trí của heatmap wrapper
991
+ const wrapperRect = heatmapWrapperRef.current.getBoundingClientRect();
992
+ // Tính toán tọa độ chuột trong iframe (đã scale)
993
+ const mouseX = (event.clientX - wrapperRect.left) / scaleRatio;
994
+ const mouseY = (event.clientY - wrapperRect.top) / scaleRatio - scrollTop;
995
+ // Tìm elements tại vị trí chuột
996
+ const elementsAtPoint = getElementsAtPoint(iframeRef.current.contentDocument, Math.round(mouseX), Math.round(mouseY),
997
+ // Filter: chỉ lấy elements có heatmap attribute
998
+ (element) => element.hasAttribute(HEATMAP_ELEMENT_ATTRIBUTE));
999
+ if (!elementsAtPoint || elementsAtPoint.length === 0) {
1000
+ return;
1001
+ }
1002
+ // Duyệt qua các elements tìm được
1003
+ for (let i = 0; i < elementsAtPoint.length; i++) {
1004
+ const element = elementsAtPoint[i];
1005
+ // Lấy hash/id của element
1006
+ const elementHash = element.getAttribute(HEATMAP_ELEMENT_ATTRIBUTE);
1007
+ // Kiểm tra element có data trong heatmapInfo không
1008
+ if (elementHash && heatmapInfo.elementMapInfo[elementHash]) {
1009
+ const elementData = heatmapInfo.elementMapInfo[elementHash];
1010
+ // Lấy bounding box của element
1011
+ const boundingBox = getBoundingBox(element);
1012
+ if (boundingBox) {
1013
+ // Tính rank của element
1014
+ const rank = Array.isArray(heatmapInfo.sortedElements) && elementData
1015
+ ? heatmapInfo.sortedElements.indexOf(elementData) + 1
1016
+ : NaN;
1017
+ // Callback với thông tin element
1018
+ onElementHover({
1019
+ ...boundingBox,
1020
+ // Giới hạn width không vượt quá width của heatmap
1021
+ width: Math.min(boundingBox.width, heatmapInfo.width || 0),
1022
+ // Adjust top position với scroll
1023
+ top: boundingBox.top + scrollTop,
1024
+ // Metadata
1025
+ hash: elementHash,
1026
+ clicks: elementData.totalclicks,
1027
+ rank: rank,
1028
+ selector: elementData.selector || '',
1029
+ });
1030
+ // Dừng loop khi tìm thấy element hợp lệ đầu tiên
1031
+ break;
1032
+ }
1033
+ }
1034
+ }
1035
+ }
1036
+ catch (error) {
1037
+ console.warn('Error handling mouse move on heatmap:', error);
1038
+ }
1039
+ }, [heatmapWrapperRef, iframeRef, parentRef, heatmapInfo, scaleRatio, onElementHover]);
1040
+ return { handleMouseMove };
1041
+ }
1042
+ // ===================== EXAMPLE USAGE =====================
1043
+ /*
1044
+ import { useRef, useState } from 'react';
1045
+
1046
+ function HeatmapComponent() {
1047
+ const heatmapWrapperRef = useRef<HTMLDivElement>(null);
1048
+ const iframeRef = useRef<HTMLIFrameElement>(null);
1049
+ const parentRef = useRef<HTMLDivElement>(null);
1050
+
1051
+ const [hoveredElement, setHoveredElement] = useState<HoveredElementInfo | null>(null);
1052
+
1053
+ const heatmapInfo = {
1054
+ width: 1920,
1055
+ elementMapInfo: {
1056
+ 'hash123': {
1057
+ totalclicks: 45,
1058
+ selector: 'button.submit'
1059
+ }
1060
+ },
1061
+ sortedElements: [...]
1062
+ };
1063
+
1064
+ const { handleMouseMove } = useHeatmapMouseHandler({
1065
+ heatmapWrapperRef,
1066
+ iframeRef,
1067
+ parentRef,
1068
+ heatmapInfo,
1069
+ scaleRatio: 0.8, // 80% zoom
1070
+ onElementHover: (info) => {
1071
+ setHoveredElement(info);
1072
+ console.log('Hovered element:', info);
1073
+ }
1074
+ });
1075
+
1076
+ return (
1077
+ <div ref={parentRef}>
1078
+ <div
1079
+ ref={heatmapWrapperRef}
1080
+ onMouseMove={handleMouseMove}
1081
+ >
1082
+ <iframe ref={iframeRef} />
1083
+
1084
+ {hoveredElement && (
1085
+ <div className="tooltip" style={{
1086
+ position: 'absolute',
1087
+ left: hoveredElement.left,
1088
+ top: hoveredElement.top
1089
+ }}>
1090
+ Clicks: {hoveredElement.clicks}
1091
+ <br />
1092
+ Rank: #{hoveredElement.rank}
1093
+ <br />
1094
+ Selector: {hoveredElement.selector}
1095
+ </div>
1096
+ )}
1097
+ </div>
1098
+ </div>
1099
+ );
1100
+ }
1101
+ */
1102
+
923
1103
  const useHoveredElement = ({ iframeRef, getRect }) => {
924
1104
  const hoveredElement = useHeatmapInteractionStore((state) => state.hoveredElement);
925
1105
  const setHoveredElement = useHeatmapInteractionStore((state) => state.setHoveredElement);
@@ -941,7 +1121,7 @@ const useHoveredElement = ({ iframeRef, getRect }) => {
941
1121
  const doc = iframe.contentDocument;
942
1122
  const iframeRect = iframe.getBoundingClientRect();
943
1123
  const { x, y } = convertViewportToIframeCoords(event.clientX, event.clientY, iframeRect, widthScale);
944
- const targetElement = findTargetElement(doc, x, y);
1124
+ const targetElement = findTargetElement(doc, x, y, heatmapInfo);
945
1125
  if (!targetElement || !isValidElement(targetElement, heatmapInfo)) {
946
1126
  reset();
947
1127
  return;
@@ -992,7 +1172,25 @@ const convertViewportToIframeCoords = (clientX, clientY, iframeRect, scale) => {
992
1172
  }
993
1173
  return { x, y };
994
1174
  };
995
- const findTargetElement = (doc, x, y) => {
1175
+ const findTargetElement = (doc, x, y, heatmapInfo) => {
1176
+ const HEATMAP_ELEMENT_ATTRIBUTE = 'data-clarity-hashalpha';
1177
+ const elementsAtPoint = getElementsAtPoint(doc, Math.round(x), Math.round(y), (element) => element.hasAttribute(HEATMAP_ELEMENT_ATTRIBUTE));
1178
+ let dataElement = null;
1179
+ for (let i = 0; i < elementsAtPoint.length; i++) {
1180
+ const element = elementsAtPoint[i];
1181
+ const elementHash = element.getAttribute(HEATMAP_ELEMENT_ATTRIBUTE);
1182
+ if (elementHash && heatmapInfo.elementMapInfo?.[elementHash]) {
1183
+ heatmapInfo.elementMapInfo[elementHash];
1184
+ const boundingBox = getBoundingBox(element);
1185
+ if (boundingBox) {
1186
+ dataElement = element;
1187
+ break;
1188
+ }
1189
+ }
1190
+ }
1191
+ if (!!dataElement) {
1192
+ return dataElement;
1193
+ }
996
1194
  let targetElement = getElementAtPoint(doc, x, y);
997
1195
  if (!targetElement) {
998
1196
  targetElement = doc.elementFromPoint(x, y);
@@ -1016,9 +1214,9 @@ var MessageType;
1016
1214
  MessageType["GX_DOM_TRACKING_PAYLOAD"] = "GX_DOM_TRACKING_PAYLOAD";
1017
1215
  MessageType["CLARITY_READY"] = "CLARITY_READY";
1018
1216
  })(MessageType || (MessageType = {}));
1019
- function useIframeMessage(options = {}) {
1217
+ function useVizLiveIframeMsg(options = {}) {
1020
1218
  const { trustedOrigins = [], onMessage } = options;
1021
- const [payloads, setPayloads] = useState([]);
1219
+ const addPayload = useHeatmapLiveStore((state) => state.addPayload);
1022
1220
  const [isReady, setIsReady] = useState(false);
1023
1221
  const iframeRef = useRef(null);
1024
1222
  const isValidOrigin = useCallback((origin) => {
@@ -1044,9 +1242,9 @@ function useIframeMessage(options = {}) {
1044
1242
  switch (message.type) {
1045
1243
  case MessageType.GX_DOM_TRACKING_PAYLOAD:
1046
1244
  if (message.payload) {
1047
- const decodedPayloads = decodePayloads(message.payload);
1048
- if (decodedPayloads) {
1049
- setPayloads((prev) => [...prev, decodedPayloads]);
1245
+ const data = decodePayloads(message.payload);
1246
+ if (data) {
1247
+ addPayload(data);
1050
1248
  }
1051
1249
  }
1052
1250
  break;
@@ -1061,27 +1259,19 @@ function useIframeMessage(options = {}) {
1061
1259
  window.removeEventListener('message', handleMessage);
1062
1260
  };
1063
1261
  }, [handleMessage]);
1064
- const clearPayloads = useCallback(() => {
1065
- setPayloads([]);
1066
- }, []);
1067
- const reset = useCallback(() => {
1068
- setPayloads([]);
1069
- setIsReady(false);
1070
- }, []);
1071
1262
  return {
1072
1263
  iframeRef,
1073
- payloads,
1074
1264
  isReady,
1075
- clearPayloads,
1076
- reset,
1077
1265
  };
1078
1266
  }
1079
- function useIframeRender() {
1267
+
1268
+ function useVizLiveRender() {
1080
1269
  const wrapperHeight = useHeatmapLiveStore((state) => state.wrapperHeight);
1270
+ const setIframeHeight = useHeatmapLiveStore((state) => state.setIframeHeight);
1081
1271
  const contentWidth = useHeatmapConfigStore((state) => state.width);
1082
- const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
1083
1272
  const htmlContent = useHeatmapLiveStore((state) => state.htmlContent);
1084
- const { iframeRef, payloads, isReady } = useIframeMessage();
1273
+ const setIsRenderViz = useHeatmapVizStore((state) => state.setIsRenderViz);
1274
+ const { iframeRef, isReady } = useVizLiveIframeMsg();
1085
1275
  useEffect(() => {
1086
1276
  if (!htmlContent || !iframeRef.current)
1087
1277
  return;
@@ -1101,41 +1291,41 @@ function useIframeRender() {
1101
1291
  const iframe = iframeRef.current;
1102
1292
  if (!iframe || !htmlContent)
1103
1293
  return;
1294
+ setIsRenderViz(false);
1104
1295
  reset$1(iframe, { width: contentWidth, height: wrapperHeight }, (height) => {
1105
- setIframeHeight(height);
1296
+ height && setIframeHeight(height);
1297
+ setIsRenderViz(true);
1106
1298
  });
1107
1299
  }, [isReady, contentWidth, wrapperHeight]);
1108
1300
  return {
1109
1301
  iframeRef,
1110
- payloads,
1111
- isReady,
1112
1302
  };
1113
1303
  }
1114
- function reset$1(iframe, payloads, onSuccess) {
1304
+ function reset$1(iframe, rect, onSuccess) {
1115
1305
  const viewportFixer = initViewportFixer({
1116
- targetWidth: payloads.width,
1117
- targetHeight: payloads.height,
1306
+ targetWidth: rect.width,
1307
+ targetHeight: rect.height,
1118
1308
  iframe: iframe,
1119
1309
  onSuccess: (data) => {
1120
- onSuccess(data.height);
1121
1310
  iframe.height = `${data.height}px`;
1311
+ onSuccess(data.height);
1122
1312
  },
1123
1313
  });
1124
1314
  viewportFixer.recalculate();
1125
1315
  return iframe;
1126
1316
  }
1127
1317
 
1318
+ let visualizer = new Visualizer();
1128
1319
  const useHeatmapRender = () => {
1129
1320
  const data = useHeatmapDataStore((state) => state.data);
1130
- const setVizRef = useHeatmapVizStore((state) => state.setVizRef);
1321
+ const setVizRef = useHeatmapSingleStore((state) => state.setVizRef);
1131
1322
  const setIsRenderViz = useHeatmapVizStore((state) => state.setIsRenderViz);
1132
- const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
1323
+ const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
1133
1324
  const iframeRef = useRef(null);
1134
1325
  const renderHeatmap = useCallback(async (payloads) => {
1135
1326
  if (!payloads || payloads.length === 0)
1136
1327
  return;
1137
1328
  setIsRenderViz(false);
1138
- const visualizer = new Visualizer();
1139
1329
  const iframe = iframeRef.current;
1140
1330
  if (!iframe?.contentWindow)
1141
1331
  return;
@@ -1143,8 +1333,8 @@ const useHeatmapRender = () => {
1143
1333
  reset(iframe, payloads, (height) => {
1144
1334
  height && setIframeHeight(height);
1145
1335
  setIsRenderViz(true);
1336
+ setVizRef(visualizer);
1146
1337
  });
1147
- setVizRef(visualizer);
1148
1338
  }, []);
1149
1339
  useEffect(() => {
1150
1340
  if (!data || data.length === 0)
@@ -1167,8 +1357,8 @@ function reset(iframe, payloads, onSuccess) {
1167
1357
  targetHeight: docHeight,
1168
1358
  iframe: iframe,
1169
1359
  onSuccess: (data) => {
1170
- onSuccess(data.height);
1171
1360
  iframe.height = `${data.height}px`;
1361
+ onSuccess(data.height);
1172
1362
  },
1173
1363
  });
1174
1364
  viewportFixer.recalculate();
@@ -1357,30 +1547,64 @@ const useContentDimensions = ({ iframeRef, }) => {
1357
1547
  return { contentWidth };
1358
1548
  };
1359
1549
 
1360
- const useIframeHeight = (props) => {
1550
+ const useObserveIframeHeight = (props) => {
1361
1551
  const { iframeRef, setIframeHeight } = props;
1362
1552
  const isRenderViz = useHeatmapVizStore((state) => state.isRenderViz);
1363
1553
  const resizeObserverRef = useRef(null);
1364
1554
  const mutationObserverRef = useRef(null);
1555
+ const debounceTimerRef = useRef(null);
1556
+ const lastHeightRef = useRef(0);
1557
+ const animationFrameRef = useRef(null);
1365
1558
  const updateIframeHeight = useCallback(() => {
1366
1559
  const iframe = iframeRef.current;
1367
- if (!iframe)
1560
+ if (!iframe || !setIframeHeight)
1368
1561
  return;
1369
1562
  try {
1370
1563
  const iframeDocument = iframe.contentDocument;
1371
1564
  const iframeBody = iframeDocument?.body;
1372
- if (!iframeBody)
1565
+ const iframeDocumentElement = iframeDocument?.documentElement;
1566
+ if (!iframeBody || !iframeDocumentElement)
1373
1567
  return;
1374
- const bodyHeight = Math.max(iframeBody.scrollHeight, iframeBody.offsetHeight, iframeBody.clientHeight);
1375
- if (bodyHeight > 0) {
1376
- iframe.height = `${bodyHeight}px`;
1377
- setIframeHeight(bodyHeight);
1378
- }
1568
+ iframe.style.height = 'auto';
1569
+ requestAnimationFrame(() => {
1570
+ const bodyHeight = Math.max(iframeBody.scrollHeight, iframeBody.offsetHeight, iframeBody.clientHeight);
1571
+ const documentHeight = Math.max(iframeDocumentElement.scrollHeight, iframeDocumentElement.offsetHeight, iframeDocumentElement.clientHeight);
1572
+ const actualHeight = Math.max(bodyHeight, documentHeight);
1573
+ if (actualHeight > 0) {
1574
+ lastHeightRef.current = actualHeight;
1575
+ iframe.height = `${actualHeight}px`;
1576
+ iframe.style.height = `${actualHeight}px`;
1577
+ setIframeHeight(actualHeight);
1578
+ }
1579
+ });
1379
1580
  }
1380
1581
  catch (error) {
1381
1582
  console.warn('Cannot measure iframe content:', error);
1382
1583
  }
1383
1584
  }, [iframeRef, setIframeHeight]);
1585
+ const debouncedUpdate = useCallback(() => {
1586
+ // Cancel pending updates
1587
+ if (debounceTimerRef.current) {
1588
+ clearTimeout(debounceTimerRef.current);
1589
+ }
1590
+ if (animationFrameRef.current) {
1591
+ cancelAnimationFrame(animationFrameRef.current);
1592
+ }
1593
+ debounceTimerRef.current = setTimeout(() => {
1594
+ animationFrameRef.current = requestAnimationFrame(() => {
1595
+ updateIframeHeight();
1596
+ });
1597
+ }, 50);
1598
+ }, [updateIframeHeight]);
1599
+ // Immediate update không debounce (cho ResizeObserver)
1600
+ const immediateUpdate = useCallback(() => {
1601
+ if (animationFrameRef.current) {
1602
+ cancelAnimationFrame(animationFrameRef.current);
1603
+ }
1604
+ animationFrameRef.current = requestAnimationFrame(() => {
1605
+ updateIframeHeight();
1606
+ });
1607
+ }, [updateIframeHeight]);
1384
1608
  useEffect(() => {
1385
1609
  const iframe = iframeRef.current;
1386
1610
  if (!iframe || !isRenderViz)
@@ -1398,22 +1622,24 @@ const useIframeHeight = (props) => {
1398
1622
  if (mutationObserverRef.current) {
1399
1623
  mutationObserverRef.current.disconnect();
1400
1624
  }
1401
- // ResizeObserver for size changes
1402
1625
  if (typeof window.ResizeObserver !== 'undefined') {
1403
- resizeObserverRef.current = new ResizeObserver(updateIframeHeight);
1626
+ resizeObserverRef.current = new ResizeObserver(immediateUpdate);
1404
1627
  resizeObserverRef.current.observe(iframeBody);
1628
+ const iframeDocumentElement = iframeDocument?.documentElement;
1629
+ if (iframeDocumentElement) {
1630
+ resizeObserverRef.current.observe(iframeDocumentElement);
1631
+ }
1405
1632
  }
1406
- // MutationObserver for DOM changes
1407
1633
  if (typeof window.MutationObserver !== 'undefined') {
1408
- mutationObserverRef.current = new MutationObserver(updateIframeHeight);
1634
+ mutationObserverRef.current = new MutationObserver(immediateUpdate);
1409
1635
  mutationObserverRef.current.observe(iframeBody, {
1410
1636
  childList: true,
1411
1637
  subtree: true,
1412
1638
  attributes: true,
1413
- characterData: true,
1639
+ attributeFilter: ['style', 'class'],
1640
+ characterData: false,
1414
1641
  });
1415
1642
  }
1416
- // Initial measurement
1417
1643
  updateIframeHeight();
1418
1644
  }
1419
1645
  catch (error) {
@@ -1427,15 +1653,23 @@ const useIframeHeight = (props) => {
1427
1653
  iframe.addEventListener('load', setupObservers, { once: true });
1428
1654
  }
1429
1655
  return () => {
1656
+ // Cleanup observers
1430
1657
  if (resizeObserverRef.current) {
1431
1658
  resizeObserverRef.current.disconnect();
1432
1659
  }
1433
1660
  if (mutationObserverRef.current) {
1434
1661
  mutationObserverRef.current.disconnect();
1435
1662
  }
1663
+ // Cleanup timers
1664
+ if (debounceTimerRef.current) {
1665
+ clearTimeout(debounceTimerRef.current);
1666
+ }
1667
+ if (animationFrameRef.current) {
1668
+ cancelAnimationFrame(animationFrameRef.current);
1669
+ }
1436
1670
  iframe.removeEventListener('load', setupObservers);
1437
1671
  };
1438
- }, [iframeRef, isRenderViz, updateIframeHeight]);
1672
+ }, [iframeRef, isRenderViz, updateIframeHeight, debouncedUpdate, immediateUpdate]);
1439
1673
  return {};
1440
1674
  };
1441
1675
 
@@ -1481,16 +1715,18 @@ const useHeatmapScale = (props) => {
1481
1715
  // 2. Get content dimensions from config
1482
1716
  const { contentWidth } = useContentDimensions({ iframeRef });
1483
1717
  // 3. Observe iframe height (now reacts to width changes)
1484
- useIframeHeight({ iframeRef, setIframeHeight });
1718
+ useObserveIframeHeight({ iframeRef, setIframeHeight });
1485
1719
  // 4. Calculate scale
1486
1720
  const { scale } = useScaleCalculation({ containerWidth, contentWidth });
1487
1721
  // 5. Setup scroll sync
1488
1722
  const { handleScroll } = useScrollSync({ iframeRef });
1723
+ const scaledHeight = iframeHeight * scale;
1724
+ const scaledWidth = contentWidth * scale;
1489
1725
  return {
1490
1726
  containerWidth,
1491
1727
  containerHeight,
1492
- scaledWidth: contentWidth * scale,
1493
- scaledHeight: iframeHeight * scale,
1728
+ scaledWidth,
1729
+ scaledHeight,
1494
1730
  handleScroll,
1495
1731
  };
1496
1732
  };
@@ -1650,35 +1886,159 @@ const VizContainer = ({ children, setWrapperHeight }) => {
1650
1886
  const useClickmap = () => {
1651
1887
  const [isInitialized, setIsInitialized] = useState(false);
1652
1888
  const clickmap = useHeatmapDataStore((state) => state.clickmap);
1653
- const vizRef = useHeatmapVizStore((state) => state.vizRef);
1654
- useEffect(() => {
1889
+ const vizRef = useHeatmapSingleStore((state) => state.vizRef);
1890
+ const start = useCallback(() => {
1655
1891
  if (isInitialized)
1656
1892
  return;
1657
1893
  if (!vizRef || !clickmap || clickmap.length === 0)
1658
1894
  return;
1659
- vizRef.clearmap();
1660
- vizRef?.clickmap(clickmap);
1661
- setIsInitialized(true);
1895
+ try {
1896
+ vizRef?.clearmap?.();
1897
+ vizRef?.clickmap?.(clickmap);
1898
+ setIsInitialized(true);
1899
+ }
1900
+ catch (error) {
1901
+ console.error(`🚀 🐥 ~ useClickmap ~ error:`, error);
1902
+ }
1662
1903
  }, [vizRef, clickmap]);
1663
- return {};
1904
+ return { start };
1664
1905
  };
1665
1906
 
1907
+ const DATA_SCROLLMAP = [
1908
+ {
1909
+ scrollReachY: 5,
1910
+ cumulativeSum: 0,
1911
+ percUsers: 0,
1912
+ },
1913
+ {
1914
+ scrollReachY: 10,
1915
+ cumulativeSum: 0,
1916
+ percUsers: 0,
1917
+ },
1918
+ {
1919
+ scrollReachY: 15,
1920
+ cumulativeSum: 0,
1921
+ percUsers: 0,
1922
+ },
1923
+ {
1924
+ scrollReachY: 20,
1925
+ cumulativeSum: 0,
1926
+ percUsers: 0,
1927
+ },
1928
+ {
1929
+ scrollReachY: 25,
1930
+ cumulativeSum: 0,
1931
+ percUsers: 0,
1932
+ },
1933
+ {
1934
+ scrollReachY: 30,
1935
+ cumulativeSum: 0,
1936
+ percUsers: 0,
1937
+ },
1938
+ {
1939
+ scrollReachY: 35,
1940
+ cumulativeSum: 0,
1941
+ percUsers: 0,
1942
+ },
1943
+ {
1944
+ scrollReachY: 40,
1945
+ cumulativeSum: 0,
1946
+ percUsers: 0,
1947
+ },
1948
+ {
1949
+ scrollReachY: 45,
1950
+ cumulativeSum: 0,
1951
+ percUsers: 0,
1952
+ },
1953
+ {
1954
+ scrollReachY: 50,
1955
+ cumulativeSum: 0,
1956
+ percUsers: 0,
1957
+ },
1958
+ {
1959
+ scrollReachY: 55,
1960
+ cumulativeSum: 0,
1961
+ percUsers: 0,
1962
+ },
1963
+ {
1964
+ scrollReachY: 60,
1965
+ cumulativeSum: 0,
1966
+ percUsers: 0,
1967
+ },
1968
+ {
1969
+ scrollReachY: 65,
1970
+ cumulativeSum: 0,
1971
+ percUsers: 0,
1972
+ },
1973
+ {
1974
+ scrollReachY: 70,
1975
+ cumulativeSum: 0,
1976
+ percUsers: 0,
1977
+ },
1978
+ {
1979
+ scrollReachY: 75,
1980
+ cumulativeSum: 0,
1981
+ percUsers: 0,
1982
+ },
1983
+ {
1984
+ scrollReachY: 80,
1985
+ cumulativeSum: 0,
1986
+ percUsers: 0,
1987
+ },
1988
+ {
1989
+ scrollReachY: 85,
1990
+ cumulativeSum: 0,
1991
+ percUsers: 0,
1992
+ },
1993
+ {
1994
+ scrollReachY: 90,
1995
+ cumulativeSum: 0,
1996
+ percUsers: 0,
1997
+ },
1998
+ {
1999
+ scrollReachY: 95,
2000
+ cumulativeSum: 0,
2001
+ percUsers: 0,
2002
+ },
2003
+ {
2004
+ scrollReachY: 100,
2005
+ cumulativeSum: 0,
2006
+ percUsers: 0,
2007
+ },
2008
+ ];
1666
2009
  const useScrollmap = () => {
1667
- useHeatmapDataStore((state) => state.clickmap);
1668
- return {};
2010
+ const vizRef = useHeatmapSingleStore((state) => state.vizRef);
2011
+ const start = useCallback(() => {
2012
+ // if (isInitialized) return;
2013
+ const scrollmap = DATA_SCROLLMAP;
2014
+ if (!vizRef || !scrollmap || scrollmap.length === 0)
2015
+ return;
2016
+ try {
2017
+ vizRef?.clearmap?.();
2018
+ vizRef?.scrollmap?.(scrollmap);
2019
+ // setIsInitialized(true);
2020
+ }
2021
+ catch (error) {
2022
+ console.error(`🚀 🐥 ~ useScrollmap ~ error:`, error);
2023
+ }
2024
+ }, [vizRef]);
2025
+ return { start };
1669
2026
  };
1670
2027
 
1671
2028
  const useHeatmapVizCanvas = () => {
1672
2029
  const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
1673
- const heatmapRender = useMemo(() => {
2030
+ const { start: startClickmap } = useClickmap();
2031
+ const { start: startScrollmap } = useScrollmap();
2032
+ useEffect(() => {
1674
2033
  switch (heatmapType) {
1675
2034
  case IHeatmapType.Click:
1676
- return useClickmap;
2035
+ startClickmap();
2036
+ break;
1677
2037
  case IHeatmapType.Scroll:
1678
- return useScrollmap;
2038
+ startClickmap();
2039
+ break;
1679
2040
  }
1680
- }, [heatmapType]);
1681
- return heatmapRender?.();
2041
+ }, [heatmapType, startClickmap, startScrollmap]);
1682
2042
  };
1683
2043
 
1684
2044
  const CLICKED_ELEMENT_ID = 'gx-hm-clicked-element';
@@ -1741,7 +2101,7 @@ const ElementCallout = (props) => {
1741
2101
  window.removeEventListener('resize', handleUpdate);
1742
2102
  visualRef?.current?.removeEventListener('scroll', handleUpdate);
1743
2103
  };
1744
- }, [target, visualRef, hozOffset, alignment]);
2104
+ }, [element, target, visualRef, hozOffset, alignment]);
1745
2105
  const calloutContent = (jsx("div", { ref: calloutRef, className: `clarity-callout clarity-callout--${position.placement} clarity-callout--align-${position.horizontalAlign}`, style: {
1746
2106
  position: 'fixed',
1747
2107
  top: position.top,
@@ -1806,7 +2166,8 @@ const ELEMENT_CALLOUT = {
1806
2166
  alignment: 'left',
1807
2167
  };
1808
2168
  const HeatmapElements = (props) => {
1809
- const height = useHeatmapVizStore((state) => state.iframeHeight);
2169
+ const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
2170
+ const setHoveredElement = useHeatmapInteractionStore((state) => state.setHoveredElement);
1810
2171
  const { iframeRef, wrapperRef, visualRef, visualizer, iframeDimensions, isElementSidebarOpen, isVisible = true, areDefaultRanksHidden, isSecondary, ...rest } = props;
1811
2172
  const getRect = useHeatmapElementPosition({
1812
2173
  iframeRef,
@@ -1821,6 +2182,27 @@ const HeatmapElements = (props) => {
1821
2182
  iframeRef,
1822
2183
  getRect,
1823
2184
  });
2185
+ const heatmapInfo = useHeatmapDataStore((state) => state.dataInfo);
2186
+ useHeatmapMouseHandler({
2187
+ heatmapWrapperRef: wrapperRef,
2188
+ iframeRef,
2189
+ parentRef: visualRef,
2190
+ heatmapInfo: heatmapInfo || {},
2191
+ scaleRatio: 0.8, // 80% zoom
2192
+ onElementHover: (info) => {
2193
+ setHoveredElement({
2194
+ hash: info.hash,
2195
+ clicks: info.clicks,
2196
+ rank: info.rank,
2197
+ selector: info.selector,
2198
+ top: info.top,
2199
+ left: info.left,
2200
+ width: info.width,
2201
+ height: info.height,
2202
+ });
2203
+ console.log(`🚀 🐥 ~ HeatmapElements ~ info:`, info);
2204
+ },
2205
+ });
1824
2206
  useElementCalloutVisible({
1825
2207
  visualRef,
1826
2208
  getRect,
@@ -1836,14 +2218,21 @@ const HeatmapElements = (props) => {
1836
2218
  });
1837
2219
  if (!isVisible)
1838
2220
  return null;
1839
- return (jsxs("div", { onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave, className: "gx-hm-elements", style: { ...iframeDimensions, height }, children: [jsx(ElementMissing, { show: showMissingElement }), jsx(DefaultRankBadges, { getRect: getRect, hidden: areDefaultRanksHidden }), jsx(ElementOverlay, { type: "clicked", element: clickedElement, isSecondary: isSecondary }), jsx(ElementOverlay, { type: "hovered", element: hoveredElement, isSecondary: isSecondary, onClick: handleClick }), hoveredElement?.hash !== clickedElement?.hash && hoveredElement && (jsx(ElementCallout, { element: hoveredElement, target: `#${HOVERED_ELEMENT_ID}`, visualRef: visualRef, ...ELEMENT_CALLOUT })), shouldShowCallout && clickedElement && (jsx(ElementCallout, { element: clickedElement, target: `#${CLICKED_ELEMENT_ID}`, visualRef: visualRef, ...ELEMENT_CALLOUT }))] }));
2221
+ return (jsxs("div", { onMouseMove: (event) => {
2222
+ handleMouseMove(event);
2223
+ // handleMouseMove2(event as any);
2224
+ }, onMouseLeave: handleMouseLeave, className: "gx-hm-elements", style: { ...iframeDimensions, height: `${iframeHeight}px` }, children: [jsx(ElementMissing, { show: showMissingElement }), jsx(DefaultRankBadges, { getRect: getRect, hidden: areDefaultRanksHidden }), jsx(ElementOverlay, { type: "clicked", element: clickedElement, isSecondary: isSecondary }), jsx(ElementOverlay, { type: "hovered", element: hoveredElement, isSecondary: isSecondary, onClick: handleClick }), hoveredElement?.hash !== clickedElement?.hash && hoveredElement && (jsx(ElementCallout, { element: hoveredElement, target: `#${HOVERED_ELEMENT_ID}`, visualRef: visualRef, ...ELEMENT_CALLOUT })), shouldShowCallout && clickedElement && (jsx(ElementCallout, { element: clickedElement, target: `#${CLICKED_ELEMENT_ID}`, visualRef: visualRef, ...ELEMENT_CALLOUT }))] }));
1840
2225
  };
1841
2226
 
1842
2227
  const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
1843
2228
  const heatmapInfo = useHeatmapDataStore((state) => state.dataInfo);
1844
2229
  const contentWidth = useHeatmapConfigStore((state) => state.width);
2230
+ const vizRef = useHeatmapSingleStore((state) => state.vizRef);
1845
2231
  const visualizer = {
1846
2232
  get: (hash) => {
2233
+ if (vizRef) {
2234
+ return vizRef.get(hash);
2235
+ }
1847
2236
  const doc = iframeRef.current?.contentDocument;
1848
2237
  if (!doc)
1849
2238
  return null;
@@ -1903,8 +2292,8 @@ const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHe
1903
2292
 
1904
2293
  const VizDomRenderer = ({ mode = 'heatmap' }) => {
1905
2294
  const width = useHeatmapConfigStore((state) => state.width);
1906
- const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
1907
- const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
2295
+ const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
2296
+ const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
1908
2297
  const setSelectedElement = useHeatmapInteractionStore((state) => state.setSelectedElement);
1909
2298
  const wrapperRef = useRef(null);
1910
2299
  const visualRef = useRef(null);
@@ -1914,7 +2303,6 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
1914
2303
  iframeRef,
1915
2304
  visualRef,
1916
2305
  iframeHeight,
1917
- setIframeHeight,
1918
2306
  });
1919
2307
  const contentWidth = width ?? 0;
1920
2308
  const onScroll = (e) => {
@@ -1929,7 +2317,7 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
1929
2317
  useEffect(() => {
1930
2318
  return cleanUp;
1931
2319
  }, []);
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" })] }));
2320
+ 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, scrolling: "no" })] }));
1933
2321
  };
1934
2322
 
1935
2323
  const VizLoading = () => {
@@ -1939,12 +2327,12 @@ const VizLoading = () => {
1939
2327
  const VizDomHeatmap = () => {
1940
2328
  const controls = useHeatmapControlStore((state) => state.controls);
1941
2329
  const isRendering = useHeatmapDataStore((state) => state.isRendering);
1942
- const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
1943
- const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
1944
- const setVizRef = useHeatmapVizStore((state) => state.setVizRef);
2330
+ const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
2331
+ const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
2332
+ const setVizRef = useHeatmapSingleStore((state) => state.setVizRef);
1945
2333
  useEffect(() => {
1946
2334
  return () => {
1947
- setVizRef(undefined);
2335
+ setVizRef(null);
1948
2336
  setIframeHeight(0);
1949
2337
  };
1950
2338
  }, []);
@@ -1959,7 +2347,7 @@ const VizLiveRenderer = () => {
1959
2347
  const setIframeHeight = useHeatmapLiveStore((state) => state.setIframeHeight);
1960
2348
  const visualRef = useRef(null);
1961
2349
  const wrapperRef = useRef(null);
1962
- const { iframeRef } = useIframeRender();
2350
+ const { iframeRef } = useVizLiveRender();
1963
2351
  const { scaledHeight, handleScroll } = useHeatmapScale({
1964
2352
  wrapperRef,
1965
2353
  iframeRef,
@@ -1971,13 +2359,15 @@ const VizLiveRenderer = () => {
1971
2359
  const scrollTop = e.currentTarget.scrollTop;
1972
2360
  handleScroll(scrollTop);
1973
2361
  };
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" }) }));
2362
+ return (jsx(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, iframeHeight: iframeHeight, onScroll: onScroll, children: jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: contentWidth,
2363
+ // height={iframeHeight}
2364
+ scrolling: "no", sandbox: "allow-scripts allow-same-origin" }) }));
1975
2365
  };
1976
2366
 
1977
2367
  const VizLiveHeatmap = () => {
1978
2368
  const controls = useHeatmapControlStore((state) => state.controls);
1979
2369
  const isRendering = useHeatmapDataStore((state) => state.isRendering);
1980
- const iframeHeight = useHeatmapVizStore((state) => state.iframeHeight);
2370
+ const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
1981
2371
  const wrapperHeight = useHeatmapLiveStore((state) => state.wrapperHeight);
1982
2372
  const setWrapperHeight = useHeatmapLiveStore((state) => state.setWrapperHeight);
1983
2373
  const reset = useHeatmapLiveStore((state) => state.reset);
@@ -2052,4 +2442,4 @@ const HeatmapLayout = ({ data, clickmap, controls, dataInfo, }) => {
2052
2442
  }
2053
2443
  };
2054
2444
 
2055
- export { GraphView, HeatmapLayout, IHeatmapType, useHeatmapConfigStore, useHeatmapDataStore, useHeatmapInteractionStore, useHeatmapLiveStore };
2445
+ export { GraphView, HeatmapLayout, IHeatmapType, useHeatmapConfigStore, useHeatmapDataStore, useHeatmapInteractionStore, useHeatmapLiveStore, useHeatmapVizStore };