@gemx-dev/heatmap-react 3.5.44 → 3.5.45
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 +3 -2
- 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/VizElement/HeatmapElements.d.ts +2 -2
- package/dist/esm/components/VizElement/HeatmapElements.d.ts.map +1 -1
- package/dist/esm/components/VizElement/HeatmapExample.d.ts +2 -0
- package/dist/esm/components/VizElement/HeatmapExample.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/AverageFoldLine.d.ts +8 -0
- package/dist/esm/components/VizScrollmap/AverageFoldLine.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/HoverZones.d.ts +10 -0
- package/dist/esm/components/VizScrollmap/HoverZones.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/MetricRow.d.ts +1 -0
- package/dist/esm/components/VizScrollmap/MetricRow.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollMapMinimap.d.ts +8 -0
- package/dist/esm/components/VizScrollmap/ScrollMapMinimap.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollMapOverlay.d.ts +7 -0
- package/dist/esm/components/VizScrollmap/ScrollMapOverlay.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollZoneHoverArea.d.ts +14 -0
- package/dist/esm/components/VizScrollmap/ScrollZoneHoverArea.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollZoneTooltip.d.ts +10 -0
- package/dist/esm/components/VizScrollmap/ScrollZoneTooltip.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollmapMarker.d.ts +7 -0
- package/dist/esm/components/VizScrollmap/ScrollmapMarker.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/VizScrollMap.d.ts +7 -0
- package/dist/esm/components/VizScrollmap/VizScrollMap.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/index.d.ts +2 -0
- package/dist/esm/components/VizScrollmap/index.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts +5 -0
- package/dist/esm/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmapV2/index.d.ts +2 -0
- package/dist/esm/components/VizScrollmapV2/index.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmapV2/scrollmap.types.d.ts +18 -0
- package/dist/esm/components/VizScrollmapV2/scrollmap.types.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmapV2/useScrollmapOverlay.d.ts +16 -0
- package/dist/esm/components/VizScrollmapV2/useScrollmapOverlay.d.ts.map +1 -0
- package/dist/esm/helpers/elm-getter.d.ts +2 -2
- package/dist/esm/helpers/elm-getter.d.ts.map +1 -1
- package/dist/esm/helpers/index.d.ts +1 -0
- package/dist/esm/helpers/index.d.ts.map +1 -1
- package/dist/esm/helpers/viz-canvas/area-clustering.d.ts +44 -0
- package/dist/esm/helpers/viz-canvas/area-clustering.d.ts.map +1 -0
- package/dist/esm/helpers/viz-canvas/area-overlay-manager-v2.d.ts +17 -0
- package/dist/esm/helpers/viz-canvas/area-overlay-manager-v2.d.ts.map +1 -0
- package/dist/esm/helpers/viz-canvas/area-overlay-manager.d.ts +51 -0
- package/dist/esm/helpers/viz-canvas/area-overlay-manager.d.ts.map +1 -0
- package/dist/esm/helpers/viz-canvas/hierarchical-area-clustering.d.ts +73 -0
- package/dist/esm/helpers/viz-canvas/hierarchical-area-clustering.d.ts.map +1 -0
- package/dist/esm/helpers/viz-canvas/index.d.ts +3 -0
- package/dist/esm/helpers/viz-canvas/index.d.ts.map +1 -0
- package/dist/esm/hooks/index.d.ts +2 -1
- package/dist/esm/hooks/index.d.ts.map +1 -1
- package/dist/esm/hooks/register/useRegisterData.d.ts +2 -2
- package/dist/esm/hooks/register/useRegisterData.d.ts.map +1 -1
- package/dist/esm/hooks/register/useRegisterHeatmap.d.ts +7 -2
- package/dist/esm/hooks/register/useRegisterHeatmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-area/useAreaHeatmap.d.ts +59 -0
- package/dist/esm/hooks/viz-area/useAreaHeatmap.d.ts.map +1 -0
- package/dist/esm/hooks/viz-area/useAreaHeatmapManager.d.ts +77 -0
- package/dist/esm/hooks/viz-area/useAreaHeatmapManager.d.ts.map +1 -0
- package/dist/esm/hooks/viz-canvas/index.d.ts +1 -1
- package/dist/esm/hooks/viz-canvas/index.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useAreamap.d.ts +14 -0
- package/dist/esm/hooks/viz-canvas/useAreamap.d.ts.map +1 -0
- package/dist/esm/hooks/viz-canvas/useHeatmapCanvas.d.ts +4 -0
- package/dist/esm/hooks/viz-canvas/useHeatmapCanvas.d.ts.map +1 -0
- package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/{umd/hooks/vix-elements → esm/hooks/viz-elements}/index.d.ts.map +1 -1
- package/dist/{umd/hooks/vix-elements → esm/hooks/viz-elements}/useClickedElement.d.ts.map +1 -1
- package/dist/esm/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts.map +1 -1
- package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts.map +1 -1
- package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts.map +1 -1
- package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapMouseHandler.d.ts +2 -2
- package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapMouseHandler.d.ts.map +1 -1
- package/dist/{umd/hooks/vix-elements → esm/hooks/viz-elements}/useHoveredElement.d.ts +4 -0
- package/dist/esm/hooks/{vix-elements → viz-elements}/useHoveredElement.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scrollmap/index.d.ts +3 -0
- package/dist/esm/hooks/viz-scrollmap/index.d.ts.map +1 -0
- package/dist/esm/hooks/viz-scrollmap/useScrollmapZones.d.ts +29 -0
- package/dist/esm/hooks/viz-scrollmap/useScrollmapZones.d.ts.map +1 -0
- package/dist/esm/hooks/viz-scrollmap/useZonePositions.d.ts +12 -0
- package/dist/esm/hooks/viz-scrollmap/useZonePositions.d.ts.map +1 -0
- package/dist/esm/index.js +470 -206
- package/dist/esm/index.mjs +470 -206
- package/dist/esm/stores/config.d.ts +5 -1
- package/dist/esm/stores/config.d.ts.map +1 -1
- package/dist/esm/stores/data.d.ts +5 -3
- package/dist/esm/stores/data.d.ts.map +1 -1
- package/dist/esm/stores/index.d.ts +1 -0
- package/dist/esm/stores/index.d.ts.map +1 -1
- package/dist/esm/stores/viz-scrollmap.d.ts +11 -0
- package/dist/esm/stores/viz-scrollmap.d.ts.map +1 -0
- package/dist/esm/types/clarity.d.ts +5 -0
- package/dist/esm/types/clarity.d.ts.map +1 -1
- package/dist/esm/types/heatmap-info.d.ts +11 -0
- package/dist/esm/types/heatmap-info.d.ts.map +1 -0
- package/dist/esm/types/heatmap.d.ts +13 -0
- package/dist/esm/types/heatmap.d.ts.map +1 -1
- package/dist/esm/types/index.d.ts +3 -0
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/types/viz-canvas.d.ts +23 -0
- package/dist/esm/types/viz-canvas.d.ts.map +1 -0
- package/dist/esm/types/viz-element.d.ts +0 -6
- package/dist/esm/types/viz-element.d.ts.map +1 -1
- package/dist/esm/types/viz-scrollmap.d.ts +27 -0
- package/dist/esm/types/viz-scrollmap.d.ts.map +1 -0
- package/dist/umd/components/Layout/HeatmapLayout.d.ts +3 -2
- 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/VizElement/HeatmapElements.d.ts +2 -2
- package/dist/umd/components/VizElement/HeatmapElements.d.ts.map +1 -1
- package/dist/umd/components/VizElement/HeatmapExample.d.ts +2 -0
- package/dist/umd/components/VizElement/HeatmapExample.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/AverageFoldLine.d.ts +8 -0
- package/dist/umd/components/VizScrollmap/AverageFoldLine.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/HoverZones.d.ts +10 -0
- package/dist/umd/components/VizScrollmap/HoverZones.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/MetricRow.d.ts +1 -0
- package/dist/umd/components/VizScrollmap/MetricRow.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollMapMinimap.d.ts +8 -0
- package/dist/umd/components/VizScrollmap/ScrollMapMinimap.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollMapOverlay.d.ts +7 -0
- package/dist/umd/components/VizScrollmap/ScrollMapOverlay.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollZoneHoverArea.d.ts +14 -0
- package/dist/umd/components/VizScrollmap/ScrollZoneHoverArea.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollZoneTooltip.d.ts +10 -0
- package/dist/umd/components/VizScrollmap/ScrollZoneTooltip.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollmapMarker.d.ts +7 -0
- package/dist/umd/components/VizScrollmap/ScrollmapMarker.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/VizScrollMap.d.ts +7 -0
- package/dist/umd/components/VizScrollmap/VizScrollMap.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/index.d.ts +2 -0
- package/dist/umd/components/VizScrollmap/index.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts +5 -0
- package/dist/umd/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmapV2/index.d.ts +2 -0
- package/dist/umd/components/VizScrollmapV2/index.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmapV2/scrollmap.types.d.ts +18 -0
- package/dist/umd/components/VizScrollmapV2/scrollmap.types.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmapV2/useScrollmapOverlay.d.ts +16 -0
- package/dist/umd/components/VizScrollmapV2/useScrollmapOverlay.d.ts.map +1 -0
- package/dist/umd/helpers/elm-getter.d.ts +2 -2
- package/dist/umd/helpers/elm-getter.d.ts.map +1 -1
- package/dist/umd/helpers/index.d.ts +1 -0
- package/dist/umd/helpers/index.d.ts.map +1 -1
- package/dist/umd/helpers/viz-canvas/area-clustering.d.ts +44 -0
- package/dist/umd/helpers/viz-canvas/area-clustering.d.ts.map +1 -0
- package/dist/umd/helpers/viz-canvas/area-overlay-manager-v2.d.ts +17 -0
- package/dist/umd/helpers/viz-canvas/area-overlay-manager-v2.d.ts.map +1 -0
- package/dist/umd/helpers/viz-canvas/area-overlay-manager.d.ts +51 -0
- package/dist/umd/helpers/viz-canvas/area-overlay-manager.d.ts.map +1 -0
- package/dist/umd/helpers/viz-canvas/hierarchical-area-clustering.d.ts +73 -0
- package/dist/umd/helpers/viz-canvas/hierarchical-area-clustering.d.ts.map +1 -0
- package/dist/umd/helpers/viz-canvas/index.d.ts +3 -0
- package/dist/umd/helpers/viz-canvas/index.d.ts.map +1 -0
- package/dist/umd/hooks/index.d.ts +2 -1
- package/dist/umd/hooks/index.d.ts.map +1 -1
- package/dist/umd/hooks/register/useRegisterData.d.ts +2 -2
- package/dist/umd/hooks/register/useRegisterData.d.ts.map +1 -1
- package/dist/umd/hooks/register/useRegisterHeatmap.d.ts +7 -2
- package/dist/umd/hooks/register/useRegisterHeatmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-area/useAreaHeatmap.d.ts +59 -0
- package/dist/umd/hooks/viz-area/useAreaHeatmap.d.ts.map +1 -0
- package/dist/umd/hooks/viz-area/useAreaHeatmapManager.d.ts +77 -0
- package/dist/umd/hooks/viz-area/useAreaHeatmapManager.d.ts.map +1 -0
- package/dist/umd/hooks/viz-canvas/index.d.ts +1 -1
- package/dist/umd/hooks/viz-canvas/index.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useAreamap.d.ts +14 -0
- package/dist/umd/hooks/viz-canvas/useAreamap.d.ts.map +1 -0
- package/dist/umd/hooks/viz-canvas/useHeatmapCanvas.d.ts +4 -0
- package/dist/umd/hooks/viz-canvas/useHeatmapCanvas.d.ts.map +1 -0
- package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/{esm/hooks/vix-elements → umd/hooks/viz-elements}/index.d.ts.map +1 -1
- package/dist/{esm/hooks/vix-elements → umd/hooks/viz-elements}/useClickedElement.d.ts.map +1 -1
- package/dist/umd/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts.map +1 -1
- package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts.map +1 -1
- package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts.map +1 -1
- package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapMouseHandler.d.ts +2 -2
- package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapMouseHandler.d.ts.map +1 -1
- package/dist/{esm/hooks/vix-elements → umd/hooks/viz-elements}/useHoveredElement.d.ts +4 -0
- package/dist/umd/hooks/{vix-elements → viz-elements}/useHoveredElement.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scrollmap/index.d.ts +3 -0
- package/dist/umd/hooks/viz-scrollmap/index.d.ts.map +1 -0
- package/dist/umd/hooks/viz-scrollmap/useScrollmapZones.d.ts +29 -0
- package/dist/umd/hooks/viz-scrollmap/useScrollmapZones.d.ts.map +1 -0
- package/dist/umd/hooks/viz-scrollmap/useZonePositions.d.ts +12 -0
- package/dist/umd/hooks/viz-scrollmap/useZonePositions.d.ts.map +1 -0
- package/dist/umd/index.js +2 -2
- package/dist/umd/stores/config.d.ts +5 -1
- package/dist/umd/stores/config.d.ts.map +1 -1
- package/dist/umd/stores/data.d.ts +5 -3
- package/dist/umd/stores/data.d.ts.map +1 -1
- package/dist/umd/stores/index.d.ts +1 -0
- package/dist/umd/stores/index.d.ts.map +1 -1
- package/dist/umd/stores/viz-scrollmap.d.ts +11 -0
- package/dist/umd/stores/viz-scrollmap.d.ts.map +1 -0
- package/dist/umd/types/clarity.d.ts +5 -0
- package/dist/umd/types/clarity.d.ts.map +1 -1
- package/dist/umd/types/heatmap-info.d.ts +11 -0
- package/dist/umd/types/heatmap-info.d.ts.map +1 -0
- package/dist/umd/types/heatmap.d.ts +13 -0
- package/dist/umd/types/heatmap.d.ts.map +1 -1
- package/dist/umd/types/index.d.ts +3 -0
- package/dist/umd/types/index.d.ts.map +1 -1
- package/dist/umd/types/viz-canvas.d.ts +23 -0
- package/dist/umd/types/viz-canvas.d.ts.map +1 -0
- package/dist/umd/types/viz-element.d.ts +0 -6
- package/dist/umd/types/viz-element.d.ts.map +1 -1
- package/dist/umd/types/viz-scrollmap.d.ts +27 -0
- package/dist/umd/types/viz-scrollmap.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +0 -2
- package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +0 -1
- package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +0 -2
- package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +0 -1
- /package/dist/esm/hooks/{vix-elements → viz-elements}/index.d.ts +0 -0
- /package/dist/esm/hooks/{vix-elements → viz-elements}/useClickedElement.d.ts +0 -0
- /package/dist/esm/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts +0 -0
- /package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts +0 -0
- /package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts +0 -0
- /package/dist/umd/hooks/{vix-elements → viz-elements}/index.d.ts +0 -0
- /package/dist/umd/hooks/{vix-elements → viz-elements}/useClickedElement.d.ts +0 -0
- /package/dist/umd/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts +0 -0
- /package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts +0 -0
- /package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts +0 -0
package/dist/esm/index.js
CHANGED
|
@@ -93,18 +93,37 @@ var IHeatmapType;
|
|
|
93
93
|
IHeatmapType["Click"] = "click";
|
|
94
94
|
IHeatmapType["Scroll"] = "scroll";
|
|
95
95
|
})(IHeatmapType || (IHeatmapType = {}));
|
|
96
|
+
var IClickType;
|
|
97
|
+
(function (IClickType) {
|
|
98
|
+
IClickType["Total"] = "total-clicks";
|
|
99
|
+
IClickType["Rage"] = "rage-clicks";
|
|
100
|
+
IClickType["Dead"] = "dead-clicks";
|
|
101
|
+
IClickType["Error"] = "error-clicks";
|
|
102
|
+
IClickType["First"] = "first-clicks";
|
|
103
|
+
IClickType["Last"] = "last-clicks";
|
|
104
|
+
})(IClickType || (IClickType = {}));
|
|
105
|
+
var IScrollType;
|
|
106
|
+
(function (IScrollType) {
|
|
107
|
+
IScrollType["Depth"] = "scroll-depth";
|
|
108
|
+
IScrollType["Attention"] = "attention-scroll";
|
|
109
|
+
IScrollType["Revenue"] = "revenue-scroll";
|
|
110
|
+
})(IScrollType || (IScrollType = {}));
|
|
96
111
|
|
|
97
112
|
const useHeatmapConfigStore = create()((set, get) => {
|
|
98
113
|
return {
|
|
99
114
|
mode: 'single',
|
|
100
115
|
width: 1440,
|
|
101
116
|
sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
|
|
102
|
-
heatmapType: IHeatmapType.
|
|
117
|
+
heatmapType: IHeatmapType.Scroll,
|
|
118
|
+
clickType: IClickType.Total,
|
|
119
|
+
scrollType: IScrollType.Depth,
|
|
103
120
|
setMode: (mode) => set({ mode }),
|
|
104
121
|
resetMode: () => set({ mode: 'single' }),
|
|
105
122
|
setWidth: (width) => set({ width }),
|
|
106
123
|
setSidebarWidth: (sidebarWidth) => set({ sidebarWidth }),
|
|
107
124
|
setHeatmapType: (heatmapType) => set({ heatmapType }),
|
|
125
|
+
setClickType: (clickType) => set({ clickType }),
|
|
126
|
+
setScrollType: (scrollType) => set({ scrollType }),
|
|
108
127
|
};
|
|
109
128
|
});
|
|
110
129
|
|
|
@@ -113,11 +132,13 @@ const useHeatmapDataStore = create()((set, get) => {
|
|
|
113
132
|
data: undefined,
|
|
114
133
|
clickmap: undefined,
|
|
115
134
|
dataInfo: undefined,
|
|
135
|
+
scrollmap: undefined,
|
|
116
136
|
isRendering: true,
|
|
117
137
|
setIsRendering: (isRendering) => set({ isRendering }),
|
|
118
138
|
setDataInfo: (dataInfo) => set({ dataInfo }),
|
|
119
139
|
setData: (data) => set({ data }),
|
|
120
140
|
setClickmap: (clickmap) => set({ clickmap }),
|
|
141
|
+
setScrollmap: (scrollmap) => set({ scrollmap }),
|
|
121
142
|
};
|
|
122
143
|
});
|
|
123
144
|
|
|
@@ -145,6 +166,17 @@ const useHeatmapVizStore = create()((set, get) => {
|
|
|
145
166
|
};
|
|
146
167
|
});
|
|
147
168
|
|
|
169
|
+
const useHeatmapVizScrollmapStore = create()((set, get) => {
|
|
170
|
+
return {
|
|
171
|
+
zones: [],
|
|
172
|
+
hoveredZone: null,
|
|
173
|
+
showMinimap: true,
|
|
174
|
+
setZones: (zones) => set({ zones }),
|
|
175
|
+
setHoveredZone: (hoveredZone) => set({ hoveredZone }),
|
|
176
|
+
setShowMinimap: (showMinimap) => set({ showMinimap }),
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
|
|
148
180
|
const initialState = {
|
|
149
181
|
payloads: [],
|
|
150
182
|
htmlContent: '',
|
|
@@ -219,16 +251,25 @@ const useRegisterData = (data, dataInfo) => {
|
|
|
219
251
|
}, [dataInfo]);
|
|
220
252
|
};
|
|
221
253
|
|
|
222
|
-
const useRegisterHeatmap = (clickmap) => {
|
|
254
|
+
const useRegisterHeatmap = ({ clickmap, scrollmap }) => {
|
|
223
255
|
const setClickmap = useHeatmapDataStore((state) => state.setClickmap);
|
|
256
|
+
const setScrollmap = useHeatmapDataStore((state) => state.setScrollmap);
|
|
224
257
|
const handleSetClickmap = useCallback((clickmap) => {
|
|
225
258
|
if (!clickmap)
|
|
226
259
|
return;
|
|
227
260
|
setClickmap(clickmap);
|
|
228
261
|
}, [clickmap]);
|
|
262
|
+
const handleSetScrollmap = useCallback((scrollmap) => {
|
|
263
|
+
if (!scrollmap)
|
|
264
|
+
return;
|
|
265
|
+
setScrollmap(scrollmap);
|
|
266
|
+
}, [scrollmap]);
|
|
229
267
|
useEffect(() => {
|
|
230
268
|
handleSetClickmap(clickmap);
|
|
231
269
|
}, [clickmap]);
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
handleSetScrollmap(scrollmap);
|
|
272
|
+
}, [scrollmap]);
|
|
232
273
|
};
|
|
233
274
|
|
|
234
275
|
const PADDING = 0;
|
|
@@ -1246,8 +1287,6 @@ const debounce = (fn, delay) => {
|
|
|
1246
1287
|
};
|
|
1247
1288
|
};
|
|
1248
1289
|
|
|
1249
|
-
// ===================== CONSTANTS =====================
|
|
1250
|
-
const HEATMAP_ELEMENT_ATTRIBUTE = 'data-clarity-hashalpha'; // Hoặc attribute bạn đang dùng
|
|
1251
1290
|
// ===================== UTILITY FUNCTIONS =====================
|
|
1252
1291
|
/**
|
|
1253
1292
|
* Lấy bounding box tuyệt đối của element (relative to document)
|
|
@@ -1290,74 +1329,6 @@ function getElementsAtPoint(documentOrShadowRoot, x, y, filterFunction, visitedS
|
|
|
1290
1329
|
}
|
|
1291
1330
|
return elementsAtPoint;
|
|
1292
1331
|
}
|
|
1293
|
-
// ===================== MAIN HOOK =====================
|
|
1294
|
-
function useHeatmapMouseHandler(props) {
|
|
1295
|
-
const { heatmapWrapperRef, iframeRef, parentRef, heatmapInfo, scaleRatio, onElementHover } = props;
|
|
1296
|
-
const handleMouseMove = useCallback((event) => {
|
|
1297
|
-
// Kiểm tra tất cả refs và data cần thiết
|
|
1298
|
-
if (!heatmapWrapperRef?.current ||
|
|
1299
|
-
!iframeRef?.current ||
|
|
1300
|
-
!iframeRef.current.contentDocument ||
|
|
1301
|
-
!heatmapInfo?.elementMapInfo ||
|
|
1302
|
-
!parentRef?.current) {
|
|
1303
|
-
return;
|
|
1304
|
-
}
|
|
1305
|
-
try {
|
|
1306
|
-
// Tính toán scroll position (đã scale)
|
|
1307
|
-
const scrollTop = parentRef.current.scrollTop / scaleRatio;
|
|
1308
|
-
console.log(`🚀 🐥 ~ useHeatmapMouseHandler ~ scrollTop:`, scrollTop);
|
|
1309
|
-
// Lấy vị trí của heatmap wrapper
|
|
1310
|
-
const wrapperRect = heatmapWrapperRef.current.getBoundingClientRect();
|
|
1311
|
-
// Tính toán tọa độ chuột trong iframe (đã scale)
|
|
1312
|
-
const mouseX = (event.clientX - wrapperRect.left) / scaleRatio;
|
|
1313
|
-
const mouseY = (event.clientY - wrapperRect.top) / scaleRatio - scrollTop;
|
|
1314
|
-
// Tìm elements tại vị trí chuột
|
|
1315
|
-
const elementsAtPoint = getElementsAtPoint(iframeRef.current.contentDocument, Math.round(mouseX), Math.round(mouseY),
|
|
1316
|
-
// Filter: chỉ lấy elements có heatmap attribute
|
|
1317
|
-
(element) => element.hasAttribute(HEATMAP_ELEMENT_ATTRIBUTE));
|
|
1318
|
-
if (!elementsAtPoint || elementsAtPoint.length === 0) {
|
|
1319
|
-
return;
|
|
1320
|
-
}
|
|
1321
|
-
// Duyệt qua các elements tìm được
|
|
1322
|
-
for (let i = 0; i < elementsAtPoint.length; i++) {
|
|
1323
|
-
const element = elementsAtPoint[i];
|
|
1324
|
-
// Lấy hash/id của element
|
|
1325
|
-
const elementHash = element.getAttribute(HEATMAP_ELEMENT_ATTRIBUTE);
|
|
1326
|
-
// Kiểm tra element có data trong heatmapInfo không
|
|
1327
|
-
if (elementHash && heatmapInfo.elementMapInfo[elementHash]) {
|
|
1328
|
-
const elementData = heatmapInfo.elementMapInfo[elementHash];
|
|
1329
|
-
// Lấy bounding box của element
|
|
1330
|
-
const boundingBox = getBoundingBox(element);
|
|
1331
|
-
if (boundingBox) {
|
|
1332
|
-
// Tính rank của element
|
|
1333
|
-
const rank = Array.isArray(heatmapInfo.sortedElements) && elementData
|
|
1334
|
-
? heatmapInfo.sortedElements.indexOf(elementData) + 1
|
|
1335
|
-
: NaN;
|
|
1336
|
-
// Callback với thông tin element
|
|
1337
|
-
onElementHover({
|
|
1338
|
-
...boundingBox,
|
|
1339
|
-
// Giới hạn width không vượt quá width của heatmap
|
|
1340
|
-
width: Math.min(boundingBox.width, heatmapInfo.width || 0),
|
|
1341
|
-
// Adjust top position với scroll
|
|
1342
|
-
top: boundingBox.top + scrollTop,
|
|
1343
|
-
// Metadata
|
|
1344
|
-
hash: elementHash,
|
|
1345
|
-
clicks: elementData.totalclicks,
|
|
1346
|
-
rank: rank,
|
|
1347
|
-
selector: elementData.selector || '',
|
|
1348
|
-
});
|
|
1349
|
-
// Dừng loop khi tìm thấy element hợp lệ đầu tiên
|
|
1350
|
-
break;
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
}
|
|
1355
|
-
catch (error) {
|
|
1356
|
-
console.warn('Error handling mouse move on heatmap:', error);
|
|
1357
|
-
}
|
|
1358
|
-
}, [heatmapWrapperRef, iframeRef, parentRef, heatmapInfo, scaleRatio, onElementHover]);
|
|
1359
|
-
return { handleMouseMove };
|
|
1360
|
-
}
|
|
1361
1332
|
// ===================== EXAMPLE USAGE =====================
|
|
1362
1333
|
/*
|
|
1363
1334
|
import { useRef, useState } from 'react';
|
|
@@ -2118,6 +2089,135 @@ const useWrapperRefHeight = (props) => {
|
|
|
2118
2089
|
return {};
|
|
2119
2090
|
};
|
|
2120
2091
|
|
|
2092
|
+
const useZonePositions = (options) => {
|
|
2093
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
2094
|
+
const getZonePosition = useCallback((zone) => {
|
|
2095
|
+
if (!iframeHeight) {
|
|
2096
|
+
return null;
|
|
2097
|
+
}
|
|
2098
|
+
const startYPx = (zone.startY / 100) * iframeHeight;
|
|
2099
|
+
const heightPx = ((zone.endY - zone.startY) / 100) * iframeHeight;
|
|
2100
|
+
return {
|
|
2101
|
+
top: startYPx,
|
|
2102
|
+
height: heightPx,
|
|
2103
|
+
};
|
|
2104
|
+
}, [iframeHeight]);
|
|
2105
|
+
return {
|
|
2106
|
+
getZonePosition,
|
|
2107
|
+
};
|
|
2108
|
+
};
|
|
2109
|
+
|
|
2110
|
+
const SCROLL_GRADIENT_COLORS = [
|
|
2111
|
+
[255, 0, 0], // Red
|
|
2112
|
+
[255, 255, 0], // Yellow
|
|
2113
|
+
[0, 255, 0], // Green
|
|
2114
|
+
];
|
|
2115
|
+
const useScrollmapZones = (options) => {
|
|
2116
|
+
const { mode = 'basic', enabled = true, iframeRef, wrapperRef } = options;
|
|
2117
|
+
const [isReady, setIsReady] = useState(false);
|
|
2118
|
+
const [zones, setZones] = useState([]);
|
|
2119
|
+
const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
|
|
2120
|
+
const scrollMapInfo = useHeatmapDataStore((state) => state.dataInfo?.scrollMapInfo);
|
|
2121
|
+
const { getZonePosition } = useZonePositions();
|
|
2122
|
+
const maxUsers = useMemo(() => {
|
|
2123
|
+
if (!scrollmap || scrollmap.length === 0)
|
|
2124
|
+
return 100;
|
|
2125
|
+
return Math.max(...scrollmap.map((d) => d.percUsers));
|
|
2126
|
+
}, [scrollmap]);
|
|
2127
|
+
const createZones = useCallback((data) => {
|
|
2128
|
+
if (mode === 'basic') {
|
|
2129
|
+
const breakpoints = [0, 25, 50, 75, 100];
|
|
2130
|
+
const zones = [];
|
|
2131
|
+
for (let i = 0; i < breakpoints.length - 1; i++) {
|
|
2132
|
+
const startY = breakpoints[i];
|
|
2133
|
+
const endY = breakpoints[i + 1];
|
|
2134
|
+
const pointsInRange = data.filter((d) => d.scrollReachY >= startY && d.scrollReachY < endY);
|
|
2135
|
+
const avgUsers = pointsInRange.length > 0
|
|
2136
|
+
? pointsInRange.reduce((sum, p) => sum + p.percUsers, 0) / pointsInRange.length
|
|
2137
|
+
: 0;
|
|
2138
|
+
zones.push({
|
|
2139
|
+
id: `zone_${startY}_${endY}`,
|
|
2140
|
+
startY,
|
|
2141
|
+
endY,
|
|
2142
|
+
percUsers: avgUsers,
|
|
2143
|
+
label: `${startY}% - ${endY}%`,
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2146
|
+
return zones;
|
|
2147
|
+
}
|
|
2148
|
+
else {
|
|
2149
|
+
// Metrics mode: 20 zones (5% intervals)
|
|
2150
|
+
const zones = [];
|
|
2151
|
+
const interval = 5;
|
|
2152
|
+
// Prepare metrics map
|
|
2153
|
+
let metricsMap;
|
|
2154
|
+
if (scrollMapInfo && Object.keys(scrollMapInfo).length > 0) {
|
|
2155
|
+
metricsMap = new Map();
|
|
2156
|
+
Object.entries(scrollMapInfo).forEach(([key, value]) => {
|
|
2157
|
+
metricsMap.set(Number(key), value);
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2160
|
+
for (let i = 0; i < 100; i += interval) {
|
|
2161
|
+
const startY = i;
|
|
2162
|
+
const endY = i + interval;
|
|
2163
|
+
const point = data.find((d) => d.scrollReachY === startY) || {
|
|
2164
|
+
scrollReachY: startY,
|
|
2165
|
+
cumulativeSum: 0,
|
|
2166
|
+
percUsers: 0,
|
|
2167
|
+
};
|
|
2168
|
+
const metrics = metricsMap?.get(startY);
|
|
2169
|
+
zones.push({
|
|
2170
|
+
id: `zone_${startY}_${endY}`,
|
|
2171
|
+
startY,
|
|
2172
|
+
endY,
|
|
2173
|
+
percUsers: point.percUsers,
|
|
2174
|
+
metrics,
|
|
2175
|
+
label: `${startY}% - ${endY}%`,
|
|
2176
|
+
});
|
|
2177
|
+
}
|
|
2178
|
+
return zones;
|
|
2179
|
+
}
|
|
2180
|
+
}, [mode, scrollMapInfo]);
|
|
2181
|
+
/**
|
|
2182
|
+
* Initialize zones
|
|
2183
|
+
*/
|
|
2184
|
+
useEffect(() => {
|
|
2185
|
+
if (!enabled || !scrollmap || scrollmap.length === 0) {
|
|
2186
|
+
setIsReady(false);
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
try {
|
|
2190
|
+
const newZones = createZones(scrollmap);
|
|
2191
|
+
setZones(newZones);
|
|
2192
|
+
setIsReady(true);
|
|
2193
|
+
console.log(`[useScrollmap] Created ${newZones.length} zones in ${mode} mode`);
|
|
2194
|
+
}
|
|
2195
|
+
catch (error) {
|
|
2196
|
+
console.error('[useScrollmap] Error:', error);
|
|
2197
|
+
setIsReady(false);
|
|
2198
|
+
}
|
|
2199
|
+
}, [enabled, scrollmap, mode, createZones]);
|
|
2200
|
+
return {
|
|
2201
|
+
zones,
|
|
2202
|
+
isReady,
|
|
2203
|
+
maxUsers,
|
|
2204
|
+
getZonePosition,
|
|
2205
|
+
};
|
|
2206
|
+
};
|
|
2207
|
+
/**
|
|
2208
|
+
* Get scroll gradient color for minimap
|
|
2209
|
+
*/
|
|
2210
|
+
const getScrollGradientColor = (normalized) => {
|
|
2211
|
+
const idx = Math.min(Math.floor(normalized * 2), 1);
|
|
2212
|
+
const [r1, g1, b1] = SCROLL_GRADIENT_COLORS[idx];
|
|
2213
|
+
const [r2, g2, b2] = SCROLL_GRADIENT_COLORS[idx + 1];
|
|
2214
|
+
const localPercent = (normalized * 2) % 1;
|
|
2215
|
+
const r = Math.round(r1 + (r2 - r1) * localPercent);
|
|
2216
|
+
const g = Math.round(g1 + (g2 - g1) * localPercent);
|
|
2217
|
+
const b = Math.round(b1 + (b2 - b1) * localPercent);
|
|
2218
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
2219
|
+
};
|
|
2220
|
+
|
|
2121
2221
|
const BoxStack = forwardRef(({ children, ...props }, ref) => {
|
|
2122
2222
|
const id = props.id;
|
|
2123
2223
|
const flexDirection = props.flexDirection;
|
|
@@ -2222,113 +2322,11 @@ const useClickmap = () => {
|
|
|
2222
2322
|
return { start };
|
|
2223
2323
|
};
|
|
2224
2324
|
|
|
2225
|
-
const DATA_SCROLLMAP = [
|
|
2226
|
-
{
|
|
2227
|
-
scrollReachY: 5,
|
|
2228
|
-
cumulativeSum: 0,
|
|
2229
|
-
percUsers: 0,
|
|
2230
|
-
},
|
|
2231
|
-
{
|
|
2232
|
-
scrollReachY: 10,
|
|
2233
|
-
cumulativeSum: 0,
|
|
2234
|
-
percUsers: 0,
|
|
2235
|
-
},
|
|
2236
|
-
{
|
|
2237
|
-
scrollReachY: 15,
|
|
2238
|
-
cumulativeSum: 0,
|
|
2239
|
-
percUsers: 0,
|
|
2240
|
-
},
|
|
2241
|
-
{
|
|
2242
|
-
scrollReachY: 20,
|
|
2243
|
-
cumulativeSum: 0,
|
|
2244
|
-
percUsers: 0,
|
|
2245
|
-
},
|
|
2246
|
-
{
|
|
2247
|
-
scrollReachY: 25,
|
|
2248
|
-
cumulativeSum: 0,
|
|
2249
|
-
percUsers: 0,
|
|
2250
|
-
},
|
|
2251
|
-
{
|
|
2252
|
-
scrollReachY: 30,
|
|
2253
|
-
cumulativeSum: 0,
|
|
2254
|
-
percUsers: 0,
|
|
2255
|
-
},
|
|
2256
|
-
{
|
|
2257
|
-
scrollReachY: 35,
|
|
2258
|
-
cumulativeSum: 0,
|
|
2259
|
-
percUsers: 0,
|
|
2260
|
-
},
|
|
2261
|
-
{
|
|
2262
|
-
scrollReachY: 40,
|
|
2263
|
-
cumulativeSum: 0,
|
|
2264
|
-
percUsers: 0,
|
|
2265
|
-
},
|
|
2266
|
-
{
|
|
2267
|
-
scrollReachY: 45,
|
|
2268
|
-
cumulativeSum: 0,
|
|
2269
|
-
percUsers: 0,
|
|
2270
|
-
},
|
|
2271
|
-
{
|
|
2272
|
-
scrollReachY: 50,
|
|
2273
|
-
cumulativeSum: 0,
|
|
2274
|
-
percUsers: 0,
|
|
2275
|
-
},
|
|
2276
|
-
{
|
|
2277
|
-
scrollReachY: 55,
|
|
2278
|
-
cumulativeSum: 0,
|
|
2279
|
-
percUsers: 0,
|
|
2280
|
-
},
|
|
2281
|
-
{
|
|
2282
|
-
scrollReachY: 60,
|
|
2283
|
-
cumulativeSum: 0,
|
|
2284
|
-
percUsers: 0,
|
|
2285
|
-
},
|
|
2286
|
-
{
|
|
2287
|
-
scrollReachY: 65,
|
|
2288
|
-
cumulativeSum: 0,
|
|
2289
|
-
percUsers: 0,
|
|
2290
|
-
},
|
|
2291
|
-
{
|
|
2292
|
-
scrollReachY: 70,
|
|
2293
|
-
cumulativeSum: 0,
|
|
2294
|
-
percUsers: 0,
|
|
2295
|
-
},
|
|
2296
|
-
{
|
|
2297
|
-
scrollReachY: 75,
|
|
2298
|
-
cumulativeSum: 0,
|
|
2299
|
-
percUsers: 0,
|
|
2300
|
-
},
|
|
2301
|
-
{
|
|
2302
|
-
scrollReachY: 80,
|
|
2303
|
-
cumulativeSum: 0,
|
|
2304
|
-
percUsers: 0,
|
|
2305
|
-
},
|
|
2306
|
-
{
|
|
2307
|
-
scrollReachY: 85,
|
|
2308
|
-
cumulativeSum: 0,
|
|
2309
|
-
percUsers: 0,
|
|
2310
|
-
},
|
|
2311
|
-
{
|
|
2312
|
-
scrollReachY: 90,
|
|
2313
|
-
cumulativeSum: 0,
|
|
2314
|
-
percUsers: 0,
|
|
2315
|
-
},
|
|
2316
|
-
{
|
|
2317
|
-
scrollReachY: 95,
|
|
2318
|
-
cumulativeSum: 0,
|
|
2319
|
-
percUsers: 0,
|
|
2320
|
-
},
|
|
2321
|
-
{
|
|
2322
|
-
scrollReachY: 100,
|
|
2323
|
-
cumulativeSum: 0,
|
|
2324
|
-
percUsers: 0,
|
|
2325
|
-
},
|
|
2326
|
-
];
|
|
2327
2325
|
const useScrollmap = () => {
|
|
2328
2326
|
const vizRef = useHeatmapSingleStore((state) => state.vizRef);
|
|
2327
|
+
const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
|
|
2329
2328
|
const start = useCallback(() => {
|
|
2330
2329
|
// if (isInitialized) return;
|
|
2331
|
-
const scrollmap = DATA_SCROLLMAP;
|
|
2332
2330
|
if (!vizRef || !scrollmap || scrollmap.length === 0)
|
|
2333
2331
|
return;
|
|
2334
2332
|
try {
|
|
@@ -2339,11 +2337,11 @@ const useScrollmap = () => {
|
|
|
2339
2337
|
catch (error) {
|
|
2340
2338
|
console.error(`🚀 🐥 ~ useScrollmap ~ error:`, error);
|
|
2341
2339
|
}
|
|
2342
|
-
}, [vizRef]);
|
|
2340
|
+
}, [vizRef, scrollmap]);
|
|
2343
2341
|
return { start };
|
|
2344
2342
|
};
|
|
2345
2343
|
|
|
2346
|
-
const
|
|
2344
|
+
const useHeatmapCanvas = ({ iframeRef, }) => {
|
|
2347
2345
|
const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
|
|
2348
2346
|
const { start: startClickmap } = useClickmap();
|
|
2349
2347
|
const { start: startScrollmap } = useScrollmap();
|
|
@@ -2353,7 +2351,7 @@ const useHeatmapVizCanvas = () => {
|
|
|
2353
2351
|
startClickmap();
|
|
2354
2352
|
break;
|
|
2355
2353
|
case IHeatmapType.Scroll:
|
|
2356
|
-
|
|
2354
|
+
startScrollmap();
|
|
2357
2355
|
break;
|
|
2358
2356
|
}
|
|
2359
2357
|
}, [heatmapType, startClickmap, startScrollmap]);
|
|
@@ -2485,8 +2483,7 @@ const ELEMENT_CALLOUT = {
|
|
|
2485
2483
|
};
|
|
2486
2484
|
const HeatmapElements = (props) => {
|
|
2487
2485
|
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
2488
|
-
const
|
|
2489
|
-
const { iframeRef, wrapperRef, visualRef, visualizer, iframeDimensions, isElementSidebarOpen, isVisible = true, areDefaultRanksHidden, isSecondary, ...rest } = props;
|
|
2486
|
+
const { iframeRef, wrapperRef, visualRef, visualizer, iframeDimensions, isElementSidebarOpen, isVisible = true, areDefaultRanksHidden, isSecondary, } = props;
|
|
2490
2487
|
const getRect = useHeatmapElementPosition({
|
|
2491
2488
|
iframeRef,
|
|
2492
2489
|
wrapperRef,
|
|
@@ -2500,27 +2497,6 @@ const HeatmapElements = (props) => {
|
|
|
2500
2497
|
iframeRef,
|
|
2501
2498
|
getRect,
|
|
2502
2499
|
});
|
|
2503
|
-
const heatmapInfo = useHeatmapDataStore((state) => state.dataInfo);
|
|
2504
|
-
useHeatmapMouseHandler({
|
|
2505
|
-
heatmapWrapperRef: wrapperRef,
|
|
2506
|
-
iframeRef,
|
|
2507
|
-
parentRef: visualRef,
|
|
2508
|
-
heatmapInfo: heatmapInfo || {},
|
|
2509
|
-
scaleRatio: 0.8, // 80% zoom
|
|
2510
|
-
onElementHover: (info) => {
|
|
2511
|
-
setHoveredElement({
|
|
2512
|
-
hash: info.hash,
|
|
2513
|
-
clicks: info.clicks,
|
|
2514
|
-
rank: info.rank,
|
|
2515
|
-
selector: info.selector,
|
|
2516
|
-
top: info.top,
|
|
2517
|
-
left: info.left,
|
|
2518
|
-
width: info.width,
|
|
2519
|
-
height: info.height,
|
|
2520
|
-
});
|
|
2521
|
-
console.log(`🚀 🐥 ~ HeatmapElements ~ info:`, info);
|
|
2522
|
-
},
|
|
2523
|
-
});
|
|
2524
2500
|
useElementCalloutVisible({
|
|
2525
2501
|
visualRef,
|
|
2526
2502
|
getRect,
|
|
@@ -2576,6 +2552,293 @@ const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
|
|
|
2576
2552
|
} }));
|
|
2577
2553
|
};
|
|
2578
2554
|
|
|
2555
|
+
const AverageFoldLine = ({ iframeRef, wrapperRef }) => {
|
|
2556
|
+
const averageFold = useHeatmapDataStore((state) => state.dataInfo?.averageFold || 50);
|
|
2557
|
+
const { getZonePosition } = useZonePositions();
|
|
2558
|
+
const position = getZonePosition({
|
|
2559
|
+
startY: averageFold,
|
|
2560
|
+
endY: averageFold,
|
|
2561
|
+
});
|
|
2562
|
+
if (!position)
|
|
2563
|
+
return null;
|
|
2564
|
+
return (jsx("div", { style: {
|
|
2565
|
+
position: 'absolute',
|
|
2566
|
+
top: `${position.top}px`,
|
|
2567
|
+
left: 0,
|
|
2568
|
+
width: '100%',
|
|
2569
|
+
height: '2px',
|
|
2570
|
+
backgroundColor: '#0078D4',
|
|
2571
|
+
pointerEvents: 'none',
|
|
2572
|
+
zIndex: 2,
|
|
2573
|
+
boxShadow: '0 0 4px rgba(0,120,212,0.5)',
|
|
2574
|
+
display: 'flex',
|
|
2575
|
+
alignItems: 'center',
|
|
2576
|
+
}, children: jsxs("div", { style: {
|
|
2577
|
+
position: 'absolute',
|
|
2578
|
+
padding: '8px',
|
|
2579
|
+
backgroundColor: 'rgba(0, 120, 212, 0.9)',
|
|
2580
|
+
color: 'white',
|
|
2581
|
+
fontSize: '16px',
|
|
2582
|
+
fontWeight: 600,
|
|
2583
|
+
borderRadius: '4px',
|
|
2584
|
+
whiteSpace: 'nowrap',
|
|
2585
|
+
left: '12px',
|
|
2586
|
+
minWidth: '120px',
|
|
2587
|
+
textAlign: 'center',
|
|
2588
|
+
}, children: ["Average fold - ", averageFold.toFixed(0), "%"] }) }));
|
|
2589
|
+
};
|
|
2590
|
+
|
|
2591
|
+
const ScrollmapMarker = ({ iframeRef, wrapperRef }) => {
|
|
2592
|
+
const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
|
|
2593
|
+
const scrollType = useHeatmapConfigStore((state) => state.scrollType);
|
|
2594
|
+
const { getZonePosition } = useZonePositions();
|
|
2595
|
+
if (!scrollmap || scrollmap.length === 0)
|
|
2596
|
+
return null;
|
|
2597
|
+
const findScrollPositionForUserPercent = (targetPercent) => {
|
|
2598
|
+
for (let i = 0; i < scrollmap.length; i++) {
|
|
2599
|
+
if (scrollmap[i].percUsers <= targetPercent) {
|
|
2600
|
+
if (i > 0) {
|
|
2601
|
+
return scrollmap[i - 1].scrollReachY;
|
|
2602
|
+
}
|
|
2603
|
+
return scrollmap[i].scrollReachY;
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
return scrollmap[scrollmap.length - 1]?.scrollReachY || null;
|
|
2607
|
+
};
|
|
2608
|
+
const boundaries = [
|
|
2609
|
+
{ percent: 75, label: '75%', color: '#10B981' },
|
|
2610
|
+
{ percent: 50, label: '50%', color: '#F59E0B' },
|
|
2611
|
+
{ percent: 25, label: '25%', color: '#EF4444' },
|
|
2612
|
+
{ percent: 5, label: '5%', color: '#8B5CF6' },
|
|
2613
|
+
];
|
|
2614
|
+
const isScrollDepth = scrollType === IScrollType.Depth;
|
|
2615
|
+
if (!isScrollDepth)
|
|
2616
|
+
return null;
|
|
2617
|
+
return (jsx(Fragment, { children: boundaries.map((boundary) => {
|
|
2618
|
+
const scrollY = findScrollPositionForUserPercent(boundary.percent);
|
|
2619
|
+
if (scrollY === null)
|
|
2620
|
+
return null;
|
|
2621
|
+
const position = getZonePosition({
|
|
2622
|
+
startY: scrollY,
|
|
2623
|
+
endY: scrollY,
|
|
2624
|
+
});
|
|
2625
|
+
if (!position)
|
|
2626
|
+
return null;
|
|
2627
|
+
return (jsx("div", { className: `marker-boundary-line-${boundary.percent}`, style: {
|
|
2628
|
+
position: 'absolute',
|
|
2629
|
+
top: `${position.top}px`,
|
|
2630
|
+
left: 0,
|
|
2631
|
+
transformOrigin: 'left center',
|
|
2632
|
+
width: '100%',
|
|
2633
|
+
height: '0px',
|
|
2634
|
+
// borderBottom: `2px dashed #323130`,
|
|
2635
|
+
borderBottom: `2px solid ${boundary.color}`,
|
|
2636
|
+
// background: 'repeating-linear-gradient(90deg, #323130, transparent 2px 3px)',
|
|
2637
|
+
zIndex: 1,
|
|
2638
|
+
display: 'flex',
|
|
2639
|
+
alignItems: 'center',
|
|
2640
|
+
}, children: jsx("div", { style: {
|
|
2641
|
+
position: 'absolute',
|
|
2642
|
+
padding: '8px',
|
|
2643
|
+
backgroundColor: boundary.color,
|
|
2644
|
+
color: 'white',
|
|
2645
|
+
fontSize: '16px',
|
|
2646
|
+
fontWeight: 600,
|
|
2647
|
+
borderRadius: '4px',
|
|
2648
|
+
whiteSpace: 'nowrap',
|
|
2649
|
+
left: '12px',
|
|
2650
|
+
minWidth: '120px',
|
|
2651
|
+
textAlign: 'center',
|
|
2652
|
+
// textAlign: 'center',
|
|
2653
|
+
// padding: '8px',
|
|
2654
|
+
// paddingInline: '8px',
|
|
2655
|
+
// fontSize: '16px',
|
|
2656
|
+
// background: '#fff',
|
|
2657
|
+
// width: 'auto',
|
|
2658
|
+
// borderRadius: '4px',
|
|
2659
|
+
// position: 'absolute',
|
|
2660
|
+
// left: '12px',
|
|
2661
|
+
// minWidth: '120px',
|
|
2662
|
+
}, children: boundary.label }) }, boundary.label));
|
|
2663
|
+
}) }));
|
|
2664
|
+
};
|
|
2665
|
+
|
|
2666
|
+
const ScrollMapMinimap = ({ zones, maxUsers }) => {
|
|
2667
|
+
const showMinimap = useHeatmapVizScrollmapStore((state) => state.showMinimap);
|
|
2668
|
+
const scrollType = useHeatmapConfigStore((state) => state.scrollType);
|
|
2669
|
+
const isScrollType = [IScrollType.Attention].includes(scrollType);
|
|
2670
|
+
if (!showMinimap || !isScrollType)
|
|
2671
|
+
return null;
|
|
2672
|
+
return (jsx("div", { style: {
|
|
2673
|
+
position: 'fixed',
|
|
2674
|
+
left: '20px',
|
|
2675
|
+
top: '50%',
|
|
2676
|
+
transform: 'translateY(-50%)',
|
|
2677
|
+
width: '60px',
|
|
2678
|
+
height: '400px',
|
|
2679
|
+
backgroundColor: 'white',
|
|
2680
|
+
borderRadius: '8px',
|
|
2681
|
+
boxShadow: '0 4px 16px rgba(0,0,0,0.15)',
|
|
2682
|
+
zIndex: 10002,
|
|
2683
|
+
padding: '8px',
|
|
2684
|
+
boxSizing: 'border-box',
|
|
2685
|
+
}, children: jsx("div", { style: {
|
|
2686
|
+
width: '100%',
|
|
2687
|
+
height: '100%',
|
|
2688
|
+
borderRadius: '4px',
|
|
2689
|
+
overflow: 'hidden',
|
|
2690
|
+
display: 'flex',
|
|
2691
|
+
flexDirection: 'column',
|
|
2692
|
+
}, children: zones.map((zone) => {
|
|
2693
|
+
const normalized = maxUsers > 0 ? zone.percUsers / maxUsers : 0;
|
|
2694
|
+
const color = getScrollGradientColor(normalized);
|
|
2695
|
+
return (jsx("div", { title: `${zone.label}: ${zone.percUsers.toFixed(2)}%`, style: {
|
|
2696
|
+
width: '100%',
|
|
2697
|
+
flex: `${zone.endY - zone.startY}`,
|
|
2698
|
+
backgroundColor: color,
|
|
2699
|
+
borderBottom: '1px solid rgba(255,255,255,0.2)',
|
|
2700
|
+
} }, zone.id));
|
|
2701
|
+
}) }) }));
|
|
2702
|
+
};
|
|
2703
|
+
|
|
2704
|
+
const ScrollZoneTooltip = ({ zone, position, currentScrollPercent, scrollmap, }) => {
|
|
2705
|
+
const tooltipRef = useRef(null);
|
|
2706
|
+
const currentData = useMemo(() => {
|
|
2707
|
+
if (!scrollmap || scrollmap.length === 0)
|
|
2708
|
+
return null;
|
|
2709
|
+
const roundedPercent = Math.floor(currentScrollPercent);
|
|
2710
|
+
return scrollmap.find((d) => d.scrollReachY === roundedPercent) || null;
|
|
2711
|
+
}, [scrollmap, currentScrollPercent]);
|
|
2712
|
+
return (jsxs("div", { id: "gx-hm-scrollmap-tooltip", ref: tooltipRef, style: {
|
|
2713
|
+
position: 'fixed',
|
|
2714
|
+
top: `${position.y}px`,
|
|
2715
|
+
backgroundColor: 'black',
|
|
2716
|
+
zIndex: 10001,
|
|
2717
|
+
pointerEvents: 'none',
|
|
2718
|
+
width: '100%',
|
|
2719
|
+
height: '2px',
|
|
2720
|
+
}, children: [jsxs("div", { style: {
|
|
2721
|
+
position: 'absolute',
|
|
2722
|
+
left: '50%',
|
|
2723
|
+
top: '-50%',
|
|
2724
|
+
transform: 'translate(-50%, -50%)',
|
|
2725
|
+
padding: '16px',
|
|
2726
|
+
borderRadius: '8px',
|
|
2727
|
+
boxShadow: '0 4px 16px rgba(0,0,0,0.15)',
|
|
2728
|
+
fontSize: '14px',
|
|
2729
|
+
width: 'fit-content',
|
|
2730
|
+
backgroundColor: 'white',
|
|
2731
|
+
minWidth: '230px',
|
|
2732
|
+
display: 'flex',
|
|
2733
|
+
gap: '8px',
|
|
2734
|
+
alignItems: 'center',
|
|
2735
|
+
}, children: [jsxs("p", { style: {
|
|
2736
|
+
fontWeight: 650,
|
|
2737
|
+
fontSize: '20px',
|
|
2738
|
+
lineHeight: '24px',
|
|
2739
|
+
letterSpacing: '-0.2px',
|
|
2740
|
+
verticalAlign: 'middle',
|
|
2741
|
+
fontVariantNumeric: 'tabular-nums',
|
|
2742
|
+
}, children: [currentData?.percUsers?.toFixed(2), "%", ' '] }), jsx("p", { style: { fontWeight: 450 }, children: "user scrolled this far" })] }), jsx(TooltipByZone, { zone: zone })] }));
|
|
2743
|
+
};
|
|
2744
|
+
const TooltipByZone = ({ zone }) => {
|
|
2745
|
+
const scrollType = useHeatmapConfigStore((state) => state.scrollType);
|
|
2746
|
+
if (!zone)
|
|
2747
|
+
return null;
|
|
2748
|
+
const contentMarkup = () => {
|
|
2749
|
+
switch (scrollType) {
|
|
2750
|
+
case IScrollType.Depth:
|
|
2751
|
+
return jsx(BasicTooltipContent, { zone: zone });
|
|
2752
|
+
case IScrollType.Attention:
|
|
2753
|
+
return jsx(MetricsTooltipContent, { zone: zone });
|
|
2754
|
+
default:
|
|
2755
|
+
return jsx(BasicTooltipContent, { zone: zone });
|
|
2756
|
+
}
|
|
2757
|
+
};
|
|
2758
|
+
return (jsx("div", { style: { paddingTop: '12px', borderTop: '1px solid #E5E7EB' }, children: contentMarkup() }));
|
|
2759
|
+
};
|
|
2760
|
+
const BasicTooltipContent = ({ zone }) => {
|
|
2761
|
+
if (!zone)
|
|
2762
|
+
return null;
|
|
2763
|
+
return (jsxs(Fragment, { children: [jsx("div", { style: { fontWeight: 600, marginBottom: '8px' }, children: zone.label }), jsxs("div", { style: { fontSize: '24px', fontWeight: 700, color: '#0078D4' }, children: [zone.percUsers.toFixed(2), "%"] }), jsx("div", { style: { fontSize: '12px', color: '#605E5C', marginTop: '4px' }, children: "of users reached this point" })] }));
|
|
2764
|
+
};
|
|
2765
|
+
const MetricsTooltipContent = ({ zone }) => {
|
|
2766
|
+
if (!zone)
|
|
2767
|
+
return null;
|
|
2768
|
+
return (jsxs(Fragment, { children: [jsx("div", { style: { fontWeight: 600, marginBottom: '8px' }, children: zone.label }), jsxs("div", { style: { fontSize: '20px', fontWeight: 700, marginBottom: '8px' }, children: [zone.percUsers.toFixed(2), "% users"] }), zone.metrics && (jsxs("div", { style: { display: 'grid', gap: '6px', fontSize: '13px' }, children: [zone.metrics.revenue !== undefined && (jsx(MetricRow, { label: "Revenue", value: `$${zone.metrics.revenue.toFixed(2)}` })), zone.metrics.conversionRate !== undefined && (jsx(MetricRow, { label: "Conversion", value: `${zone.metrics.conversionRate.toFixed(2)}%` })), zone.metrics.orders !== undefined && (jsx(MetricRow, { label: "Orders", value: zone.metrics.orders.toString() }))] }))] }));
|
|
2769
|
+
};
|
|
2770
|
+
const MetricRow = ({ label, value }) => (jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [jsxs("span", { style: { color: '#605E5C' }, children: [label, ":"] }), jsx("span", { style: { fontWeight: 600 }, children: value })] }));
|
|
2771
|
+
|
|
2772
|
+
const HoverZones = ({ iframeRef, wrapperRef, position, currentScrollPercent, }) => {
|
|
2773
|
+
const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
|
|
2774
|
+
// const hoveredZone = useHeatmapVizScrollmapStore((state) => state.hoveredZone);
|
|
2775
|
+
// const setHoveredZone = useHeatmapVizScrollmapStore((state) => state.setHoveredZone);
|
|
2776
|
+
const { zones, isReady, maxUsers } = useScrollmapZones({
|
|
2777
|
+
iframeRef,
|
|
2778
|
+
wrapperRef,
|
|
2779
|
+
});
|
|
2780
|
+
if (!isReady || !zones.length)
|
|
2781
|
+
return null;
|
|
2782
|
+
if (!position)
|
|
2783
|
+
return null;
|
|
2784
|
+
return (jsxs(Fragment, { children: [jsx(ScrollZoneTooltip, { position: position, currentScrollPercent: currentScrollPercent, scrollmap: scrollmap || [] }), jsx(ScrollMapMinimap, { zones: zones, maxUsers: maxUsers })] }));
|
|
2785
|
+
};
|
|
2786
|
+
|
|
2787
|
+
const ScrollMapOverlay = ({ wrapperRef, iframeRef }) => {
|
|
2788
|
+
const overlayRef = useRef(null);
|
|
2789
|
+
const [position, setPosition] = useState();
|
|
2790
|
+
const [currentScrollPercent, setCurrentScrollPercent] = useState(0);
|
|
2791
|
+
const widthScale = useHeatmapVizStore((state) => state.scale);
|
|
2792
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
2793
|
+
const handleMouseMove = (event) => {
|
|
2794
|
+
if (!iframeRef.current || !wrapperRef.current)
|
|
2795
|
+
return;
|
|
2796
|
+
const iframe = iframeRef.current;
|
|
2797
|
+
const iframeRect = iframe.getBoundingClientRect();
|
|
2798
|
+
const { x, y } = convertViewportToIframeCoords(event.clientX, event.clientY, iframeRect, widthScale);
|
|
2799
|
+
const wrapperEl = wrapperRef.current;
|
|
2800
|
+
const scrollOffset = (wrapperEl?.scrollTop || 0) / widthScale;
|
|
2801
|
+
const actualY = y + scrollOffset;
|
|
2802
|
+
const scrollPercent = Math.min(100, Math.max(0, (actualY / iframeHeight) * 100));
|
|
2803
|
+
setCurrentScrollPercent(scrollPercent);
|
|
2804
|
+
setPosition({ x, y });
|
|
2805
|
+
};
|
|
2806
|
+
const onMouseMove = useCallback((event) => {
|
|
2807
|
+
requestAnimationFrame(() => handleMouseMove(event));
|
|
2808
|
+
}, [handleMouseMove]);
|
|
2809
|
+
const onMouseLeave = () => {
|
|
2810
|
+
requestAnimationFrame(() => {
|
|
2811
|
+
setCurrentScrollPercent(0);
|
|
2812
|
+
setPosition(undefined);
|
|
2813
|
+
});
|
|
2814
|
+
};
|
|
2815
|
+
return (jsx("div", { ref: overlayRef, id: "gx-hm-scrollmap-overlay", onMouseMove: onMouseMove, onMouseLeave: onMouseLeave, style: {
|
|
2816
|
+
position: 'absolute',
|
|
2817
|
+
top: 0,
|
|
2818
|
+
left: 0,
|
|
2819
|
+
width: '100%',
|
|
2820
|
+
height: `${iframeHeight}px`,
|
|
2821
|
+
zIndex: 3,
|
|
2822
|
+
}, children: jsx(HoverZones, { position: position, currentScrollPercent: currentScrollPercent, iframeRef: iframeRef, wrapperRef: wrapperRef }) }));
|
|
2823
|
+
};
|
|
2824
|
+
|
|
2825
|
+
const SCROLL_TYPES = [IHeatmapType.Scroll];
|
|
2826
|
+
const VizScrollMap = ({ iframeRef, wrapperRef }) => {
|
|
2827
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
2828
|
+
const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
|
|
2829
|
+
const isHeatmapScroll = SCROLL_TYPES.includes(heatmapType);
|
|
2830
|
+
if (!iframeHeight || !isHeatmapScroll)
|
|
2831
|
+
return null;
|
|
2832
|
+
return (jsxs("div", { style: {
|
|
2833
|
+
position: 'absolute',
|
|
2834
|
+
top: 0,
|
|
2835
|
+
left: '2px',
|
|
2836
|
+
width: `calc(100% - 4px)`,
|
|
2837
|
+
height: '100%',
|
|
2838
|
+
transform: 'translateZ(0)',
|
|
2839
|
+
}, children: [jsx(ScrollmapMarker, { iframeRef: iframeRef, wrapperRef: wrapperRef }), jsx(AverageFoldLine, { iframeRef: iframeRef, wrapperRef: wrapperRef }), jsx(ScrollMapOverlay, { wrapperRef: wrapperRef, iframeRef: iframeRef })] }));
|
|
2840
|
+
};
|
|
2841
|
+
|
|
2579
2842
|
const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHeight, onScroll, }) => {
|
|
2580
2843
|
const contentWidth = useHeatmapConfigStore((state) => state.width);
|
|
2581
2844
|
const widthScale = useHeatmapVizStore((state) => state.scale);
|
|
@@ -2610,6 +2873,7 @@ const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHe
|
|
|
2610
2873
|
|
|
2611
2874
|
const VizDomRenderer = ({ mode = 'heatmap' }) => {
|
|
2612
2875
|
const width = useHeatmapConfigStore((state) => state.width);
|
|
2876
|
+
const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
|
|
2613
2877
|
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
2614
2878
|
const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
|
|
2615
2879
|
const setSelectedElement = useHeatmapInteractionStore((state) => state.setSelectedElement);
|
|
@@ -2627,7 +2891,7 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
|
|
|
2627
2891
|
const scrollTop = e.currentTarget.scrollTop;
|
|
2628
2892
|
handleScroll(scrollTop);
|
|
2629
2893
|
};
|
|
2630
|
-
|
|
2894
|
+
useHeatmapCanvas({ iframeRef: iframeRef });
|
|
2631
2895
|
const cleanUp = () => {
|
|
2632
2896
|
setIframeHeight(0);
|
|
2633
2897
|
setSelectedElement(null);
|
|
@@ -2635,7 +2899,7 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
|
|
|
2635
2899
|
useEffect(() => {
|
|
2636
2900
|
return cleanUp;
|
|
2637
2901
|
}, []);
|
|
2638
|
-
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" })] }));
|
|
2902
|
+
return (jsxs(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, onScroll: onScroll, iframeHeight: iframeHeight, children: [heatmapType === IHeatmapType.Click && (jsx(VizElements, { iframeRef: iframeRef, visualRef: visualRef, wrapperRef: wrapperRef })), jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: contentWidth, scrolling: "no" }), jsx(VizScrollMap, { iframeRef: iframeRef, wrapperRef: visualRef })] }));
|
|
2639
2903
|
};
|
|
2640
2904
|
|
|
2641
2905
|
const VizLoading = () => {
|
|
@@ -2742,10 +3006,10 @@ const WrapperLayout = () => {
|
|
|
2742
3006
|
return (jsxs(BoxStack, { id: "gx-hm-layout", flexDirection: "column", flex: "1", children: [jsx(ContentTopBar, {}), jsx(WrapperPreview, {})] }));
|
|
2743
3007
|
};
|
|
2744
3008
|
|
|
2745
|
-
const HeatmapLayout = ({ data, clickmap, controls, dataInfo, }) => {
|
|
3009
|
+
const HeatmapLayout = ({ data, clickmap, scrollmap, controls, dataInfo, }) => {
|
|
2746
3010
|
useRegisterControl(controls);
|
|
2747
3011
|
useRegisterData(data, dataInfo);
|
|
2748
|
-
useRegisterHeatmap(clickmap);
|
|
3012
|
+
useRegisterHeatmap({ clickmap, scrollmap });
|
|
2749
3013
|
useRegisterConfig();
|
|
2750
3014
|
return (jsx(BoxStack, { id: "gx-hm-project", flexDirection: "column", flex: "1", height: "100%", style: getVariableStyle(), children: jsx(BoxStack, { id: "gx-hm-project-content", flexDirection: "column", flex: "1", children: jsx("div", { style: {
|
|
2751
3015
|
minHeight: '100%',
|
|
@@ -2760,4 +3024,4 @@ const HeatmapLayout = ({ data, clickmap, controls, dataInfo, }) => {
|
|
|
2760
3024
|
}
|
|
2761
3025
|
};
|
|
2762
3026
|
|
|
2763
|
-
export { GraphView, HeatmapLayout, IHeatmapType, useHeatmapConfigStore, useHeatmapDataStore, useHeatmapInteractionStore, useHeatmapLiveStore, useHeatmapVizStore };
|
|
3027
|
+
export { GraphView, HeatmapLayout, IClickType, IHeatmapType, IScrollType, useHeatmapConfigStore, useHeatmapDataStore, useHeatmapInteractionStore, useHeatmapLiveStore, useHeatmapVizStore };
|