@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.
- package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/esm/components/VizElement/HeatmapElements.d.ts.map +1 -1
- package/dist/esm/components/VizElement/VizElements.d.ts.map +1 -1
- package/dist/esm/components/VizLive/VizLiveRenderer.d.ts.map +1 -1
- package/dist/esm/configs/style.d.ts +2 -0
- package/dist/esm/configs/style.d.ts.map +1 -1
- package/dist/esm/helpers/viewport-fixer.d.ts.map +1 -1
- package/dist/esm/hooks/vix-elements/useHeatmapMouseHandler.d.ts +34 -0
- package/dist/esm/hooks/vix-elements/useHeatmapMouseHandler.d.ts.map +1 -0
- package/dist/esm/hooks/vix-elements/useHoveredElement.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useClickmap.d.ts +3 -1
- package/dist/esm/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -1
- package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts +3 -1
- package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-live/index.d.ts +1 -1
- package/dist/esm/hooks/viz-live/{useIframeMessage.d.ts → useVizLiveIframeMsg.d.ts} +2 -10
- package/dist/esm/hooks/viz-live/useVizLiveIframeMsg.d.ts.map +1 -0
- package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts +4 -0
- package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts.map +1 -0
- package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useContainerDimensions.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts +1 -1
- package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts +10 -0
- package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts.map +1 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +476 -86
- package/dist/esm/index.mjs +476 -86
- package/dist/esm/stores/index.d.ts +1 -0
- package/dist/esm/stores/index.d.ts.map +1 -1
- package/dist/esm/stores/interaction.d.ts.map +1 -1
- package/dist/esm/stores/mode-live.d.ts +4 -0
- package/dist/esm/stores/mode-live.d.ts.map +1 -1
- package/dist/esm/stores/mode-single.d.ts +9 -0
- package/dist/esm/stores/mode-single.d.ts.map +1 -0
- package/dist/esm/stores/viz.d.ts +0 -4
- package/dist/esm/stores/viz.d.ts.map +1 -1
- package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/umd/components/VizElement/HeatmapElements.d.ts.map +1 -1
- package/dist/umd/components/VizElement/VizElements.d.ts.map +1 -1
- package/dist/umd/components/VizLive/VizLiveRenderer.d.ts.map +1 -1
- package/dist/umd/configs/style.d.ts +2 -0
- package/dist/umd/configs/style.d.ts.map +1 -1
- package/dist/umd/helpers/viewport-fixer.d.ts.map +1 -1
- package/dist/umd/hooks/vix-elements/useHeatmapMouseHandler.d.ts +34 -0
- package/dist/umd/hooks/vix-elements/useHeatmapMouseHandler.d.ts.map +1 -0
- package/dist/umd/hooks/vix-elements/useHoveredElement.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useClickmap.d.ts +3 -1
- package/dist/umd/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -1
- package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts +3 -1
- package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-live/index.d.ts +1 -1
- package/dist/umd/hooks/viz-live/{useIframeMessage.d.ts → useVizLiveIframeMsg.d.ts} +2 -10
- package/dist/umd/hooks/viz-live/useVizLiveIframeMsg.d.ts.map +1 -0
- package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts +4 -0
- package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts.map +1 -0
- package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useContainerDimensions.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts +1 -1
- package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts +10 -0
- package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts.map +1 -0
- package/dist/umd/index.d.ts +1 -1
- package/dist/umd/index.d.ts.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/stores/index.d.ts +1 -0
- package/dist/umd/stores/index.d.ts.map +1 -1
- package/dist/umd/stores/interaction.d.ts.map +1 -1
- package/dist/umd/stores/mode-live.d.ts +4 -0
- package/dist/umd/stores/mode-live.d.ts.map +1 -1
- package/dist/umd/stores/mode-single.d.ts +9 -0
- package/dist/umd/stores/mode-single.d.ts.map +1 -0
- package/dist/umd/stores/viz.d.ts +0 -4
- package/dist/umd/stores/viz.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/esm/hooks/viz-live/useIframeMessage.d.ts.map +0 -1
- package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts +0 -10
- package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts.map +0 -1
- package/dist/umd/hooks/viz-live/useIframeMessage.d.ts.map +0 -1
- package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts +0 -10
- package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts.map +0 -1
package/dist/esm/index.js
CHANGED
|
@@ -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 =
|
|
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
|
|
1217
|
+
function useVizLiveIframeMsg(options = {}) {
|
|
1020
1218
|
const { trustedOrigins = [], onMessage } = options;
|
|
1021
|
-
const
|
|
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
|
|
1048
|
-
if (
|
|
1049
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
1304
|
+
function reset$1(iframe, rect, onSuccess) {
|
|
1115
1305
|
const viewportFixer = initViewportFixer({
|
|
1116
|
-
targetWidth:
|
|
1117
|
-
targetHeight:
|
|
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 =
|
|
1321
|
+
const setVizRef = useHeatmapSingleStore((state) => state.setVizRef);
|
|
1131
1322
|
const setIsRenderViz = useHeatmapVizStore((state) => state.setIsRenderViz);
|
|
1132
|
-
const 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
|
|
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
|
-
|
|
1565
|
+
const iframeDocumentElement = iframeDocument?.documentElement;
|
|
1566
|
+
if (!iframeBody || !iframeDocumentElement)
|
|
1373
1567
|
return;
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1493
|
-
scaledHeight
|
|
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 =
|
|
1654
|
-
|
|
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
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
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
|
-
|
|
1668
|
-
|
|
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
|
|
2030
|
+
const { start: startClickmap } = useClickmap();
|
|
2031
|
+
const { start: startScrollmap } = useScrollmap();
|
|
2032
|
+
useEffect(() => {
|
|
1674
2033
|
switch (heatmapType) {
|
|
1675
2034
|
case IHeatmapType.Click:
|
|
1676
|
-
|
|
2035
|
+
startClickmap();
|
|
2036
|
+
break;
|
|
1677
2037
|
case IHeatmapType.Scroll:
|
|
1678
|
-
|
|
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
|
|
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:
|
|
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 =
|
|
1907
|
-
const 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,
|
|
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 =
|
|
1943
|
-
const setIframeHeight =
|
|
1944
|
-
const 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(
|
|
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 } =
|
|
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,
|
|
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 =
|
|
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 };
|