@gemx-dev/heatmap-react 3.5.79 → 3.5.81
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/Layout/HeatmapLayout.d.ts +1 -0
- package/dist/esm/components/Layout/HeatmapLayout.d.ts.map +1 -1
- package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/esm/components/VizScrollmap/AverageFold.d.ts +8 -0
- package/dist/esm/components/VizScrollmap/AverageFold.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/HoverZones.d.ts +1 -1
- package/dist/esm/components/VizScrollmap/HoverZones.d.ts.map +1 -1
- package/dist/esm/components/VizScrollmap/MarkerLine.d.ts +12 -0
- package/dist/esm/components/VizScrollmap/MarkerLine.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/Minimap.d.ts +8 -0
- package/dist/esm/components/VizScrollmap/Minimap.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollMarkers.d.ts +9 -0
- package/dist/esm/components/VizScrollmap/ScrollMarkers.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollOverlay.d.ts +8 -0
- package/dist/esm/components/VizScrollmap/ScrollOverlay.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/VizScrollMap.d.ts +4 -2
- package/dist/esm/components/VizScrollmap/VizScrollMap.d.ts.map +1 -1
- package/dist/esm/components/VizScrollmap/index.d.ts +1 -1
- package/dist/esm/components/VizScrollmap/index.d.ts.map +1 -1
- package/dist/esm/hooks/register/useRegisterHeatmap.d.ts +2 -1
- package/dist/esm/hooks/register/useRegisterHeatmap.d.ts.map +1 -1
- package/dist/esm/hooks/view-context/useHeatmapClickContext.d.ts +0 -13
- package/dist/esm/hooks/view-context/useHeatmapClickContext.d.ts.map +1 -1
- package/dist/esm/hooks/view-context/useHeatmapDataContext.d.ts +2 -0
- package/dist/esm/hooks/view-context/useHeatmapDataContext.d.ts.map +1 -1
- package/dist/esm/hooks/view-context/useHeatmapScrollContext.d.ts +2 -0
- package/dist/esm/hooks/view-context/useHeatmapScrollContext.d.ts.map +1 -1
- package/dist/esm/hooks/view-context/useHeatmapVizRectContext.d.ts +3 -3
- package/dist/esm/hooks/view-context/useHeatmapVizRectContext.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useAttentionMap.d.ts +9 -0
- package/dist/esm/hooks/viz-canvas/useAttentionMap.d.ts.map +1 -0
- package/dist/esm/hooks/viz-canvas/useHeatmapCanvas.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scroll/index.d.ts +1 -0
- package/dist/esm/hooks/viz-scroll/index.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scroll/useHeatmapScroll.d.ts +7 -0
- package/dist/esm/hooks/viz-scroll/useHeatmapScroll.d.ts.map +1 -0
- package/dist/esm/hooks/viz-scroll/useScrollmapZones.d.ts +1 -1
- package/dist/esm/hooks/viz-scroll/useScrollmapZones.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scroll/useZonePositions.d.ts +1 -1
- package/dist/esm/hooks/viz-scroll/useZonePositions.d.ts.map +1 -1
- package/dist/esm/index.js +382 -115
- package/dist/esm/index.mjs +382 -115
- package/dist/esm/libs/AttentionMapRenderer.d.ts +32 -0
- package/dist/esm/libs/AttentionMapRenderer.d.ts.map +1 -0
- package/dist/esm/libs/ClickHeatmapRenderer.d.ts +30 -0
- package/dist/esm/libs/ClickHeatmapRenderer.d.ts.map +1 -0
- package/dist/esm/libs/GXVisualizer.d.ts +24 -0
- package/dist/esm/libs/GXVisualizer.d.ts.map +1 -0
- package/dist/esm/libs/ScrollHeatmapRenderer.d.ts +17 -0
- package/dist/esm/libs/ScrollHeatmapRenderer.d.ts.map +1 -0
- package/dist/esm/libs/index.d.ts +4 -0
- package/dist/esm/libs/index.d.ts.map +1 -0
- package/dist/esm/libs/types.d.ts +10 -0
- package/dist/esm/libs/types.d.ts.map +1 -0
- package/dist/esm/stores/data.d.ts +2 -0
- package/dist/esm/stores/data.d.ts.map +1 -1
- package/dist/esm/stores/mode-single.d.ts +3 -3
- package/dist/esm/stores/mode-single.d.ts.map +1 -1
- package/dist/esm/stores/viz-scroll.d.ts +2 -0
- package/dist/esm/stores/viz-scroll.d.ts.map +1 -1
- package/dist/esm/types/heatmap-ref.d.ts +6 -0
- package/dist/esm/types/heatmap-ref.d.ts.map +1 -0
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/style.css +2 -1
- package/dist/umd/components/Layout/HeatmapLayout.d.ts +1 -0
- package/dist/umd/components/Layout/HeatmapLayout.d.ts.map +1 -1
- package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/umd/components/VizScrollmap/AverageFold.d.ts +8 -0
- package/dist/umd/components/VizScrollmap/AverageFold.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/HoverZones.d.ts +1 -1
- package/dist/umd/components/VizScrollmap/HoverZones.d.ts.map +1 -1
- package/dist/umd/components/VizScrollmap/MarkerLine.d.ts +12 -0
- package/dist/umd/components/VizScrollmap/MarkerLine.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/Minimap.d.ts +8 -0
- package/dist/umd/components/VizScrollmap/Minimap.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollMarkers.d.ts +9 -0
- package/dist/umd/components/VizScrollmap/ScrollMarkers.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollOverlay.d.ts +8 -0
- package/dist/umd/components/VizScrollmap/ScrollOverlay.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/VizScrollMap.d.ts +4 -2
- package/dist/umd/components/VizScrollmap/VizScrollMap.d.ts.map +1 -1
- package/dist/umd/components/VizScrollmap/index.d.ts +1 -1
- package/dist/umd/components/VizScrollmap/index.d.ts.map +1 -1
- package/dist/umd/hooks/register/useRegisterHeatmap.d.ts +2 -1
- package/dist/umd/hooks/register/useRegisterHeatmap.d.ts.map +1 -1
- package/dist/umd/hooks/view-context/useHeatmapClickContext.d.ts +0 -13
- package/dist/umd/hooks/view-context/useHeatmapClickContext.d.ts.map +1 -1
- package/dist/umd/hooks/view-context/useHeatmapDataContext.d.ts +2 -0
- package/dist/umd/hooks/view-context/useHeatmapDataContext.d.ts.map +1 -1
- package/dist/umd/hooks/view-context/useHeatmapScrollContext.d.ts +2 -0
- package/dist/umd/hooks/view-context/useHeatmapScrollContext.d.ts.map +1 -1
- package/dist/umd/hooks/view-context/useHeatmapVizRectContext.d.ts +3 -3
- package/dist/umd/hooks/view-context/useHeatmapVizRectContext.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useAttentionMap.d.ts +9 -0
- package/dist/umd/hooks/viz-canvas/useAttentionMap.d.ts.map +1 -0
- package/dist/umd/hooks/viz-canvas/useHeatmapCanvas.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scroll/index.d.ts +1 -0
- package/dist/umd/hooks/viz-scroll/index.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scroll/useHeatmapScroll.d.ts +7 -0
- package/dist/umd/hooks/viz-scroll/useHeatmapScroll.d.ts.map +1 -0
- package/dist/umd/hooks/viz-scroll/useScrollmapZones.d.ts +1 -1
- package/dist/umd/hooks/viz-scroll/useScrollmapZones.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scroll/useZonePositions.d.ts +1 -1
- package/dist/umd/hooks/viz-scroll/useZonePositions.d.ts.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/libs/AttentionMapRenderer.d.ts +32 -0
- package/dist/umd/libs/AttentionMapRenderer.d.ts.map +1 -0
- package/dist/umd/libs/ClickHeatmapRenderer.d.ts +30 -0
- package/dist/umd/libs/ClickHeatmapRenderer.d.ts.map +1 -0
- package/dist/umd/libs/GXVisualizer.d.ts +24 -0
- package/dist/umd/libs/GXVisualizer.d.ts.map +1 -0
- package/dist/umd/libs/ScrollHeatmapRenderer.d.ts +17 -0
- package/dist/umd/libs/ScrollHeatmapRenderer.d.ts.map +1 -0
- package/dist/umd/libs/index.d.ts +4 -0
- package/dist/umd/libs/index.d.ts.map +1 -0
- package/dist/umd/libs/types.d.ts +10 -0
- package/dist/umd/libs/types.d.ts.map +1 -0
- package/dist/umd/stores/data.d.ts +2 -0
- package/dist/umd/stores/data.d.ts.map +1 -1
- package/dist/umd/stores/mode-single.d.ts +3 -3
- package/dist/umd/stores/mode-single.d.ts.map +1 -1
- package/dist/umd/stores/viz-scroll.d.ts +2 -0
- package/dist/umd/stores/viz-scroll.d.ts.map +1 -1
- package/dist/umd/types/heatmap-ref.d.ts +6 -0
- package/dist/umd/types/heatmap-ref.d.ts.map +1 -0
- package/dist/umd/types/index.d.ts +1 -0
- package/dist/umd/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/esm/components/VizScrollmap/AverageFoldLine.d.ts +0 -8
- package/dist/esm/components/VizScrollmap/AverageFoldLine.d.ts.map +0 -1
- package/dist/esm/components/VizScrollmap/ScrollMapMinimap.d.ts +0 -8
- package/dist/esm/components/VizScrollmap/ScrollMapMinimap.d.ts.map +0 -1
- package/dist/esm/components/VizScrollmap/ScrollMapOverlay.d.ts +0 -7
- package/dist/esm/components/VizScrollmap/ScrollMapOverlay.d.ts.map +0 -1
- package/dist/esm/components/VizScrollmap/ScrollmapMarker.d.ts +0 -7
- package/dist/esm/components/VizScrollmap/ScrollmapMarker.d.ts.map +0 -1
- package/dist/esm/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts +0 -4
- package/dist/esm/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts.map +0 -1
- package/dist/esm/components/VizScrollmapV2/index.d.ts +0 -2
- package/dist/esm/components/VizScrollmapV2/index.d.ts.map +0 -1
- package/dist/esm/components/VizScrollmapV2/scrollmap.types.d.ts +0 -18
- package/dist/esm/components/VizScrollmapV2/scrollmap.types.d.ts.map +0 -1
- package/dist/esm/components/VizScrollmapV2/useScrollmapOverlay.d.ts +0 -16
- package/dist/esm/components/VizScrollmapV2/useScrollmapOverlay.d.ts.map +0 -1
- package/dist/umd/components/VizScrollmap/AverageFoldLine.d.ts +0 -8
- package/dist/umd/components/VizScrollmap/AverageFoldLine.d.ts.map +0 -1
- package/dist/umd/components/VizScrollmap/ScrollMapMinimap.d.ts +0 -8
- package/dist/umd/components/VizScrollmap/ScrollMapMinimap.d.ts.map +0 -1
- package/dist/umd/components/VizScrollmap/ScrollMapOverlay.d.ts +0 -7
- package/dist/umd/components/VizScrollmap/ScrollMapOverlay.d.ts.map +0 -1
- package/dist/umd/components/VizScrollmap/ScrollmapMarker.d.ts +0 -7
- package/dist/umd/components/VizScrollmap/ScrollmapMarker.d.ts.map +0 -1
- package/dist/umd/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts +0 -4
- package/dist/umd/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts.map +0 -1
- package/dist/umd/components/VizScrollmapV2/index.d.ts +0 -2
- package/dist/umd/components/VizScrollmapV2/index.d.ts.map +0 -1
- package/dist/umd/components/VizScrollmapV2/scrollmap.types.d.ts +0 -18
- package/dist/umd/components/VizScrollmapV2/scrollmap.types.d.ts.map +0 -1
- package/dist/umd/components/VizScrollmapV2/useScrollmapOverlay.d.ts +0 -16
- package/dist/umd/components/VizScrollmapV2/useScrollmapOverlay.d.ts.map +0 -1
package/dist/esm/index.mjs
CHANGED
|
@@ -106,7 +106,7 @@ const getCompareViewId = (viewId) => {
|
|
|
106
106
|
return `compare-${viewId}`;
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
const Z_INDEX = {
|
|
109
|
+
const Z_INDEX$1 = {
|
|
110
110
|
ELEMENTS: 1000,
|
|
111
111
|
CALLOUT: 2000,
|
|
112
112
|
MINIMAP: 3000,
|
|
@@ -324,6 +324,7 @@ const useHeatmapDataStore = create()(subscribeWithSelector((set) => {
|
|
|
324
324
|
clickAreas: new Map([[DEFAULT_VIEW_ID, undefined]]),
|
|
325
325
|
dataInfo: new Map([[DEFAULT_VIEW_ID, undefined]]),
|
|
326
326
|
scrollmap: new Map([[DEFAULT_VIEW_ID, undefined]]),
|
|
327
|
+
attentionMap: new Map([[DEFAULT_VIEW_ID, undefined]]),
|
|
327
328
|
setClickAreas: (clickAreas, viewId = DEFAULT_VIEW_ID) => set((prev) => {
|
|
328
329
|
const newClickAreas = new Map(prev.clickAreas);
|
|
329
330
|
newClickAreas.set(viewId, clickAreas);
|
|
@@ -336,6 +337,11 @@ const useHeatmapDataStore = create()(subscribeWithSelector((set) => {
|
|
|
336
337
|
newClickAreas.set(viewId, filtered);
|
|
337
338
|
return { clickAreas: newClickAreas };
|
|
338
339
|
}),
|
|
340
|
+
setAttentionMap: (attentionMap, viewId = DEFAULT_VIEW_ID) => set((prev) => {
|
|
341
|
+
const newAttentionMap = new Map(prev.attentionMap);
|
|
342
|
+
newAttentionMap.set(viewId, attentionMap);
|
|
343
|
+
return { attentionMap: newAttentionMap };
|
|
344
|
+
}),
|
|
339
345
|
setDataInfo: (dataInfo, viewId = DEFAULT_VIEW_ID) => set((prev) => {
|
|
340
346
|
const newDataInfo = new Map(prev.dataInfo);
|
|
341
347
|
newDataInfo.set(viewId, dataInfo);
|
|
@@ -372,17 +378,20 @@ const useHeatmapDataStore = create()(subscribeWithSelector((set) => {
|
|
|
372
378
|
const newClickAreas = new Map(prev.clickAreas);
|
|
373
379
|
const newDataInfo = new Map(prev.dataInfo);
|
|
374
380
|
const newScrollmap = new Map(prev.scrollmap);
|
|
381
|
+
const newAttentionMap = new Map(prev.attentionMap);
|
|
375
382
|
newData.set(toViewId, prev.data.get(fromViewId));
|
|
376
383
|
newClickmap.set(toViewId, prev.clickmap.get(fromViewId));
|
|
377
384
|
newClickAreas.set(toViewId, prev.clickAreas.get(fromViewId));
|
|
378
385
|
newDataInfo.set(toViewId, prev.dataInfo.get(fromViewId));
|
|
379
386
|
newScrollmap.set(toViewId, prev.scrollmap.get(fromViewId));
|
|
387
|
+
newAttentionMap.set(toViewId, prev.attentionMap.get(fromViewId));
|
|
380
388
|
return {
|
|
381
389
|
data: newData,
|
|
382
390
|
clickmap: newClickmap,
|
|
383
391
|
clickAreas: newClickAreas,
|
|
384
392
|
dataInfo: newDataInfo,
|
|
385
393
|
scrollmap: newScrollmap,
|
|
394
|
+
attentionMap: newAttentionMap,
|
|
386
395
|
};
|
|
387
396
|
}),
|
|
388
397
|
clearView: (viewId) => set((prev) => {
|
|
@@ -391,17 +400,20 @@ const useHeatmapDataStore = create()(subscribeWithSelector((set) => {
|
|
|
391
400
|
const newClickAreas = new Map(prev.clickAreas);
|
|
392
401
|
const newDataInfo = new Map(prev.dataInfo);
|
|
393
402
|
const newScrollmap = new Map(prev.scrollmap);
|
|
403
|
+
const newAttentionMap = new Map(prev.attentionMap);
|
|
394
404
|
newData.delete(viewId);
|
|
395
405
|
newClickmap.delete(viewId);
|
|
396
406
|
newClickAreas.delete(viewId);
|
|
397
407
|
newDataInfo.delete(viewId);
|
|
398
408
|
newScrollmap.delete(viewId);
|
|
409
|
+
newAttentionMap.delete(viewId);
|
|
399
410
|
return {
|
|
400
411
|
data: newData,
|
|
401
412
|
clickmap: newClickmap,
|
|
402
413
|
clickAreas: newClickAreas,
|
|
403
414
|
dataInfo: newDataInfo,
|
|
404
415
|
scrollmap: newScrollmap,
|
|
416
|
+
attentionMap: newAttentionMap,
|
|
405
417
|
};
|
|
406
418
|
}),
|
|
407
419
|
resetAll: () => set({
|
|
@@ -410,6 +422,7 @@ const useHeatmapDataStore = create()(subscribeWithSelector((set) => {
|
|
|
410
422
|
clickAreas: new Map([[DEFAULT_VIEW_ID, undefined]]),
|
|
411
423
|
dataInfo: new Map([[DEFAULT_VIEW_ID, undefined]]),
|
|
412
424
|
scrollmap: new Map([[DEFAULT_VIEW_ID, undefined]]),
|
|
425
|
+
attentionMap: new Map([[DEFAULT_VIEW_ID, undefined]]),
|
|
413
426
|
}),
|
|
414
427
|
};
|
|
415
428
|
}));
|
|
@@ -864,6 +877,7 @@ const useHeatmapVizScrollStore = create()(subscribeWithSelector((set) => {
|
|
|
864
877
|
zones: new Map([[DEFAULT_VIEW_ID, []]]),
|
|
865
878
|
hoveredZone: new Map([[DEFAULT_VIEW_ID, null]]),
|
|
866
879
|
showMinimap: new Map([[DEFAULT_VIEW_ID, true]]),
|
|
880
|
+
selectedScrollY: new Map([[DEFAULT_VIEW_ID, null]]),
|
|
867
881
|
setZones: (zones, viewId = DEFAULT_VIEW_ID) => set((prev) => {
|
|
868
882
|
const newZones = new Map(prev.zones);
|
|
869
883
|
newZones.set(viewId, zones);
|
|
@@ -879,6 +893,11 @@ const useHeatmapVizScrollStore = create()(subscribeWithSelector((set) => {
|
|
|
879
893
|
newShowMinimap.set(viewId, showMinimap);
|
|
880
894
|
return { showMinimap: newShowMinimap };
|
|
881
895
|
}),
|
|
896
|
+
setSelectedScrollY: (selectedScrollY, viewId = DEFAULT_VIEW_ID) => set((prev) => {
|
|
897
|
+
const newSelectedScrollY = new Map(prev.selectedScrollY);
|
|
898
|
+
newSelectedScrollY.set(viewId, selectedScrollY);
|
|
899
|
+
return { selectedScrollY: newSelectedScrollY };
|
|
900
|
+
}),
|
|
882
901
|
copyView: (fromViewId, toViewId) => set((prev) => {
|
|
883
902
|
const newZones = new Map(prev.zones);
|
|
884
903
|
const newHoveredZone = new Map(prev.hoveredZone);
|
|
@@ -1130,26 +1149,7 @@ const useHeatmapAreaClickContext = createViewContextHook({
|
|
|
1130
1149
|
}),
|
|
1131
1150
|
});
|
|
1132
1151
|
|
|
1133
|
-
// ===========================
|
|
1134
|
-
// Constants
|
|
1135
|
-
// ===========================
|
|
1136
1152
|
const DEFAULT_STATE = { hideSidebar: false };
|
|
1137
|
-
// ===========================
|
|
1138
|
-
// Hook
|
|
1139
|
-
// ===========================
|
|
1140
|
-
/**
|
|
1141
|
-
* Hook to access heatmap click state and actions with optional selector
|
|
1142
|
-
*
|
|
1143
|
-
* @example
|
|
1144
|
-
* ```tsx
|
|
1145
|
-
* // Get everything
|
|
1146
|
-
* const { state, selectedElement, setSelectedElement } = useHeatmapClickContext();
|
|
1147
|
-
*
|
|
1148
|
-
* // Get only what you need (no unnecessary re-renders)
|
|
1149
|
-
* const setSelectedElement = useHeatmapClickContext(s => s.setSelectedElement);
|
|
1150
|
-
* const selectedElement = useHeatmapClickContext(s => s.selectedElement);
|
|
1151
|
-
* ```
|
|
1152
|
-
*/
|
|
1153
1153
|
const useHeatmapClickContext = createViewContextHook({
|
|
1154
1154
|
useStore: useHeatmapVizClickStore,
|
|
1155
1155
|
getState: (store, viewId) => ({
|
|
@@ -1187,6 +1187,7 @@ const useHeatmapDataContext = createViewContextHook({
|
|
|
1187
1187
|
clickmap: store.clickmap.get(viewId),
|
|
1188
1188
|
clickAreas: store.clickAreas.get(viewId),
|
|
1189
1189
|
scrollmap: store.scrollmap.get(viewId),
|
|
1190
|
+
attentionMap: store.attentionMap.get(viewId),
|
|
1190
1191
|
dataInfo: store.dataInfo.get(viewId),
|
|
1191
1192
|
}),
|
|
1192
1193
|
getActions: (store, viewId) => ({
|
|
@@ -1195,6 +1196,7 @@ const useHeatmapDataContext = createViewContextHook({
|
|
|
1195
1196
|
setClickAreas: (newClickAreas) => store.setClickAreas(newClickAreas, viewId),
|
|
1196
1197
|
setDataInfoByKey: (key, value) => store.setDataInfoByKey(key, value, viewId),
|
|
1197
1198
|
setScrollmap: (newScrollmap) => store.setScrollmap(newScrollmap, viewId),
|
|
1199
|
+
setAttentionMap: (newAttentionMap) => store.setAttentionMap(newAttentionMap, viewId),
|
|
1198
1200
|
setDataInfo: (newDataInfo) => store.setDataInfo(newDataInfo, viewId),
|
|
1199
1201
|
removeClickArea: (areaId) => store.removeClickArea(areaId, viewId),
|
|
1200
1202
|
clearView: (viewId) => store.clearView(viewId),
|
|
@@ -1218,11 +1220,13 @@ const useHeatmapScrollContext = createViewContextHook({
|
|
|
1218
1220
|
zones: store.zones.get(viewId) ?? [],
|
|
1219
1221
|
hoveredZone: store.hoveredZone.get(viewId) ?? null,
|
|
1220
1222
|
showMinimap: store.showMinimap.get(viewId) ?? true,
|
|
1223
|
+
selectedScrollY: store.selectedScrollY.get(viewId) ?? 0,
|
|
1221
1224
|
}),
|
|
1222
1225
|
getActions: (store, viewId) => ({
|
|
1223
1226
|
setZones: (zones) => store.setZones(zones, viewId),
|
|
1224
1227
|
setHoveredZone: (zone) => store.setHoveredZone(zone, viewId),
|
|
1225
1228
|
setShowMinimap: (value) => store.setShowMinimap(value, viewId),
|
|
1229
|
+
setSelectedScrollY: (value) => store.setSelectedScrollY(value, viewId),
|
|
1226
1230
|
}),
|
|
1227
1231
|
});
|
|
1228
1232
|
|
|
@@ -1446,10 +1450,11 @@ const useRegisterData = (data, dataInfo) => {
|
|
|
1446
1450
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
1447
1451
|
};
|
|
1448
1452
|
|
|
1449
|
-
const useRegisterHeatmap = ({ clickmap, scrollmap, clickAreas }) => {
|
|
1453
|
+
const useRegisterHeatmap = ({ clickmap, scrollmap, clickAreas, attentionMap }) => {
|
|
1450
1454
|
const setClickmap = useHeatmapDataContext((s) => s.setClickmap);
|
|
1451
1455
|
const setScrollmap = useHeatmapDataContext((s) => s.setScrollmap);
|
|
1452
1456
|
const setClickAreas = useHeatmapDataContext((s) => s.setClickAreas);
|
|
1457
|
+
const setAttentionMap = useHeatmapDataContext((s) => s.setAttentionMap);
|
|
1453
1458
|
const isRegistered = useRef(false);
|
|
1454
1459
|
useEffect(() => {
|
|
1455
1460
|
if (isRegistered.current)
|
|
@@ -1463,6 +1468,9 @@ const useRegisterHeatmap = ({ clickmap, scrollmap, clickAreas }) => {
|
|
|
1463
1468
|
if (scrollmap) {
|
|
1464
1469
|
setScrollmap(scrollmap);
|
|
1465
1470
|
}
|
|
1471
|
+
if (attentionMap) {
|
|
1472
|
+
setAttentionMap(attentionMap);
|
|
1473
|
+
}
|
|
1466
1474
|
isRegistered.current = true;
|
|
1467
1475
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
1468
1476
|
};
|
|
@@ -2404,7 +2412,7 @@ const getStyleFromCandidate = (candidate, widthScale) => {
|
|
|
2404
2412
|
return {
|
|
2405
2413
|
top,
|
|
2406
2414
|
left,
|
|
2407
|
-
zIndex: Z_INDEX.CALLOUT,
|
|
2415
|
+
zIndex: Z_INDEX$1.CALLOUT,
|
|
2408
2416
|
transform: `scale(${1 / widthScale})`, // TODO: remove this when we have a better way to handle the scale
|
|
2409
2417
|
transformOrigin: `${xTransformAlign} ${yTransformAlign}`,
|
|
2410
2418
|
};
|
|
@@ -4471,27 +4479,43 @@ const useClickmap = () => {
|
|
|
4471
4479
|
|
|
4472
4480
|
const useScrollmap = () => {
|
|
4473
4481
|
const vizRef = useHeatmapVizRectContext((s) => s.vizRef);
|
|
4482
|
+
const scrollType = useHeatmapSettingContext((s) => s.scrollType);
|
|
4474
4483
|
const scrollmap = useHeatmapDataContext((s) => s.scrollmap);
|
|
4484
|
+
const attentionMap = useHeatmapDataContext((s) => s.attentionMap);
|
|
4485
|
+
const dataMap = useMemo(() => {
|
|
4486
|
+
switch (scrollType) {
|
|
4487
|
+
case EScrollType.Depth:
|
|
4488
|
+
return scrollmap;
|
|
4489
|
+
case EScrollType.Attention:
|
|
4490
|
+
return attentionMap;
|
|
4491
|
+
case EScrollType.Revenue:
|
|
4492
|
+
return [];
|
|
4493
|
+
default:
|
|
4494
|
+
return scrollmap;
|
|
4495
|
+
}
|
|
4496
|
+
}, [scrollmap, attentionMap, scrollType]);
|
|
4475
4497
|
const start = useCallback(() => {
|
|
4476
|
-
if (!vizRef || !
|
|
4498
|
+
if (!vizRef || !dataMap || dataMap.length === 0)
|
|
4477
4499
|
return;
|
|
4478
4500
|
try {
|
|
4479
4501
|
vizRef?.clearmap?.();
|
|
4480
|
-
vizRef?.scrollmap?.(
|
|
4502
|
+
vizRef?.scrollmap?.(dataMap);
|
|
4481
4503
|
}
|
|
4482
4504
|
catch (error) {
|
|
4483
4505
|
logger$4.error(`🚀 🐥 ~ useScrollmap ~ error:`, error);
|
|
4484
4506
|
}
|
|
4485
|
-
}, [vizRef,
|
|
4507
|
+
}, [vizRef, dataMap]);
|
|
4486
4508
|
return { start };
|
|
4487
4509
|
};
|
|
4488
4510
|
|
|
4489
4511
|
const useHeatmapCanvas = () => {
|
|
4490
4512
|
const heatmapType = useHeatmapSettingContext((state) => state.heatmapType);
|
|
4491
4513
|
const clickMode = useHeatmapSettingContext((state) => state.clickMode);
|
|
4514
|
+
const scrollType = useHeatmapSettingContext((state) => state.scrollType);
|
|
4492
4515
|
const { start: startClickmap } = useClickmap();
|
|
4493
4516
|
const { start: startAreaClickmap } = useAreaClickmap();
|
|
4494
4517
|
const { start: startScrollmap } = useScrollmap();
|
|
4518
|
+
// const { start: startAttentionMap } = useAttentionMap();
|
|
4495
4519
|
useEffect(() => {
|
|
4496
4520
|
switch (heatmapType) {
|
|
4497
4521
|
case EHeatmapType.Click:
|
|
@@ -4506,7 +4530,7 @@ const useHeatmapCanvas = () => {
|
|
|
4506
4530
|
startScrollmap();
|
|
4507
4531
|
break;
|
|
4508
4532
|
}
|
|
4509
|
-
}, [heatmapType, clickMode, startClickmap, startAreaClickmap, startScrollmap]);
|
|
4533
|
+
}, [heatmapType, clickMode, startClickmap, startAreaClickmap, startScrollmap, scrollType]);
|
|
4510
4534
|
};
|
|
4511
4535
|
|
|
4512
4536
|
const scrollToElementIfNeeded = (visualRef, rect, scale, onScrollComplete) => {
|
|
@@ -6431,6 +6455,260 @@ function initIframeHelper$1(iframe, rect, onSuccess) {
|
|
|
6431
6455
|
enableNavigationBlocking();
|
|
6432
6456
|
}
|
|
6433
6457
|
|
|
6458
|
+
const CANVAS_ID = 'clarity-heatmap-canvas';
|
|
6459
|
+
const ATTENTION_HUES = [240, 210, 180, 150, 120, 90, 60, 30, 0];
|
|
6460
|
+
const CANVAS_MAX_HEIGHT = 65535;
|
|
6461
|
+
const Z_INDEX = 2147483647;
|
|
6462
|
+
const DEFAULT_IFRAME_ID = 'clarity-snapshot-heatmap-iframe';
|
|
6463
|
+
const SECONDARY_IFRAME_ID = 'clarity-snapshot-heatmap-iframe-secondary';
|
|
6464
|
+
const DEFAULT_VISUAL_DIV_ID = 'heatmapVisual';
|
|
6465
|
+
const SECONDARY_VISUAL_DIV_ID = 'heatmapVisual_sec';
|
|
6466
|
+
class AttentionMapRenderer {
|
|
6467
|
+
attentionData = null;
|
|
6468
|
+
attentionMapData = null;
|
|
6469
|
+
observer = null;
|
|
6470
|
+
visualizer = null;
|
|
6471
|
+
avgFold = 0;
|
|
6472
|
+
heatmapIframeId = DEFAULT_IFRAME_ID;
|
|
6473
|
+
heatmapVisualDivId = DEFAULT_VISUAL_DIV_ID;
|
|
6474
|
+
state;
|
|
6475
|
+
constructor(state) {
|
|
6476
|
+
this.state = state;
|
|
6477
|
+
}
|
|
6478
|
+
reset = () => {
|
|
6479
|
+
this.attentionData = null;
|
|
6480
|
+
this.attentionMapData = null;
|
|
6481
|
+
this.avgFold = 0;
|
|
6482
|
+
this.observer?.disconnect();
|
|
6483
|
+
this.observer = null;
|
|
6484
|
+
if (this.state?.window) {
|
|
6485
|
+
this.state.window.removeEventListener('resize', this.reRender, true);
|
|
6486
|
+
}
|
|
6487
|
+
};
|
|
6488
|
+
clear = () => {
|
|
6489
|
+
if (!this.state?.window)
|
|
6490
|
+
return;
|
|
6491
|
+
const win = this.state.window;
|
|
6492
|
+
const doc = win.document;
|
|
6493
|
+
const de = doc.documentElement;
|
|
6494
|
+
const canvas = doc.getElementById(CANVAS_ID);
|
|
6495
|
+
if (canvas) {
|
|
6496
|
+
canvas.width = de.clientWidth;
|
|
6497
|
+
canvas.height = de.clientHeight;
|
|
6498
|
+
canvas.style.left = `${win.pageXOffset}px`;
|
|
6499
|
+
canvas.style.top = `${win.pageYOffset}px`;
|
|
6500
|
+
canvas.getContext('2d')?.clearRect(0, 0, canvas.width, canvas.height);
|
|
6501
|
+
}
|
|
6502
|
+
this.reset();
|
|
6503
|
+
};
|
|
6504
|
+
attention = (attentionData, avgFold, visualizer, isSecondary = false) => {
|
|
6505
|
+
this.attentionData = attentionData ?? this.attentionData;
|
|
6506
|
+
this.visualizer = visualizer ?? this.visualizer;
|
|
6507
|
+
this.avgFold = avgFold ?? this.avgFold;
|
|
6508
|
+
if (isSecondary) {
|
|
6509
|
+
this.heatmapIframeId = SECONDARY_IFRAME_ID;
|
|
6510
|
+
this.heatmapVisualDivId = SECONDARY_VISUAL_DIV_ID;
|
|
6511
|
+
}
|
|
6512
|
+
return this.renderAttentionmap();
|
|
6513
|
+
};
|
|
6514
|
+
reRender = () => {
|
|
6515
|
+
const doc = this.state?.window?.document;
|
|
6516
|
+
if (!doc)
|
|
6517
|
+
return;
|
|
6518
|
+
const canvas = this.overlay();
|
|
6519
|
+
if (!canvas)
|
|
6520
|
+
return;
|
|
6521
|
+
const ctx = canvas.getContext('2d');
|
|
6522
|
+
const body = doc.body;
|
|
6523
|
+
const de = doc.documentElement;
|
|
6524
|
+
const contentHeight = Math.max(body.scrollHeight, body.offsetHeight, de.clientHeight, de.scrollHeight, de.offsetHeight);
|
|
6525
|
+
canvas.height = Math.min(contentHeight, CANVAS_MAX_HEIGHT);
|
|
6526
|
+
canvas.style.top = '0px';
|
|
6527
|
+
if (canvas.width <= 0 || canvas.height <= 0 || !this.attentionMapData)
|
|
6528
|
+
return;
|
|
6529
|
+
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
|
|
6530
|
+
for (let i = 0; i < 100; i++) {
|
|
6531
|
+
gradient.addColorStop(i / 100, `hsla(${ATTENTION_HUES[this.attentionMapData[i].colorIndex]}, 100%, 50%, 0.6)`);
|
|
6532
|
+
}
|
|
6533
|
+
ctx.fillStyle = gradient;
|
|
6534
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
6535
|
+
};
|
|
6536
|
+
renderAttentionmap = () => {
|
|
6537
|
+
const doc = this.state?.window?.document;
|
|
6538
|
+
if (!doc)
|
|
6539
|
+
return null;
|
|
6540
|
+
const canvas = this.overlay();
|
|
6541
|
+
if (!canvas)
|
|
6542
|
+
return null;
|
|
6543
|
+
const ctx = canvas.getContext('2d');
|
|
6544
|
+
const body = doc.body;
|
|
6545
|
+
const de = doc.documentElement;
|
|
6546
|
+
const contentHeight = Math.max(body.scrollHeight, body.offsetHeight, de.clientHeight, de.scrollHeight, de.offsetHeight);
|
|
6547
|
+
canvas.height = Math.min(contentHeight, CANVAS_MAX_HEIGHT);
|
|
6548
|
+
canvas.style.top = '0px';
|
|
6549
|
+
let iframeEl = document.getElementById(this.heatmapIframeId);
|
|
6550
|
+
if (!iframeEl) {
|
|
6551
|
+
iframeEl = document.getElementById('clarity-snapshot-iframe');
|
|
6552
|
+
}
|
|
6553
|
+
const visualDiv = document.getElementById(this.heatmapVisualDivId);
|
|
6554
|
+
const visualWidth = visualDiv?.clientWidth ?? 0;
|
|
6555
|
+
const visualHeight = visualDiv?.clientHeight ?? 0;
|
|
6556
|
+
const maxCumulativeTime = this.buildAggregatedData(doc, contentHeight, iframeEl);
|
|
6557
|
+
const colorStops = new Array(100);
|
|
6558
|
+
if (canvas.width > 0 && canvas.height > 0 && this.attentionMapData) {
|
|
6559
|
+
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
|
|
6560
|
+
for (const point of this.attentionMapData) {
|
|
6561
|
+
const timePercent = Math.floor((100 * point.cumulativeTime) / maxCumulativeTime);
|
|
6562
|
+
const colorIndex = timePercent <= 5 ? 0 : Math.min(Math.ceil(timePercent / 10), 8);
|
|
6563
|
+
if (point.scrollPos / 100 <= 1) {
|
|
6564
|
+
point.colorIndex = colorIndex;
|
|
6565
|
+
colorStops[point.scrollPos] = colorIndex;
|
|
6566
|
+
}
|
|
6567
|
+
}
|
|
6568
|
+
// Smooth the top portion based on the fold/viewport ratio
|
|
6569
|
+
const foldPixels = visualWidth >= visualHeight ? 0.15 * visualHeight : 0.2 * visualHeight;
|
|
6570
|
+
const smoothUntil = Math.min(Math.ceil((foldPixels / canvas.height) * 100), 98);
|
|
6571
|
+
for (let i = 0; i < smoothUntil; i++) {
|
|
6572
|
+
colorStops[i] = colorStops[smoothUntil + 1];
|
|
6573
|
+
this.attentionMapData[i].colorIndex = colorStops[smoothUntil + 1];
|
|
6574
|
+
this.attentionMapData[i].cumulativeTime = this.attentionMapData[smoothUntil + 1].cumulativeTime;
|
|
6575
|
+
}
|
|
6576
|
+
// Smooth isolated single-step outliers
|
|
6577
|
+
for (let i = 0; i < 100; i++) {
|
|
6578
|
+
let colorIndex = colorStops[i];
|
|
6579
|
+
if (i > 0 && i < 99) {
|
|
6580
|
+
const prev = colorStops[i - 1];
|
|
6581
|
+
if (prev === colorStops[i + 1] && colorIndex !== prev && Math.abs(colorIndex - prev) === 1) {
|
|
6582
|
+
colorIndex = prev;
|
|
6583
|
+
this.attentionMapData[i].colorIndex = colorIndex;
|
|
6584
|
+
}
|
|
6585
|
+
}
|
|
6586
|
+
gradient.addColorStop(i / 100, `hsla(${ATTENTION_HUES[colorIndex]}, 100%, 50%, 0.6)`);
|
|
6587
|
+
}
|
|
6588
|
+
ctx.fillStyle = gradient;
|
|
6589
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
6590
|
+
}
|
|
6591
|
+
return this.attentionMapData;
|
|
6592
|
+
};
|
|
6593
|
+
buildAggregatedData = (doc, contentHeight, iframeEl) => {
|
|
6594
|
+
const elementCache = new Map();
|
|
6595
|
+
this.attentionMapData = Array.from({ length: 100 }, (_, i) => ({
|
|
6596
|
+
scrollPos: i,
|
|
6597
|
+
cumulativeTime: 0,
|
|
6598
|
+
colorIndex: 0,
|
|
6599
|
+
}));
|
|
6600
|
+
let maxTime = 0;
|
|
6601
|
+
const htmlEl = iframeEl?.contentDocument?.getElementsByTagName('HTML')?.[0] ??
|
|
6602
|
+
iframeEl?.ownerDocument?.getElementsByTagName('HTML')?.[0];
|
|
6603
|
+
const scrollTop = htmlEl?.scrollTop ?? 0;
|
|
6604
|
+
const foldPercent = ((this.avgFold ?? 0) / contentHeight) * 100;
|
|
6605
|
+
for (const dataPoint of this.attentionData ?? []) {
|
|
6606
|
+
const { startElementHash, endElementHash, timeSpent } = dataPoint;
|
|
6607
|
+
if (!startElementHash || !endElementHash)
|
|
6608
|
+
continue;
|
|
6609
|
+
let startY = elementCache.get(startElementHash);
|
|
6610
|
+
let endY = elementCache.get(endElementHash);
|
|
6611
|
+
if (startY === undefined) {
|
|
6612
|
+
const el = this.visualizer?.get(startElementHash) ??
|
|
6613
|
+
doc.querySelector(`[data-clarity-hashbeta='${startElementHash}']`);
|
|
6614
|
+
startY = Math.max(scrollTop + (el?.getBoundingClientRect().y ?? 0), 10);
|
|
6615
|
+
elementCache.set(startElementHash, startY);
|
|
6616
|
+
}
|
|
6617
|
+
if (endY === undefined) {
|
|
6618
|
+
const el = this.visualizer?.get(endElementHash) ??
|
|
6619
|
+
doc.querySelector(`[data-clarity-hashbeta='${endElementHash}']`);
|
|
6620
|
+
const rect = el?.getBoundingClientRect();
|
|
6621
|
+
endY = Math.min(scrollTop + (rect?.y ?? 0) + (rect?.height ?? 0), contentHeight);
|
|
6622
|
+
elementCache.set(endElementHash, endY);
|
|
6623
|
+
}
|
|
6624
|
+
if (startY && endY && endY >= startY) {
|
|
6625
|
+
const startPercent = Math.max(Math.floor((100 * startY) / contentHeight), 0);
|
|
6626
|
+
const endPercent = Math.min(Math.floor((100 * endY) / contentHeight), 99);
|
|
6627
|
+
if (foldPercent === 0 || endPercent - startPercent <= 2 * foldPercent) {
|
|
6628
|
+
for (let i = startPercent; i < endPercent; i++) {
|
|
6629
|
+
this.attentionMapData[i].cumulativeTime += timeSpent;
|
|
6630
|
+
maxTime = Math.max(maxTime, this.attentionMapData[i].cumulativeTime);
|
|
6631
|
+
}
|
|
6632
|
+
}
|
|
6633
|
+
}
|
|
6634
|
+
}
|
|
6635
|
+
return maxTime;
|
|
6636
|
+
};
|
|
6637
|
+
overlay = () => {
|
|
6638
|
+
if (!this.state?.window)
|
|
6639
|
+
return null;
|
|
6640
|
+
const win = this.state.window;
|
|
6641
|
+
const doc = win.document;
|
|
6642
|
+
const de = doc.documentElement;
|
|
6643
|
+
let canvas = doc.getElementById(CANVAS_ID + '-single');
|
|
6644
|
+
if (!canvas) {
|
|
6645
|
+
canvas = doc.createElement('CANVAS');
|
|
6646
|
+
canvas.id = CANVAS_ID + '-single';
|
|
6647
|
+
canvas.width = 0;
|
|
6648
|
+
canvas.height = 0;
|
|
6649
|
+
canvas.style.position = 'absolute';
|
|
6650
|
+
canvas.style.zIndex = `${Z_INDEX}`;
|
|
6651
|
+
canvas.style.display = 'block';
|
|
6652
|
+
de.appendChild(canvas);
|
|
6653
|
+
win.addEventListener('resize', this.reRender, true);
|
|
6654
|
+
this.observer = typeof window.ResizeObserver !== 'undefined' ? new ResizeObserver(this.reRender) : null;
|
|
6655
|
+
this.observer?.observe(doc.body);
|
|
6656
|
+
}
|
|
6657
|
+
canvas.width = de.clientWidth;
|
|
6658
|
+
canvas.height = de.clientHeight;
|
|
6659
|
+
canvas.style.left = `${win.pageXOffset}px`;
|
|
6660
|
+
canvas.style.top = `${win.pageYOffset}px`;
|
|
6661
|
+
canvas.getContext('2d')?.clearRect(0, 0, canvas.width, canvas.height);
|
|
6662
|
+
return canvas;
|
|
6663
|
+
};
|
|
6664
|
+
}
|
|
6665
|
+
|
|
6666
|
+
class GXVisualizer extends Visualizer {
|
|
6667
|
+
attentionMap;
|
|
6668
|
+
originalHtml;
|
|
6669
|
+
originalClearmap;
|
|
6670
|
+
originalSetup;
|
|
6671
|
+
constructor() {
|
|
6672
|
+
super();
|
|
6673
|
+
this.attentionMap = new AttentionMapRenderer(null);
|
|
6674
|
+
// Save references to base implementations before overriding
|
|
6675
|
+
this.originalHtml = this.html;
|
|
6676
|
+
this.originalClearmap = this.clearmap;
|
|
6677
|
+
this.originalSetup = this.setup;
|
|
6678
|
+
this.html = this.htmlOverride;
|
|
6679
|
+
this.clearmap = this.clearmapOverride;
|
|
6680
|
+
this.setup = this.setupOverride;
|
|
6681
|
+
}
|
|
6682
|
+
htmlOverride = async (decoded, target, portalCanvasId, hash, useproxy, logerror, shortCircuitStrategy) => {
|
|
6683
|
+
await this.originalHtml(decoded, target, portalCanvasId, hash, useproxy, logerror, shortCircuitStrategy);
|
|
6684
|
+
return this;
|
|
6685
|
+
};
|
|
6686
|
+
setupOverride = async (target, options) => {
|
|
6687
|
+
// Clear existing custom renderers before re-initializing (null-safe)
|
|
6688
|
+
this.attentionMap?.clear();
|
|
6689
|
+
// Initialize base Visualizer (sets this.state, this.heatmap, this.layout, etc.)
|
|
6690
|
+
await this.originalSetup(target, options);
|
|
6691
|
+
// Re-create custom renderers with the newly initialized PlaybackState
|
|
6692
|
+
const state = this.state;
|
|
6693
|
+
this.attentionMap = new AttentionMapRenderer(state);
|
|
6694
|
+
return this;
|
|
6695
|
+
};
|
|
6696
|
+
clearmapOverride = () => {
|
|
6697
|
+
this.originalClearmap();
|
|
6698
|
+
this.attentionMap?.clear();
|
|
6699
|
+
};
|
|
6700
|
+
/**
|
|
6701
|
+
* Render attention/engagement map.
|
|
6702
|
+
* @param attentionData - Array of attention data points with start/end element hashes and time spent
|
|
6703
|
+
* @param avgFold - Average fold pixel position (used to scale top portion)
|
|
6704
|
+
* @param isSecondary - Whether to use secondary comparison iframe IDs
|
|
6705
|
+
*/
|
|
6706
|
+
attention = (attentionData, avgFold, isSecondary = false) => {
|
|
6707
|
+
this.clearmapOverride();
|
|
6708
|
+
this.attentionMap.attention(attentionData, avgFold, this, isSecondary);
|
|
6709
|
+
};
|
|
6710
|
+
}
|
|
6711
|
+
|
|
6434
6712
|
const useHeatmapRender = () => {
|
|
6435
6713
|
const viewId = useViewIdContext();
|
|
6436
6714
|
const data = useHeatmapDataContext((s) => s.data);
|
|
@@ -6442,11 +6720,9 @@ const useHeatmapRender = () => {
|
|
|
6442
6720
|
const renderHeatmap = useCallback(async (payloads) => {
|
|
6443
6721
|
if (!payloads || payloads.length === 0)
|
|
6444
6722
|
return;
|
|
6445
|
-
|
|
6446
|
-
if (!
|
|
6447
|
-
visualizer = new Visualizer();
|
|
6723
|
+
const visualizer = vizRef ?? new GXVisualizer();
|
|
6724
|
+
if (!vizRef)
|
|
6448
6725
|
setVizRef(visualizer);
|
|
6449
|
-
}
|
|
6450
6726
|
setIsRenderViz(false);
|
|
6451
6727
|
const iframe = iframeRef.current;
|
|
6452
6728
|
if (!iframe?.contentWindow)
|
|
@@ -6998,6 +7274,29 @@ const useWrapperRefHeight = (props) => {
|
|
|
6998
7274
|
return {};
|
|
6999
7275
|
};
|
|
7000
7276
|
|
|
7277
|
+
const useHeatmapScroll = ({ visualRef }) => {
|
|
7278
|
+
const selectedScrollY = useHeatmapScrollContext((s) => s.selectedScrollY);
|
|
7279
|
+
const widthScale = useHeatmapVizContext((s) => s.widthScale);
|
|
7280
|
+
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
7281
|
+
useEffect(() => {
|
|
7282
|
+
if (!selectedScrollY || !iframeHeight || !visualRef.current)
|
|
7283
|
+
return;
|
|
7284
|
+
const container = visualRef.current;
|
|
7285
|
+
// const visualRect = container.getBoundingClientRect();
|
|
7286
|
+
// const viewportHeight = visualRect.height;
|
|
7287
|
+
// selectedScrollY is a percentage (0-100) → convert to content pixels → scale to visual position
|
|
7288
|
+
const contentPixelY = (selectedScrollY / 100) * iframeHeight;
|
|
7289
|
+
const topScaled = contentPixelY * widthScale;
|
|
7290
|
+
// Skip if already visible in the current viewport
|
|
7291
|
+
// const currentScrollTop = container.scrollTop;
|
|
7292
|
+
// const isVisible = topScaled >= currentScrollTop && topScaled <= currentScrollTop + viewportHeight;
|
|
7293
|
+
// if (isVisible) return;
|
|
7294
|
+
// Center the target position vertically in the viewport
|
|
7295
|
+
const targetScrollTop = Math.max(0, topScaled);
|
|
7296
|
+
container.scrollTo({ top: targetScrollTop, behavior: 'smooth' });
|
|
7297
|
+
}, [selectedScrollY, widthScale, iframeHeight]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
7298
|
+
};
|
|
7299
|
+
|
|
7001
7300
|
const useZonePositions = (_options) => {
|
|
7002
7301
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
7003
7302
|
const getZonePosition = useCallback((zone) => {
|
|
@@ -7212,7 +7511,7 @@ const PopoverSidebar = () => {
|
|
|
7212
7511
|
position: 'absolute',
|
|
7213
7512
|
top: '24px',
|
|
7214
7513
|
left: '24px',
|
|
7215
|
-
zIndex: Z_INDEX.SIDEBAR_POPOVER,
|
|
7514
|
+
zIndex: Z_INDEX$1.SIDEBAR_POPOVER,
|
|
7216
7515
|
height: `calc(100% - ${HEATMAP_CONFIG.heightToolbar}px - ${HEATMAP_CONFIG.padding}px - 24px)`,
|
|
7217
7516
|
width: `calc(${sidebarWidth}px + ${HEATMAP_CONFIG.borderWidth}px)`,
|
|
7218
7517
|
};
|
|
@@ -8361,11 +8660,12 @@ const VizClickmap = ({ iframeRef, visualRef, wrapperRef }) => {
|
|
|
8361
8660
|
}
|
|
8362
8661
|
};
|
|
8363
8662
|
|
|
8364
|
-
const
|
|
8663
|
+
const IS_ENABLE_MINIMAP = false;
|
|
8664
|
+
const Minimap = ({ zones, maxUsers }) => {
|
|
8365
8665
|
const scrollType = useHeatmapSettingContext((s) => s.scrollType);
|
|
8366
8666
|
const showMinimap = useHeatmapScrollContext((s) => s.showMinimap);
|
|
8367
8667
|
const isScrollType = [EScrollType.Attention].includes(scrollType ?? EScrollType.Depth);
|
|
8368
|
-
if (!showMinimap || !isScrollType)
|
|
8668
|
+
if (!showMinimap || !isScrollType || !IS_ENABLE_MINIMAP)
|
|
8369
8669
|
return null;
|
|
8370
8670
|
return (jsx("div", { style: {
|
|
8371
8671
|
position: 'fixed',
|
|
@@ -8434,10 +8734,10 @@ const HoverZones = ({ iframeRef, wrapperRef, position, currentScrollPercent }) =
|
|
|
8434
8734
|
return null;
|
|
8435
8735
|
if (!position)
|
|
8436
8736
|
return null;
|
|
8437
|
-
return (jsxs(Fragment, { children: [jsx(ScrollZoneTooltip, { position: position, currentScrollPercent: currentScrollPercent, scrollmap: scrollmap || [] }), jsx(
|
|
8737
|
+
return (jsxs(Fragment, { children: [jsx(ScrollZoneTooltip, { position: position, currentScrollPercent: currentScrollPercent, scrollmap: scrollmap || [] }), jsx(Minimap, { zones: zones, maxUsers: maxUsers })] }));
|
|
8438
8738
|
};
|
|
8439
8739
|
|
|
8440
|
-
const
|
|
8740
|
+
const ScrollOverlay = ({ wrapperRef, iframeRef }) => {
|
|
8441
8741
|
const widthScale = useHeatmapVizContext((s) => s.widthScale);
|
|
8442
8742
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
8443
8743
|
const overlayRef = useRef(null);
|
|
@@ -8475,71 +8775,74 @@ const ScrollMapOverlay = ({ wrapperRef, iframeRef }) => {
|
|
|
8475
8775
|
}, children: jsx(HoverZones, { position: position, currentScrollPercent: currentScrollPercent, iframeRef: iframeRef, wrapperRef: wrapperRef }) }));
|
|
8476
8776
|
};
|
|
8477
8777
|
|
|
8478
|
-
const
|
|
8479
|
-
const dataInfo = useHeatmapDataContext((s) => s.dataInfo);
|
|
8480
|
-
const { getZonePosition } = useZonePositions();
|
|
8481
|
-
const averageFold = dataInfo?.averageFold || 50;
|
|
8482
|
-
const position = getZonePosition({
|
|
8483
|
-
startY: averageFold,
|
|
8484
|
-
endY: averageFold,
|
|
8485
|
-
});
|
|
8486
|
-
if (!position)
|
|
8487
|
-
return null;
|
|
8778
|
+
const MarkerLine = ({ top, label, bgColor = 'white', lineColor = '#303030', labelColor = '#303030', variant = 'dashed', zIndex = 1, }) => {
|
|
8488
8779
|
return (jsx("div", { style: {
|
|
8489
8780
|
position: 'absolute',
|
|
8490
|
-
top: `${
|
|
8781
|
+
top: `${top}px`,
|
|
8491
8782
|
left: 0,
|
|
8492
8783
|
width: '100%',
|
|
8493
|
-
height: '
|
|
8494
|
-
|
|
8784
|
+
height: '0px',
|
|
8785
|
+
borderBottom: `2px ${variant} ${lineColor}`,
|
|
8786
|
+
// height: isSolid ? '2px' : '0px',
|
|
8787
|
+
// boxShadow: isSolid ? `0 0 4px ${lineColor}40` : undefined,
|
|
8495
8788
|
pointerEvents: 'none',
|
|
8496
|
-
zIndex
|
|
8497
|
-
boxShadow: '0 0 4px rgba(0,120,212,0.5)',
|
|
8789
|
+
zIndex,
|
|
8498
8790
|
display: 'flex',
|
|
8499
8791
|
alignItems: 'center',
|
|
8500
|
-
}, children:
|
|
8792
|
+
}, children: jsx("div", { style: {
|
|
8501
8793
|
position: 'absolute',
|
|
8502
|
-
padding: '8px',
|
|
8503
|
-
backgroundColor:
|
|
8504
|
-
color:
|
|
8505
|
-
fontSize: '
|
|
8506
|
-
fontWeight:
|
|
8794
|
+
padding: '6px 8px',
|
|
8795
|
+
backgroundColor: bgColor,
|
|
8796
|
+
color: labelColor,
|
|
8797
|
+
fontSize: '14px',
|
|
8798
|
+
fontWeight: 500,
|
|
8507
8799
|
borderRadius: '4px',
|
|
8508
8800
|
whiteSpace: 'nowrap',
|
|
8509
|
-
left: '
|
|
8510
|
-
minWidth: '
|
|
8801
|
+
left: '16px',
|
|
8802
|
+
minWidth: '100px',
|
|
8511
8803
|
textAlign: 'center',
|
|
8512
|
-
}, children:
|
|
8804
|
+
}, children: label }) }));
|
|
8513
8805
|
};
|
|
8514
8806
|
|
|
8515
|
-
const
|
|
8807
|
+
const AverageFold = ({ iframeRef, wrapperRef }) => {
|
|
8808
|
+
const dataInfo = useHeatmapDataContext((s) => s.dataInfo);
|
|
8809
|
+
const { getZonePosition } = useZonePositions();
|
|
8810
|
+
const averageFold = dataInfo?.averageFold || 50;
|
|
8811
|
+
const position = getZonePosition({
|
|
8812
|
+
startY: averageFold,
|
|
8813
|
+
endY: averageFold,
|
|
8814
|
+
});
|
|
8815
|
+
if (!position)
|
|
8816
|
+
return null;
|
|
8817
|
+
return jsx(MarkerLine, { top: position.top, label: `Average fold`, zIndex: 2 });
|
|
8818
|
+
};
|
|
8819
|
+
|
|
8820
|
+
const ScrollMarkers = ({ iframeRef, wrapperRef, visualRef }) => {
|
|
8516
8821
|
const scrollmap = useHeatmapDataContext((s) => s.scrollmap);
|
|
8517
8822
|
const scrollType = useHeatmapSettingContext((s) => s.scrollType);
|
|
8518
8823
|
const { getZonePosition } = useZonePositions();
|
|
8824
|
+
useHeatmapScroll({ visualRef });
|
|
8519
8825
|
if (!scrollmap || scrollmap.length === 0)
|
|
8520
8826
|
return null;
|
|
8521
|
-
|
|
8522
|
-
|
|
8523
|
-
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
|
-
|
|
8527
|
-
|
|
8528
|
-
|
|
8529
|
-
}
|
|
8530
|
-
return scrollmap[scrollmap.length - 1]?.scrollReachY || null;
|
|
8827
|
+
// Matches Clarity's addInfoMarkers logic:
|
|
8828
|
+
// find the closest percUsers entry, then validate it's within ±MARKER_RANGE
|
|
8829
|
+
const MARKER_RANGE = 2;
|
|
8830
|
+
const findScrollReachY = (targetPercent) => {
|
|
8831
|
+
const closest = scrollmap.reduce((prev, curr) => Math.abs(curr.percUsers - targetPercent) < Math.abs(prev.percUsers - targetPercent) ? curr : prev);
|
|
8832
|
+
if (Math.abs(closest.percUsers - targetPercent) > MARKER_RANGE)
|
|
8833
|
+
return null;
|
|
8834
|
+
return closest.scrollReachY;
|
|
8531
8835
|
};
|
|
8532
8836
|
const boundaries = [
|
|
8533
8837
|
{ percent: 75, label: '75%', color: '#10B981' },
|
|
8534
8838
|
{ percent: 50, label: '50%', color: '#F59E0B' },
|
|
8535
8839
|
{ percent: 25, label: '25%', color: '#EF4444' },
|
|
8536
|
-
{ percent: 5, label: '5%', color: '#8B5CF6' },
|
|
8537
8840
|
];
|
|
8538
8841
|
const isScrollDepth = scrollType === EScrollType.Depth;
|
|
8539
8842
|
if (!isScrollDepth)
|
|
8540
8843
|
return null;
|
|
8541
8844
|
return (jsx(Fragment, { children: boundaries.map((boundary) => {
|
|
8542
|
-
const scrollY =
|
|
8845
|
+
const scrollY = findScrollReachY(boundary.percent);
|
|
8543
8846
|
if (scrollY === null)
|
|
8544
8847
|
return null;
|
|
8545
8848
|
const position = getZonePosition({
|
|
@@ -8548,50 +8851,14 @@ const ScrollmapMarker = ({ iframeRef, wrapperRef }) => {
|
|
|
8548
8851
|
});
|
|
8549
8852
|
if (!position)
|
|
8550
8853
|
return null;
|
|
8551
|
-
return
|
|
8552
|
-
position: 'absolute',
|
|
8553
|
-
top: `${position.top}px`,
|
|
8554
|
-
left: 0,
|
|
8555
|
-
transformOrigin: 'left center',
|
|
8556
|
-
width: '100%',
|
|
8557
|
-
height: '0px',
|
|
8558
|
-
// borderBottom: `2px dashed #323130`,
|
|
8559
|
-
borderBottom: `2px solid ${boundary.color}`,
|
|
8560
|
-
// background: 'repeating-linear-gradient(90deg, #323130, transparent 2px 3px)',
|
|
8561
|
-
zIndex: 1,
|
|
8562
|
-
display: 'flex',
|
|
8563
|
-
alignItems: 'center',
|
|
8564
|
-
}, children: jsx("div", { style: {
|
|
8565
|
-
position: 'absolute',
|
|
8566
|
-
padding: '8px',
|
|
8567
|
-
backgroundColor: boundary.color,
|
|
8568
|
-
color: 'white',
|
|
8569
|
-
fontSize: '16px',
|
|
8570
|
-
fontWeight: 600,
|
|
8571
|
-
borderRadius: '4px',
|
|
8572
|
-
whiteSpace: 'nowrap',
|
|
8573
|
-
left: '12px',
|
|
8574
|
-
minWidth: '120px',
|
|
8575
|
-
textAlign: 'center',
|
|
8576
|
-
// textAlign: 'center',
|
|
8577
|
-
// padding: '8px',
|
|
8578
|
-
// paddingInline: '8px',
|
|
8579
|
-
// fontSize: '16px',
|
|
8580
|
-
// background: '#fff',
|
|
8581
|
-
// width: 'auto',
|
|
8582
|
-
// borderRadius: '4px',
|
|
8583
|
-
// position: 'absolute',
|
|
8584
|
-
// left: '12px',
|
|
8585
|
-
// minWidth: '120px',
|
|
8586
|
-
}, children: boundary.label }) }, boundary.label));
|
|
8854
|
+
return jsx(MarkerLine, { top: position.top, label: boundary.label }, boundary.label);
|
|
8587
8855
|
}) }));
|
|
8588
8856
|
};
|
|
8589
8857
|
|
|
8590
8858
|
const SCROLL_TYPES = [EHeatmapType.Scroll];
|
|
8591
|
-
const VizScrollMap = ({ iframeRef, wrapperRef }) => {
|
|
8859
|
+
const VizScrollMap = ({ iframeRef, wrapperRef, visualRef }) => {
|
|
8592
8860
|
const heatmapType = useHeatmapSettingContext((s) => s.heatmapType);
|
|
8593
8861
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
8594
|
-
// useRenderCount('VizScrollMap');
|
|
8595
8862
|
const isHeatmapScroll = SCROLL_TYPES.includes(heatmapType ?? EHeatmapType.Click);
|
|
8596
8863
|
if (!iframeHeight || !isHeatmapScroll)
|
|
8597
8864
|
return null;
|
|
@@ -8603,7 +8870,7 @@ const VizScrollMap = ({ iframeRef, wrapperRef }) => {
|
|
|
8603
8870
|
height: '100%',
|
|
8604
8871
|
transform: 'translateZ(0)',
|
|
8605
8872
|
zIndex: 2,
|
|
8606
|
-
}, children: [jsx(
|
|
8873
|
+
}, children: [jsx(ScrollMarkers, { iframeRef: iframeRef, wrapperRef: wrapperRef, visualRef: visualRef }), jsx(AverageFold, { iframeRef: iframeRef, wrapperRef: wrapperRef }), jsx(ScrollOverlay, { iframeRef: iframeRef, wrapperRef: wrapperRef })] }));
|
|
8607
8874
|
};
|
|
8608
8875
|
|
|
8609
8876
|
const VizLoadingCanvas = () => {
|
|
@@ -8674,7 +8941,7 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
|
|
|
8674
8941
|
const scrollTop = e.currentTarget.scrollTop;
|
|
8675
8942
|
handleScroll(scrollTop);
|
|
8676
8943
|
};
|
|
8677
|
-
return (jsxs(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, onScroll: onScroll, iframeHeight: iframeHeight, children: [jsx(VizClickmap, { iframeRef: iframeRef, visualRef: visualRef, wrapperRef: wrapperRef }), jsx("iframe", { ...HEATMAP_IFRAME, id: `clarity-iframe-${viewId}`, ref: iframeRef, width: contentWidth, height: wrapperHeight }), jsx(VizLoadingCanvas, {}), jsx(VizScrollMap, { iframeRef: iframeRef, wrapperRef:
|
|
8944
|
+
return (jsxs(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, onScroll: onScroll, iframeHeight: iframeHeight, children: [jsx(VizClickmap, { iframeRef: iframeRef, visualRef: visualRef, wrapperRef: wrapperRef }), jsx("iframe", { ...HEATMAP_IFRAME, id: `clarity-iframe-${viewId}`, ref: iframeRef, width: contentWidth, height: wrapperHeight }), jsx(VizLoadingCanvas, {}), jsx(VizScrollMap, { visualRef: visualRef, iframeRef: iframeRef, wrapperRef: wrapperRef })] }));
|
|
8678
8945
|
};
|
|
8679
8946
|
|
|
8680
8947
|
const VizLoading = () => {
|
|
@@ -8785,10 +9052,10 @@ const ContentTopBar = () => {
|
|
|
8785
9052
|
}, children: CompTopBar && jsx(CompTopBar, {}) }));
|
|
8786
9053
|
};
|
|
8787
9054
|
|
|
8788
|
-
const HeatmapLayout = ({ data, clickmap, clickAreas, scrollmap, controls, dataInfo, isLoading, isLoadingCanvas, }) => {
|
|
9055
|
+
const HeatmapLayout = ({ data, clickmap, clickAreas, scrollmap, attentionMap, controls, dataInfo, isLoading, isLoadingCanvas, }) => {
|
|
8789
9056
|
useRegisterControl(controls);
|
|
8790
9057
|
useRegisterData(data, dataInfo);
|
|
8791
|
-
useRegisterHeatmap({ clickmap, scrollmap, clickAreas });
|
|
9058
|
+
useRegisterHeatmap({ clickmap, scrollmap, clickAreas, attentionMap });
|
|
8792
9059
|
useRegisterConfig({ isLoading, isLoadingCanvas });
|
|
8793
9060
|
// performanceLogger.configure({
|
|
8794
9061
|
// enabled: true,
|
|
@@ -8819,4 +9086,4 @@ const HeatmapLayout = ({ data, clickmap, clickAreas, scrollmap, controls, dataIn
|
|
|
8819
9086
|
}
|
|
8820
9087
|
};
|
|
8821
9088
|
|
|
8822
|
-
export { BACKDROP_CONFIG, DEFAULT_SIDEBAR_WIDTH, DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO, EClickMode, EClickRankType, EClickType, EDeviceType, EHeatmapType, ELM_CALLOUT_CONFIG, EScrollType, GraphView, HEATMAP_CONFIG, HEATMAP_IFRAME, HEATMAP_STYLE, HeatmapLayout, ViewIdContext, Z_INDEX, compareViewPerformance, convertViewportToIframeCoords, createStorePerformanceTracker, createViewContextHook, downloadPerformanceReport, getCompareViewId, getMetricsByViewId, getPerformanceReportJSON, getScrollGradientColor, performanceLogger, printPerformanceSummary, scrollToElementIfNeeded, sendPerformanceReport, serializeAreas, trackStoreAction, useAreaCreation, useAreaEditMode, useAreaFilterVisible, useAreaHydration, useAreaInteraction, useAreaPositionsUpdater, useAreaRectSync, useAreaRendererContainer, useAreaTopAutoDetect, useClickedElement, useDebounceCallback, useElementCalloutVisible, useHeatmapAreaClickContext, useHeatmapCanvas, useHeatmapClickContext, useHeatmapCompareStore, useHeatmapConfigStore, useHeatmapCopyView, useHeatmapDataContext, useHeatmapEffects, useHeatmapElementPosition, useHeatmapHoverContext, useHeatmapLiveStore, useHeatmapRenderByMode, useHeatmapScale, useHeatmapScrollContext, useHeatmapSettingContext, useHeatmapVizContext, useHeatmapVizRectContext, useHeatmapWidthByDevice, useHoveredElement, useIframeHeight, useIframeHeightProcessor, useMeasureFunction, useRegisterConfig, useRegisterControl, useRegisterData, useRegisterHeatmap, useRenderCount, useScrollmapZones, useTrackHookCall, useViewIdContext, useVizLiveRender, useWhyDidYouUpdate, useWrapperRefHeight, useZonePositions, withPerformanceTracking };
|
|
9089
|
+
export { BACKDROP_CONFIG, DEFAULT_SIDEBAR_WIDTH, DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO, EClickMode, EClickRankType, EClickType, EDeviceType, EHeatmapType, ELM_CALLOUT_CONFIG, EScrollType, GraphView, HEATMAP_CONFIG, HEATMAP_IFRAME, HEATMAP_STYLE, HeatmapLayout, ViewIdContext, Z_INDEX$1 as Z_INDEX, compareViewPerformance, convertViewportToIframeCoords, createStorePerformanceTracker, createViewContextHook, downloadPerformanceReport, getCompareViewId, getMetricsByViewId, getPerformanceReportJSON, getScrollGradientColor, performanceLogger, printPerformanceSummary, scrollToElementIfNeeded, sendPerformanceReport, serializeAreas, trackStoreAction, useAreaCreation, useAreaEditMode, useAreaFilterVisible, useAreaHydration, useAreaInteraction, useAreaPositionsUpdater, useAreaRectSync, useAreaRendererContainer, useAreaTopAutoDetect, useClickedElement, useDebounceCallback, useElementCalloutVisible, useHeatmapAreaClickContext, useHeatmapCanvas, useHeatmapClickContext, useHeatmapCompareStore, useHeatmapConfigStore, useHeatmapCopyView, useHeatmapDataContext, useHeatmapEffects, useHeatmapElementPosition, useHeatmapHoverContext, useHeatmapLiveStore, useHeatmapRenderByMode, useHeatmapScale, useHeatmapScroll, useHeatmapScrollContext, useHeatmapSettingContext, useHeatmapVizContext, useHeatmapVizRectContext, useHeatmapWidthByDevice, useHoveredElement, useIframeHeight, useIframeHeightProcessor, useMeasureFunction, useRegisterConfig, useRegisterControl, useRegisterData, useRegisterHeatmap, useRenderCount, useScrollmapZones, useTrackHookCall, useViewIdContext, useVizLiveRender, useWhyDidYouUpdate, useWrapperRefHeight, useZonePositions, withPerformanceTracking };
|