@gemx-dev/heatmap-react 3.5.92-dev.15 → 3.5.92-dev.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/VizDom/VizDomHeatmap.d.ts.map +1 -1
- package/dist/esm/components/VizDom/VizDomRenderer.d.ts +2 -1
- package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/esm/hooks/common/index.d.ts +1 -1
- package/dist/esm/hooks/common/index.d.ts.map +1 -1
- package/dist/esm/hooks/common/useHeatmapViewportByDevice.d.ts +7 -0
- package/dist/esm/hooks/common/useHeatmapViewportByDevice.d.ts.map +1 -0
- package/dist/esm/hooks/view-context/useHeatmapVizContext.d.ts +2 -2
- package/dist/esm/hooks/view-context/useHeatmapVizContext.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-render/useHeatmapIframeProcessor.d.ts +6 -0
- package/dist/esm/hooks/viz-render/useHeatmapIframeProcessor.d.ts.map +1 -0
- package/dist/esm/hooks/viz-render/useHeatmapRenderByMode.d.ts +3 -2
- package/dist/esm/hooks/viz-render/useHeatmapRenderByMode.d.ts.map +1 -1
- package/dist/esm/hooks/viz-render/useHeatmapRenderDom.d.ts +5 -0
- package/dist/esm/hooks/viz-render/useHeatmapRenderDom.d.ts.map +1 -0
- package/dist/esm/hooks/viz-render/useReplayRender.d.ts +2 -2
- package/dist/esm/hooks/viz-render/useReplayRender.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useScaleCalculation.d.ts +1 -2
- package/dist/esm/hooks/viz-scale/useScaleCalculation.d.ts.map +1 -1
- package/dist/esm/index.js +697 -185
- package/dist/esm/index.mjs +697 -185
- package/dist/esm/libs/visualizer/GXVisualizer.d.ts +7 -1
- package/dist/esm/libs/visualizer/GXVisualizer.d.ts.map +1 -1
- package/dist/esm/libs/visualizer/cache/config.d.ts +15 -0
- package/dist/esm/libs/visualizer/cache/config.d.ts.map +1 -0
- package/dist/esm/libs/visualizer/cache/index.d.ts +16 -0
- package/dist/esm/libs/visualizer/cache/index.d.ts.map +1 -0
- package/dist/esm/libs/visualizer/index.d.ts +1 -2
- package/dist/esm/libs/visualizer/index.d.ts.map +1 -1
- package/dist/esm/libs/visualizer/{AttentionMapRenderer.d.ts → renderers/AttentionMapRenderer.d.ts} +1 -1
- package/dist/esm/libs/visualizer/renderers/AttentionMapRenderer.d.ts.map +1 -0
- package/dist/esm/libs/visualizer/{ClickHeatmapRenderer.d.ts → renderers/ClickHeatmapRenderer.d.ts} +1 -1
- package/dist/esm/libs/visualizer/renderers/ClickHeatmapRenderer.d.ts.map +1 -0
- package/dist/esm/libs/visualizer/renderers/index.d.ts +3 -0
- package/dist/esm/libs/visualizer/renderers/index.d.ts.map +1 -0
- package/dist/esm/libs/visualizer/shadow-dom/extractor.d.ts +23 -0
- package/dist/esm/libs/visualizer/shadow-dom/extractor.d.ts.map +1 -0
- package/dist/esm/libs/visualizer/types/data.d.ts +72 -0
- package/dist/esm/libs/visualizer/types/data.d.ts.map +1 -0
- package/dist/esm/libs/visualizer/{types.d.ts → types/extend.d.ts} +7 -2
- package/dist/esm/libs/visualizer/types/extend.d.ts.map +1 -0
- package/dist/esm/libs/visualizer/types/index.d.ts +6 -0
- package/dist/esm/libs/visualizer/types/index.d.ts.map +1 -0
- package/dist/esm/libs/visualizer/types/layout.d.ts +69 -0
- package/dist/esm/libs/visualizer/types/layout.d.ts.map +1 -0
- package/dist/esm/libs/visualizer/types/visualize.d.ts +7 -0
- package/dist/esm/libs/visualizer/types/visualize.d.ts.map +1 -0
- package/dist/esm/stores/viz.d.ts +2 -2
- package/dist/esm/stores/viz.d.ts.map +1 -1
- package/dist/esm/types/heatmap-info.d.ts +1 -0
- package/dist/esm/types/heatmap-info.d.ts.map +1 -1
- package/dist/esm/types/heatmap.d.ts +4 -0
- package/dist/esm/types/heatmap.d.ts.map +1 -1
- package/dist/umd/components/VizDom/VizDomHeatmap.d.ts.map +1 -1
- package/dist/umd/components/VizDom/VizDomRenderer.d.ts +2 -1
- package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/umd/hooks/common/index.d.ts +1 -1
- package/dist/umd/hooks/common/index.d.ts.map +1 -1
- package/dist/umd/hooks/common/useHeatmapViewportByDevice.d.ts +7 -0
- package/dist/umd/hooks/common/useHeatmapViewportByDevice.d.ts.map +1 -0
- package/dist/umd/hooks/view-context/useHeatmapVizContext.d.ts +2 -2
- package/dist/umd/hooks/view-context/useHeatmapVizContext.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-render/useHeatmapIframeProcessor.d.ts +6 -0
- package/dist/umd/hooks/viz-render/useHeatmapIframeProcessor.d.ts.map +1 -0
- package/dist/umd/hooks/viz-render/useHeatmapRenderByMode.d.ts +3 -2
- package/dist/umd/hooks/viz-render/useHeatmapRenderByMode.d.ts.map +1 -1
- package/dist/umd/hooks/viz-render/useHeatmapRenderDom.d.ts +5 -0
- package/dist/umd/hooks/viz-render/useHeatmapRenderDom.d.ts.map +1 -0
- package/dist/umd/hooks/viz-render/useReplayRender.d.ts +2 -2
- package/dist/umd/hooks/viz-render/useReplayRender.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useScaleCalculation.d.ts +1 -2
- package/dist/umd/hooks/viz-scale/useScaleCalculation.d.ts.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/libs/visualizer/GXVisualizer.d.ts +7 -1
- package/dist/umd/libs/visualizer/GXVisualizer.d.ts.map +1 -1
- package/dist/umd/libs/visualizer/cache/config.d.ts +15 -0
- package/dist/umd/libs/visualizer/cache/config.d.ts.map +1 -0
- package/dist/umd/libs/visualizer/cache/index.d.ts +16 -0
- package/dist/umd/libs/visualizer/cache/index.d.ts.map +1 -0
- package/dist/umd/libs/visualizer/index.d.ts +1 -2
- package/dist/umd/libs/visualizer/index.d.ts.map +1 -1
- package/dist/umd/libs/visualizer/{AttentionMapRenderer.d.ts → renderers/AttentionMapRenderer.d.ts} +1 -1
- package/dist/umd/libs/visualizer/renderers/AttentionMapRenderer.d.ts.map +1 -0
- package/dist/umd/libs/visualizer/{ClickHeatmapRenderer.d.ts → renderers/ClickHeatmapRenderer.d.ts} +1 -1
- package/dist/umd/libs/visualizer/renderers/ClickHeatmapRenderer.d.ts.map +1 -0
- package/dist/umd/libs/visualizer/renderers/index.d.ts +3 -0
- package/dist/umd/libs/visualizer/renderers/index.d.ts.map +1 -0
- package/dist/umd/libs/visualizer/shadow-dom/extractor.d.ts +23 -0
- package/dist/umd/libs/visualizer/shadow-dom/extractor.d.ts.map +1 -0
- package/dist/umd/libs/visualizer/types/data.d.ts +72 -0
- package/dist/umd/libs/visualizer/types/data.d.ts.map +1 -0
- package/dist/umd/libs/visualizer/{types.d.ts → types/extend.d.ts} +7 -2
- package/dist/umd/libs/visualizer/types/extend.d.ts.map +1 -0
- package/dist/umd/libs/visualizer/types/index.d.ts +6 -0
- package/dist/umd/libs/visualizer/types/index.d.ts.map +1 -0
- package/dist/umd/libs/visualizer/types/layout.d.ts +69 -0
- package/dist/umd/libs/visualizer/types/layout.d.ts.map +1 -0
- package/dist/umd/libs/visualizer/types/visualize.d.ts +7 -0
- package/dist/umd/libs/visualizer/types/visualize.d.ts.map +1 -0
- package/dist/umd/stores/viz.d.ts +2 -2
- package/dist/umd/stores/viz.d.ts.map +1 -1
- package/dist/umd/types/heatmap-info.d.ts +1 -0
- package/dist/umd/types/heatmap-info.d.ts.map +1 -1
- package/dist/umd/types/heatmap.d.ts +4 -0
- package/dist/umd/types/heatmap.d.ts.map +1 -1
- package/package.json +4 -4
- package/dist/esm/hooks/common/useHeatmapWidthByDevice.d.ts +0 -2
- package/dist/esm/hooks/common/useHeatmapWidthByDevice.d.ts.map +0 -1
- package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts +0 -5
- package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +0 -1
- package/dist/esm/hooks/viz-scale/useContentDimensions.d.ts +0 -9
- package/dist/esm/hooks/viz-scale/useContentDimensions.d.ts.map +0 -1
- package/dist/esm/libs/visualizer/AttentionMapRenderer.d.ts.map +0 -1
- package/dist/esm/libs/visualizer/ClickHeatmapRenderer.d.ts.map +0 -1
- package/dist/esm/libs/visualizer/ScrollHeatmapRenderer.d.ts +0 -17
- package/dist/esm/libs/visualizer/ScrollHeatmapRenderer.d.ts.map +0 -1
- package/dist/esm/libs/visualizer/types.d.ts.map +0 -1
- package/dist/umd/hooks/common/useHeatmapWidthByDevice.d.ts +0 -2
- package/dist/umd/hooks/common/useHeatmapWidthByDevice.d.ts.map +0 -1
- package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts +0 -5
- package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +0 -1
- package/dist/umd/hooks/viz-scale/useContentDimensions.d.ts +0 -9
- package/dist/umd/hooks/viz-scale/useContentDimensions.d.ts.map +0 -1
- package/dist/umd/libs/visualizer/AttentionMapRenderer.d.ts.map +0 -1
- package/dist/umd/libs/visualizer/ClickHeatmapRenderer.d.ts.map +0 -1
- package/dist/umd/libs/visualizer/ScrollHeatmapRenderer.d.ts +0 -17
- package/dist/umd/libs/visualizer/ScrollHeatmapRenderer.d.ts.map +0 -1
- package/dist/umd/libs/visualizer/types.d.ts.map +0 -1
package/dist/esm/index.mjs
CHANGED
|
@@ -162,6 +162,11 @@ var EHeatmapType;
|
|
|
162
162
|
EHeatmapType["Click"] = "click";
|
|
163
163
|
EHeatmapType["Scroll"] = "scroll";
|
|
164
164
|
})(EHeatmapType || (EHeatmapType = {}));
|
|
165
|
+
var EHeatmapMode;
|
|
166
|
+
(function (EHeatmapMode) {
|
|
167
|
+
EHeatmapMode["Heatmap"] = "heatmap";
|
|
168
|
+
EHeatmapMode["Replay"] = "replay";
|
|
169
|
+
})(EHeatmapMode || (EHeatmapMode = {}));
|
|
165
170
|
var EClickType;
|
|
166
171
|
(function (EClickType) {
|
|
167
172
|
/** Return all clicks (default) */
|
|
@@ -198,7 +203,6 @@ var EScrollType;
|
|
|
198
203
|
EScrollType["Attention"] = "ATTENTION";
|
|
199
204
|
EScrollType["Revenue"] = "REVENUE";
|
|
200
205
|
})(EScrollType || (EScrollType = {}));
|
|
201
|
-
var EHeatmapMode;
|
|
202
206
|
(function (EHeatmapMode) {
|
|
203
207
|
EHeatmapMode["Single"] = "single";
|
|
204
208
|
EHeatmapMode["Live"] = "live";
|
|
@@ -620,16 +624,16 @@ const useHeatmapSettingStore = create()(subscribeWithSelector((set) => {
|
|
|
620
624
|
|
|
621
625
|
const useHeatmapVizStore = create()(subscribeWithSelector((set) => {
|
|
622
626
|
return {
|
|
623
|
-
|
|
627
|
+
isDomLoaded: new Map([[DEFAULT_VIEW_ID, false]]),
|
|
624
628
|
zoomRatio: new Map([[DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO.DEFAULT]]),
|
|
625
629
|
minZoomRatio: new Map([[DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO.MIN]]),
|
|
626
630
|
maxZoomRatio: new Map([[DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO.MAX]]),
|
|
627
631
|
scale: new Map([[DEFAULT_VIEW_ID, 1]]),
|
|
628
632
|
isScaledToFit: new Map([[DEFAULT_VIEW_ID, false]]),
|
|
629
|
-
|
|
630
|
-
const
|
|
631
|
-
|
|
632
|
-
return {
|
|
633
|
+
setIsDomLoaded: (isDomLoaded, viewId = DEFAULT_VIEW_ID) => set((prev) => {
|
|
634
|
+
const newIsDomLoaded = new Map(prev.isDomLoaded);
|
|
635
|
+
newIsDomLoaded.set(viewId, isDomLoaded);
|
|
636
|
+
return { isDomLoaded: newIsDomLoaded };
|
|
633
637
|
}),
|
|
634
638
|
setZoomRatio: (zoomRatio, viewId = DEFAULT_VIEW_ID) => set((prev) => {
|
|
635
639
|
const newZoomRatio = new Map(prev.zoomRatio);
|
|
@@ -657,18 +661,18 @@ const useHeatmapVizStore = create()(subscribeWithSelector((set) => {
|
|
|
657
661
|
return { isScaledToFit: newIsScaledToFit };
|
|
658
662
|
}),
|
|
659
663
|
copyView: (fromViewId, toViewId) => set((prev) => {
|
|
660
|
-
const
|
|
664
|
+
const newIsDomLoaded = new Map(prev.isDomLoaded);
|
|
661
665
|
const newZoomRatio = new Map(prev.zoomRatio);
|
|
662
666
|
const newMinZoomRatio = new Map(prev.minZoomRatio);
|
|
663
667
|
const newScale = new Map(prev.scale);
|
|
664
668
|
const newIsScaledToFit = new Map(prev.isScaledToFit);
|
|
665
|
-
|
|
669
|
+
newIsDomLoaded.set(toViewId, prev.isDomLoaded.get(fromViewId) ?? false);
|
|
666
670
|
newZoomRatio.set(toViewId, prev.zoomRatio.get(fromViewId) ?? 100);
|
|
667
671
|
newMinZoomRatio.set(toViewId, prev.minZoomRatio.get(fromViewId) ?? 10);
|
|
668
672
|
newScale.set(toViewId, prev.scale.get(fromViewId) ?? 1);
|
|
669
673
|
newIsScaledToFit.set(toViewId, prev.isScaledToFit.get(fromViewId) ?? false);
|
|
670
674
|
return {
|
|
671
|
-
|
|
675
|
+
isDomLoaded: newIsDomLoaded,
|
|
672
676
|
zoomRatio: newZoomRatio,
|
|
673
677
|
minZoomRatio: newMinZoomRatio,
|
|
674
678
|
scale: newScale,
|
|
@@ -676,18 +680,18 @@ const useHeatmapVizStore = create()(subscribeWithSelector((set) => {
|
|
|
676
680
|
};
|
|
677
681
|
}),
|
|
678
682
|
clearView: (viewId) => set((prev) => {
|
|
679
|
-
const
|
|
683
|
+
const newIsDomLoaded = new Map(prev.isDomLoaded);
|
|
680
684
|
const newZoomRatio = new Map(prev.zoomRatio);
|
|
681
685
|
const newMinZoomRatio = new Map(prev.minZoomRatio);
|
|
682
686
|
const newScale = new Map(prev.scale);
|
|
683
687
|
const newIsScaledToFit = new Map(prev.isScaledToFit);
|
|
684
|
-
|
|
688
|
+
newIsDomLoaded.delete(viewId);
|
|
685
689
|
newZoomRatio.delete(viewId);
|
|
686
690
|
newMinZoomRatio.delete(viewId);
|
|
687
691
|
newScale.delete(viewId);
|
|
688
692
|
newIsScaledToFit.delete(viewId);
|
|
689
693
|
return {
|
|
690
|
-
|
|
694
|
+
isDomLoaded: newIsDomLoaded,
|
|
691
695
|
zoomRatio: newZoomRatio,
|
|
692
696
|
minZoomRatio: newMinZoomRatio,
|
|
693
697
|
scale: newScale,
|
|
@@ -695,7 +699,7 @@ const useHeatmapVizStore = create()(subscribeWithSelector((set) => {
|
|
|
695
699
|
};
|
|
696
700
|
}),
|
|
697
701
|
resetAll: () => set({
|
|
698
|
-
|
|
702
|
+
isDomLoaded: new Map([[DEFAULT_VIEW_ID, false]]),
|
|
699
703
|
zoomRatio: new Map([[DEFAULT_VIEW_ID, 100]]),
|
|
700
704
|
minZoomRatio: new Map([[DEFAULT_VIEW_ID, 10]]),
|
|
701
705
|
scale: new Map([[DEFAULT_VIEW_ID, 1]]),
|
|
@@ -1415,7 +1419,7 @@ const useHeatmapSettingContext = createViewContextHook({
|
|
|
1415
1419
|
const useHeatmapVizContext = createViewContextHook({
|
|
1416
1420
|
useStore: useHeatmapVizStore,
|
|
1417
1421
|
getState: (store, viewId) => ({
|
|
1418
|
-
|
|
1422
|
+
isDomLoaded: store.isDomLoaded.get(viewId) ?? false,
|
|
1419
1423
|
zoomRatio: store.zoomRatio.get(viewId) ?? DEFAULT_ZOOM_RATIO.DEFAULT,
|
|
1420
1424
|
minZoomRatio: store.minZoomRatio.get(viewId) ?? DEFAULT_ZOOM_RATIO.MIN,
|
|
1421
1425
|
maxZoomRatio: store.maxZoomRatio.get(viewId) ?? DEFAULT_ZOOM_RATIO.MAX,
|
|
@@ -1423,7 +1427,7 @@ const useHeatmapVizContext = createViewContextHook({
|
|
|
1423
1427
|
isScaledToFit: store.isScaledToFit.get(viewId) ?? false,
|
|
1424
1428
|
}),
|
|
1425
1429
|
getActions: (store, viewId) => ({
|
|
1426
|
-
|
|
1430
|
+
setIsDomLoaded: (value) => store.setIsDomLoaded(value, viewId),
|
|
1427
1431
|
setZoomRatio: (value) => store.setZoomRatio(value, viewId),
|
|
1428
1432
|
setMinZoomRatio: (value) => store.setMinZoomRatio(value, viewId),
|
|
1429
1433
|
setMaxZoomRatio: (value) => store.setMaxZoomRatio(value, viewId),
|
|
@@ -1525,10 +1529,11 @@ const useHeatmapCopyView = () => {
|
|
|
1525
1529
|
};
|
|
1526
1530
|
};
|
|
1527
1531
|
|
|
1528
|
-
const
|
|
1532
|
+
const useHeatmapViewportByDevice = () => {
|
|
1529
1533
|
const deviceType = useHeatmapSettingContext((state) => state.deviceType);
|
|
1530
1534
|
const width = useMemo(() => calcWidthByDeviceType(deviceType), [deviceType]);
|
|
1531
|
-
|
|
1535
|
+
const height = useMemo(() => calcHeightByDeviceType(deviceType), [deviceType]);
|
|
1536
|
+
return { width, height };
|
|
1532
1537
|
function calcWidthByDeviceType(deviceType) {
|
|
1533
1538
|
if (!deviceType)
|
|
1534
1539
|
return 1440;
|
|
@@ -1543,6 +1548,20 @@ const useHeatmapWidthByDevice = () => {
|
|
|
1543
1548
|
return 375;
|
|
1544
1549
|
}
|
|
1545
1550
|
}
|
|
1551
|
+
function calcHeightByDeviceType(deviceType) {
|
|
1552
|
+
if (!deviceType)
|
|
1553
|
+
return 900;
|
|
1554
|
+
switch (deviceType) {
|
|
1555
|
+
case EDeviceType.DesktopLarge:
|
|
1556
|
+
return 1080; // 1920×1080
|
|
1557
|
+
case EDeviceType.Desktop:
|
|
1558
|
+
return 900; // 1440×900
|
|
1559
|
+
case EDeviceType.Tablet:
|
|
1560
|
+
return 1024; // 768×1024 (iPad portrait)
|
|
1561
|
+
case EDeviceType.Mobile:
|
|
1562
|
+
return 812; // 375×812 (iPhone X/11/12/13)
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1546
1565
|
};
|
|
1547
1566
|
|
|
1548
1567
|
const useRegisterConfig = ({ shopId, isLoading, isLoadingCanvas, excludeClassNames, }) => {
|
|
@@ -1567,7 +1586,7 @@ const useRegisterConfig = ({ shopId, isLoading, isLoadingCanvas, excludeClassNam
|
|
|
1567
1586
|
setIsRendering(true);
|
|
1568
1587
|
setTimeout(() => {
|
|
1569
1588
|
setIsRendering(false);
|
|
1570
|
-
},
|
|
1589
|
+
}, 500);
|
|
1571
1590
|
}, [mode, deviceType, sidebarWidth]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
1572
1591
|
useEffect(() => {
|
|
1573
1592
|
setIsRendering(!!isLoading);
|
|
@@ -3504,18 +3523,31 @@ const useAreaClickmap = () => {
|
|
|
3504
3523
|
const useClickmap = () => {
|
|
3505
3524
|
const vizRef = useHeatmapVizRectContext((s) => s.vizRef);
|
|
3506
3525
|
const clickmap = useHeatmapDataContext((s) => s.clickmap);
|
|
3507
|
-
const
|
|
3526
|
+
const isDomLoaded = useHeatmapVizContext((s) => s.isDomLoaded);
|
|
3527
|
+
const timerRef = useRef(null);
|
|
3508
3528
|
const start = useCallback(() => {
|
|
3509
|
-
if (!vizRef || !clickmap || clickmap.length === 0 || !
|
|
3529
|
+
if (!vizRef || !clickmap || clickmap.length === 0 || !isDomLoaded)
|
|
3510
3530
|
return;
|
|
3511
3531
|
try {
|
|
3512
|
-
|
|
3513
|
-
|
|
3532
|
+
if (timerRef.current)
|
|
3533
|
+
clearTimeout(timerRef.current);
|
|
3534
|
+
timerRef.current = setTimeout(() => {
|
|
3535
|
+
vizRef?.clearmap?.();
|
|
3536
|
+
vizRef?.clickmap?.(clickmap);
|
|
3537
|
+
}, 100);
|
|
3514
3538
|
}
|
|
3515
3539
|
catch (error) {
|
|
3516
3540
|
console.error(`🚀 🐥 ~ useClickmap ~ error:`, error);
|
|
3517
3541
|
}
|
|
3518
|
-
|
|
3542
|
+
finally {
|
|
3543
|
+
timerRef.current = null;
|
|
3544
|
+
}
|
|
3545
|
+
}, [vizRef, clickmap, isDomLoaded]);
|
|
3546
|
+
useEffect(() => {
|
|
3547
|
+
return () => {
|
|
3548
|
+
timerRef.current && clearTimeout(timerRef.current);
|
|
3549
|
+
};
|
|
3550
|
+
}, []);
|
|
3519
3551
|
return { start };
|
|
3520
3552
|
};
|
|
3521
3553
|
|
|
@@ -3523,6 +3555,7 @@ const useScrollmap = () => {
|
|
|
3523
3555
|
const vizRef = useHeatmapVizRectContext((s) => s.vizRef);
|
|
3524
3556
|
const scrollType = useHeatmapSettingContext((s) => s.scrollType);
|
|
3525
3557
|
const scrollmap = useHeatmapDataContext((s) => s.scrollmap);
|
|
3558
|
+
const isDomLoaded = useHeatmapVizContext((s) => s.isDomLoaded);
|
|
3526
3559
|
useMemo(() => {
|
|
3527
3560
|
switch (scrollType) {
|
|
3528
3561
|
case EScrollType.Depth:
|
|
@@ -3536,7 +3569,7 @@ const useScrollmap = () => {
|
|
|
3536
3569
|
}
|
|
3537
3570
|
}, [scrollmap, scrollType]);
|
|
3538
3571
|
const start = useCallback(() => {
|
|
3539
|
-
if (!vizRef || !scrollmap || scrollmap.length === 0)
|
|
3572
|
+
if (!vizRef || !scrollmap || scrollmap.length === 0 || !isDomLoaded)
|
|
3540
3573
|
return;
|
|
3541
3574
|
try {
|
|
3542
3575
|
vizRef?.clearmap?.();
|
|
@@ -3545,7 +3578,7 @@ const useScrollmap = () => {
|
|
|
3545
3578
|
catch (error) {
|
|
3546
3579
|
logger$4.error(`🚀 🐥 ~ useScrollmap ~ error:`, error);
|
|
3547
3580
|
}
|
|
3548
|
-
}, [vizRef, scrollmap]);
|
|
3581
|
+
}, [vizRef, scrollmap, isDomLoaded]);
|
|
3549
3582
|
return { start };
|
|
3550
3583
|
};
|
|
3551
3584
|
|
|
@@ -3709,7 +3742,7 @@ const useHeatmapEffects = ({ isVisible }) => {
|
|
|
3709
3742
|
};
|
|
3710
3743
|
|
|
3711
3744
|
const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
|
|
3712
|
-
const
|
|
3745
|
+
const viewport = useHeatmapViewportByDevice();
|
|
3713
3746
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
3714
3747
|
const widthScale = useHeatmapVizContext((s) => s.widthScale);
|
|
3715
3748
|
const getRect = useCallback((element) => {
|
|
@@ -3737,17 +3770,17 @@ const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
|
|
|
3737
3770
|
const outOfBounds = adjustedTop < 0 ||
|
|
3738
3771
|
adjustedTop > (iframeHeight || Infinity) ||
|
|
3739
3772
|
layout.left < 0 ||
|
|
3740
|
-
(typeof
|
|
3773
|
+
(typeof viewport.width === 'number' && layout.left > viewport.width);
|
|
3741
3774
|
if (outOfBounds)
|
|
3742
3775
|
return null;
|
|
3743
3776
|
return {
|
|
3744
3777
|
left: layout.left,
|
|
3745
3778
|
top: adjustedTop,
|
|
3746
|
-
width: Math.min(layout.width,
|
|
3779
|
+
width: Math.min(layout.width, viewport.width || layout.width),
|
|
3747
3780
|
height: layout.height,
|
|
3748
3781
|
outOfBounds,
|
|
3749
3782
|
};
|
|
3750
|
-
}, [iframeRef, wrapperRef, visualizer,
|
|
3783
|
+
}, [iframeRef, wrapperRef, visualizer, viewport, iframeHeight, widthScale]);
|
|
3751
3784
|
return { getRect };
|
|
3752
3785
|
};
|
|
3753
3786
|
|
|
@@ -4148,7 +4181,7 @@ function flush() {
|
|
|
4148
4181
|
window.__gemxPerf = getReport();
|
|
4149
4182
|
}
|
|
4150
4183
|
// ── Global singleton export ───────────────────────────────────────────────────
|
|
4151
|
-
const perf$
|
|
4184
|
+
const perf$2 = {
|
|
4152
4185
|
startSession,
|
|
4153
4186
|
endSession,
|
|
4154
4187
|
mark: globalMark,
|
|
@@ -4941,7 +4974,7 @@ const YIELD_EVERY_RULES = 100;
|
|
|
4941
4974
|
* Uses `scheduler.yield()` (Chrome 115+) when available; falls back to a
|
|
4942
4975
|
* zero-timeout macrotask which is universally supported.
|
|
4943
4976
|
*/
|
|
4944
|
-
function yieldToMain() {
|
|
4977
|
+
function yieldToMain$1() {
|
|
4945
4978
|
if (typeof globalThis !== 'undefined' && 'scheduler' in globalThis) {
|
|
4946
4979
|
return globalThis.scheduler.yield();
|
|
4947
4980
|
}
|
|
@@ -5101,7 +5134,7 @@ async function processStylesheets(ctx) {
|
|
|
5101
5134
|
rulesSinceYield++;
|
|
5102
5135
|
if (rulesSinceYield >= YIELD_EVERY_RULES) {
|
|
5103
5136
|
rulesSinceYield = 0;
|
|
5104
|
-
await yieldToMain();
|
|
5137
|
+
await yieldToMain$1();
|
|
5105
5138
|
}
|
|
5106
5139
|
}
|
|
5107
5140
|
}
|
|
@@ -5384,52 +5417,52 @@ function configure(debug) {
|
|
|
5384
5417
|
}
|
|
5385
5418
|
async function run$1(ctx, activeGlobal, shopFix) {
|
|
5386
5419
|
// ── Phase 1: beforeProcess ────────────────────────────────────────────────
|
|
5387
|
-
const t1 = perf$
|
|
5420
|
+
const t1 = perf$2.mark('phase1.beforeProcess');
|
|
5388
5421
|
for (const fix of activeGlobal) {
|
|
5389
5422
|
if (fix.beforeProcess) {
|
|
5390
5423
|
logger.log(`[beforeProcess] ${fix.name}`);
|
|
5391
|
-
const t = perf$
|
|
5424
|
+
const t = perf$2.mark(`phase1.${fix.name}.beforeProcess`);
|
|
5392
5425
|
await fix.beforeProcess(ctx);
|
|
5393
|
-
perf$
|
|
5426
|
+
perf$2.measure(`phase1.${fix.name}.beforeProcess`, t);
|
|
5394
5427
|
}
|
|
5395
5428
|
}
|
|
5396
5429
|
if (shopFix?.beforeProcess) {
|
|
5397
5430
|
logger.log('[beforeProcess] shop');
|
|
5398
|
-
const t = perf$
|
|
5431
|
+
const t = perf$2.mark('phase1.shop.beforeProcess');
|
|
5399
5432
|
await shopFix.beforeProcess(ctx);
|
|
5400
|
-
perf$
|
|
5433
|
+
perf$2.measure('phase1.shop.beforeProcess', t);
|
|
5401
5434
|
}
|
|
5402
|
-
perf$
|
|
5435
|
+
perf$2.measure('phase1.beforeProcess', t1);
|
|
5403
5436
|
// ── Phase 2: process ──────────────────────────────────────────────────────
|
|
5404
|
-
const t2 = perf$
|
|
5437
|
+
const t2 = perf$2.mark('phase2.process');
|
|
5405
5438
|
for (const fix of activeGlobal) {
|
|
5406
5439
|
if (fix.process) {
|
|
5407
5440
|
logger.log(`[process] ${fix.name}`);
|
|
5408
|
-
const t = perf$
|
|
5441
|
+
const t = perf$2.mark(`phase2.${fix.name}.process`);
|
|
5409
5442
|
await fix.process(ctx);
|
|
5410
|
-
perf$
|
|
5443
|
+
perf$2.measure(`phase2.${fix.name}.process`, t);
|
|
5411
5444
|
}
|
|
5412
5445
|
}
|
|
5413
|
-
perf$
|
|
5446
|
+
perf$2.measure('phase2.process', t2);
|
|
5414
5447
|
// ── Phase 3: afterProcess ─────────────────────────────────────────────────
|
|
5415
|
-
const t3 = perf$
|
|
5448
|
+
const t3 = perf$2.mark('phase3.afterProcess');
|
|
5416
5449
|
if (shopFix?.afterProcess) {
|
|
5417
5450
|
logger.log('[afterProcess] shop');
|
|
5418
|
-
const t = perf$
|
|
5451
|
+
const t = perf$2.mark('phase3.shop.afterProcess');
|
|
5419
5452
|
await shopFix.afterProcess(ctx);
|
|
5420
|
-
perf$
|
|
5453
|
+
perf$2.measure('phase3.shop.afterProcess', t);
|
|
5421
5454
|
}
|
|
5422
5455
|
for (const fix of activeGlobal) {
|
|
5423
5456
|
if (fix.afterProcess) {
|
|
5424
5457
|
logger.log(`[afterProcess] ${fix.name}`);
|
|
5425
|
-
const t = perf$
|
|
5458
|
+
const t = perf$2.mark(`phase3.${fix.name}.afterProcess`);
|
|
5426
5459
|
await fix.afterProcess(ctx);
|
|
5427
|
-
perf$
|
|
5460
|
+
perf$2.measure(`phase3.${fix.name}.afterProcess`, t);
|
|
5428
5461
|
}
|
|
5429
5462
|
}
|
|
5430
|
-
perf$
|
|
5463
|
+
perf$2.measure('phase3.afterProcess', t3);
|
|
5431
5464
|
// ── Phase 4: getDimensions ────────────────────────────────────────────────
|
|
5432
|
-
const t4 = perf$
|
|
5465
|
+
const t4 = perf$2.mark('phase4.getDimensions');
|
|
5433
5466
|
return new Promise((resolve) => {
|
|
5434
5467
|
requestAnimationFrame(() => {
|
|
5435
5468
|
let dimensions = null;
|
|
@@ -5454,7 +5487,7 @@ async function run$1(ctx, activeGlobal, shopFix) {
|
|
|
5454
5487
|
dimensions = { height: getFinalHeight(ctx.doc, ctx.win), width: getFinalWidth(ctx.doc) };
|
|
5455
5488
|
}
|
|
5456
5489
|
logger.log('Final dimensions:', dimensions);
|
|
5457
|
-
perf$
|
|
5490
|
+
perf$2.measure('phase4.getDimensions', t4);
|
|
5458
5491
|
resolve(dimensions);
|
|
5459
5492
|
});
|
|
5460
5493
|
});
|
|
@@ -5582,14 +5615,14 @@ async function run(s) {
|
|
|
5582
5615
|
const activeGlobal = getActiveFixes(ctx);
|
|
5583
5616
|
if (activeGlobal.length > 0)
|
|
5584
5617
|
s.logger.log(`Active global fixes: ${activeGlobal.map((f) => f.name).join(', ')}`);
|
|
5585
|
-
const tRun = perf$
|
|
5618
|
+
const tRun = perf$2.mark('viewport.run');
|
|
5586
5619
|
try {
|
|
5587
5620
|
const result = await run$1(ctx, activeGlobal, s.shopFix);
|
|
5588
|
-
perf$
|
|
5621
|
+
perf$2.measure('viewport.run', tRun);
|
|
5589
5622
|
return result;
|
|
5590
5623
|
}
|
|
5591
5624
|
catch (err) {
|
|
5592
|
-
perf$
|
|
5625
|
+
perf$2.measure('viewport.run', tRun);
|
|
5593
5626
|
s.logger.error('Critical error:', err);
|
|
5594
5627
|
return { height: s.doc.body?.scrollHeight || 1000, width: s.doc.body?.scrollWidth || 1000 };
|
|
5595
5628
|
}
|
|
@@ -5639,22 +5672,22 @@ async function process(s) {
|
|
|
5639
5672
|
return;
|
|
5640
5673
|
}
|
|
5641
5674
|
const sessionId = `render-${Date.now()}`;
|
|
5642
|
-
perf$
|
|
5643
|
-
const t0 = perf$
|
|
5675
|
+
perf$2.startSession(sessionId);
|
|
5676
|
+
const t0 = perf$2.mark('orchestrator.process');
|
|
5644
5677
|
try {
|
|
5645
5678
|
s.logger.log('Processing viewport units...');
|
|
5646
5679
|
s.viewportReplacer.start(s.iframe, s.config);
|
|
5647
5680
|
s.navigationBlocker.start(s.iframe, { debug: s.config.debug });
|
|
5648
5681
|
const result = await s.viewportReplacer.run();
|
|
5649
|
-
perf$
|
|
5650
|
-
perf$
|
|
5682
|
+
perf$2.measure('orchestrator.process', t0);
|
|
5683
|
+
perf$2.endSession();
|
|
5651
5684
|
s.logger.log('Process completed:', result);
|
|
5652
5685
|
s.config.onSuccess?.(result);
|
|
5653
5686
|
dispatchDimensionsEvent(result);
|
|
5654
5687
|
}
|
|
5655
5688
|
catch (error) {
|
|
5656
|
-
perf$
|
|
5657
|
-
perf$
|
|
5689
|
+
perf$2.measure('orchestrator.process', t0);
|
|
5690
|
+
perf$2.endSession();
|
|
5658
5691
|
s.logger.error('Failed to process:', error);
|
|
5659
5692
|
s.config.onError?.(error);
|
|
5660
5693
|
}
|
|
@@ -5805,13 +5838,13 @@ function useVizLiveRender() {
|
|
|
5805
5838
|
const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
|
|
5806
5839
|
const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
|
|
5807
5840
|
const wrapperWidth = useHeatmapVizRectContext((s) => s.wrapperWidth);
|
|
5808
|
-
const
|
|
5841
|
+
const setIsDomLoaded = useHeatmapVizContext((s) => s.setIsDomLoaded);
|
|
5809
5842
|
const htmlContent = useHeatmapLiveContext((s) => s.htmlContent);
|
|
5810
5843
|
const targetUrl = useHeatmapLiveContext((s) => s.targetUrl);
|
|
5811
5844
|
const deviceType = useHeatmapSettingContext((s) => s.deviceType);
|
|
5812
5845
|
const renderMode = useHeatmapLiveContext((s) => s.renderMode);
|
|
5813
5846
|
const storefrontPassword = useHeatmapLiveContext((s) => s.storefrontPassword);
|
|
5814
|
-
|
|
5847
|
+
useHeatmapViewportByDevice();
|
|
5815
5848
|
const { iframeRef, isReady } = useVizLiveIframeMsg();
|
|
5816
5849
|
// Handle iframe rendering based on mode
|
|
5817
5850
|
useEffect(() => {
|
|
@@ -5851,10 +5884,10 @@ function useVizLiveRender() {
|
|
|
5851
5884
|
const hasContent = (renderMode === 'portal' && targetUrl) || (renderMode === 'inline' && htmlContent);
|
|
5852
5885
|
if (!iframe || !hasContent)
|
|
5853
5886
|
return;
|
|
5854
|
-
|
|
5887
|
+
setIsDomLoaded(true);
|
|
5855
5888
|
startIframe$1(iframe, deviceType, { width: wrapperWidth, height: wrapperHeight }, (height) => {
|
|
5856
5889
|
height && setIframeHeight(height);
|
|
5857
|
-
|
|
5890
|
+
setIsDomLoaded(true);
|
|
5858
5891
|
});
|
|
5859
5892
|
return () => { };
|
|
5860
5893
|
}, [
|
|
@@ -5866,7 +5899,7 @@ function useVizLiveRender() {
|
|
|
5866
5899
|
targetUrl,
|
|
5867
5900
|
htmlContent,
|
|
5868
5901
|
iframeRef,
|
|
5869
|
-
|
|
5902
|
+
setIsDomLoaded,
|
|
5870
5903
|
setIframeHeight,
|
|
5871
5904
|
]);
|
|
5872
5905
|
return {
|
|
@@ -5901,6 +5934,109 @@ function startIframe$1(iframe, deviceType = EDeviceType.Desktop, rect, onSuccess
|
|
|
5901
5934
|
iframeHelper.enableNavigationBlocking();
|
|
5902
5935
|
}
|
|
5903
5936
|
|
|
5937
|
+
const DEFAULT_CONFIG = {
|
|
5938
|
+
dbName: 'gx-viz-html-cache',
|
|
5939
|
+
maxEntries: 20,
|
|
5940
|
+
ttlMs: 24 * 60 * 60 * 1000, // 24 hours
|
|
5941
|
+
cacheVersion: 3.0,
|
|
5942
|
+
};
|
|
5943
|
+
let _config = { ...DEFAULT_CONFIG };
|
|
5944
|
+
function getHtmlCacheConfig() {
|
|
5945
|
+
return _config;
|
|
5946
|
+
}
|
|
5947
|
+
/** Build a full cache key that includes the cache version to handle invalidation. */
|
|
5948
|
+
function buildCacheKey(baseKey, shortCircuitStrategy) {
|
|
5949
|
+
return `v${_config.cacheVersion}:${baseKey}:${shortCircuitStrategy}`;
|
|
5950
|
+
}
|
|
5951
|
+
|
|
5952
|
+
const STORE_NAME = 'entries';
|
|
5953
|
+
const IDB_SCHEMA_VERSION = 1;
|
|
5954
|
+
function openDb() {
|
|
5955
|
+
const { dbName } = getHtmlCacheConfig();
|
|
5956
|
+
return new Promise((resolve, reject) => {
|
|
5957
|
+
const req = indexedDB.open(dbName, IDB_SCHEMA_VERSION);
|
|
5958
|
+
req.onupgradeneeded = () => {
|
|
5959
|
+
const db = req.result;
|
|
5960
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
5961
|
+
const store = db.createObjectStore(STORE_NAME, { keyPath: 'key' });
|
|
5962
|
+
store.createIndex('timestamp', 'timestamp');
|
|
5963
|
+
}
|
|
5964
|
+
};
|
|
5965
|
+
req.onsuccess = () => resolve(req.result);
|
|
5966
|
+
req.onerror = () => reject(req.error);
|
|
5967
|
+
});
|
|
5968
|
+
}
|
|
5969
|
+
async function evict(db) {
|
|
5970
|
+
const { maxEntries } = getHtmlCacheConfig();
|
|
5971
|
+
return new Promise((resolve) => {
|
|
5972
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
5973
|
+
const store = tx.objectStore(STORE_NAME);
|
|
5974
|
+
const countReq = store.count();
|
|
5975
|
+
countReq.onsuccess = () => {
|
|
5976
|
+
if (countReq.result <= maxEntries) {
|
|
5977
|
+
resolve();
|
|
5978
|
+
return;
|
|
5979
|
+
}
|
|
5980
|
+
const idx = store.index('timestamp');
|
|
5981
|
+
const cursorReq = idx.openCursor();
|
|
5982
|
+
let toDelete = countReq.result - maxEntries;
|
|
5983
|
+
cursorReq.onsuccess = () => {
|
|
5984
|
+
const cursor = cursorReq.result;
|
|
5985
|
+
if (cursor && toDelete > 0) {
|
|
5986
|
+
cursor.delete();
|
|
5987
|
+
toDelete--;
|
|
5988
|
+
cursor.continue();
|
|
5989
|
+
}
|
|
5990
|
+
else {
|
|
5991
|
+
resolve();
|
|
5992
|
+
}
|
|
5993
|
+
};
|
|
5994
|
+
cursorReq.onerror = () => resolve();
|
|
5995
|
+
};
|
|
5996
|
+
countReq.onerror = () => resolve();
|
|
5997
|
+
});
|
|
5998
|
+
}
|
|
5999
|
+
const htmlCache = {
|
|
6000
|
+
async get(key) {
|
|
6001
|
+
try {
|
|
6002
|
+
const { ttlMs } = getHtmlCacheConfig();
|
|
6003
|
+
const db = await openDb();
|
|
6004
|
+
return new Promise((resolve) => {
|
|
6005
|
+
const tx = db.transaction(STORE_NAME, 'readonly');
|
|
6006
|
+
const req = tx.objectStore(STORE_NAME).get(key);
|
|
6007
|
+
req.onsuccess = () => {
|
|
6008
|
+
const entry = req.result;
|
|
6009
|
+
if (!entry || Date.now() - entry.timestamp > ttlMs) {
|
|
6010
|
+
resolve(null);
|
|
6011
|
+
}
|
|
6012
|
+
else {
|
|
6013
|
+
resolve(entry);
|
|
6014
|
+
}
|
|
6015
|
+
};
|
|
6016
|
+
req.onerror = () => resolve(null);
|
|
6017
|
+
});
|
|
6018
|
+
}
|
|
6019
|
+
catch {
|
|
6020
|
+
return null;
|
|
6021
|
+
}
|
|
6022
|
+
},
|
|
6023
|
+
async set(entry) {
|
|
6024
|
+
try {
|
|
6025
|
+
const db = await openDb();
|
|
6026
|
+
await new Promise((resolve, reject) => {
|
|
6027
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
6028
|
+
tx.objectStore(STORE_NAME).put(entry);
|
|
6029
|
+
tx.oncomplete = () => resolve();
|
|
6030
|
+
tx.onerror = () => reject(tx.error);
|
|
6031
|
+
});
|
|
6032
|
+
await evict(db);
|
|
6033
|
+
}
|
|
6034
|
+
catch {
|
|
6035
|
+
// ignore cache write errors
|
|
6036
|
+
}
|
|
6037
|
+
},
|
|
6038
|
+
};
|
|
6039
|
+
|
|
5904
6040
|
const CANVAS_ID = 'clarity-heatmap-canvas';
|
|
5905
6041
|
const ATTENTION_HUES = [240, 210, 180, 150, 120, 90, 60, 30, 0];
|
|
5906
6042
|
const CANVAS_MAX_HEIGHT = 65535;
|
|
@@ -6109,6 +6245,250 @@ class AttentionMapRenderer {
|
|
|
6109
6245
|
};
|
|
6110
6246
|
}
|
|
6111
6247
|
|
|
6248
|
+
var Event;
|
|
6249
|
+
(function (Event) {
|
|
6250
|
+
/* Data */
|
|
6251
|
+
Event[Event["Metric"] = 0] = "Metric";
|
|
6252
|
+
Event[Event["Dimension"] = 1] = "Dimension";
|
|
6253
|
+
Event[Event["Upload"] = 2] = "Upload";
|
|
6254
|
+
Event[Event["Upgrade"] = 3] = "Upgrade";
|
|
6255
|
+
Event[Event["Baseline"] = 4] = "Baseline";
|
|
6256
|
+
Event[Event["Discover"] = 5] = "Discover";
|
|
6257
|
+
Event[Event["Mutation"] = 6] = "Mutation";
|
|
6258
|
+
Event[Event["Region"] = 7] = "Region";
|
|
6259
|
+
Event[Event["Document"] = 8] = "Document";
|
|
6260
|
+
Event[Event["Click"] = 9] = "Click";
|
|
6261
|
+
Event[Event["Scroll"] = 10] = "Scroll";
|
|
6262
|
+
Event[Event["Resize"] = 11] = "Resize";
|
|
6263
|
+
Event[Event["MouseMove"] = 12] = "MouseMove";
|
|
6264
|
+
Event[Event["MouseDown"] = 13] = "MouseDown";
|
|
6265
|
+
Event[Event["MouseUp"] = 14] = "MouseUp";
|
|
6266
|
+
Event[Event["MouseWheel"] = 15] = "MouseWheel";
|
|
6267
|
+
Event[Event["DoubleClick"] = 16] = "DoubleClick";
|
|
6268
|
+
Event[Event["TouchStart"] = 17] = "TouchStart";
|
|
6269
|
+
Event[Event["TouchEnd"] = 18] = "TouchEnd";
|
|
6270
|
+
Event[Event["TouchMove"] = 19] = "TouchMove";
|
|
6271
|
+
Event[Event["TouchCancel"] = 20] = "TouchCancel";
|
|
6272
|
+
Event[Event["Selection"] = 21] = "Selection";
|
|
6273
|
+
Event[Event["Timeline"] = 22] = "Timeline";
|
|
6274
|
+
Event[Event["Page"] = 23] = "Page";
|
|
6275
|
+
Event[Event["Custom"] = 24] = "Custom";
|
|
6276
|
+
Event[Event["Ping"] = 25] = "Ping";
|
|
6277
|
+
Event[Event["Unload"] = 26] = "Unload";
|
|
6278
|
+
Event[Event["Input"] = 27] = "Input";
|
|
6279
|
+
Event[Event["Visibility"] = 28] = "Visibility";
|
|
6280
|
+
Event[Event["Navigation"] = 29] = "Navigation";
|
|
6281
|
+
/**
|
|
6282
|
+
* @deprecated No longer support Network Connection
|
|
6283
|
+
*/
|
|
6284
|
+
Event[Event["Connection"] = 30] = "Connection";
|
|
6285
|
+
Event[Event["ScriptError"] = 31] = "ScriptError";
|
|
6286
|
+
/**
|
|
6287
|
+
* @deprecated No longer support Image Error
|
|
6288
|
+
*/
|
|
6289
|
+
Event[Event["ImageError"] = 32] = "ImageError";
|
|
6290
|
+
Event[Event["Log"] = 33] = "Log";
|
|
6291
|
+
Event[Event["Variable"] = 34] = "Variable";
|
|
6292
|
+
Event[Event["Limit"] = 35] = "Limit";
|
|
6293
|
+
Event[Event["Summary"] = 36] = "Summary";
|
|
6294
|
+
/**
|
|
6295
|
+
* @deprecated No longer support Box event
|
|
6296
|
+
*/
|
|
6297
|
+
Event[Event["Box"] = 37] = "Box";
|
|
6298
|
+
Event[Event["Clipboard"] = 38] = "Clipboard";
|
|
6299
|
+
Event[Event["Submit"] = 39] = "Submit";
|
|
6300
|
+
Event[Event["Extract"] = 40] = "Extract";
|
|
6301
|
+
Event[Event["Fraud"] = 41] = "Fraud";
|
|
6302
|
+
Event[Event["Change"] = 42] = "Change";
|
|
6303
|
+
Event[Event["Snapshot"] = 43] = "Snapshot";
|
|
6304
|
+
Event[Event["Animation"] = 44] = "Animation";
|
|
6305
|
+
Event[Event["StyleSheetAdoption"] = 45] = "StyleSheetAdoption";
|
|
6306
|
+
Event[Event["StyleSheetUpdate"] = 46] = "StyleSheetUpdate";
|
|
6307
|
+
Event[Event["Consent"] = 47] = "Consent";
|
|
6308
|
+
Event[Event["ContextMenu"] = 48] = "ContextMenu";
|
|
6309
|
+
// 49 is reserved for internal use
|
|
6310
|
+
Event[Event["Focus"] = 50] = "Focus";
|
|
6311
|
+
Event[Event["CustomElement"] = 51] = "CustomElement";
|
|
6312
|
+
Event[Event["Chat"] = 52] = "Chat";
|
|
6313
|
+
// Apps specific events
|
|
6314
|
+
Event[Event["WebViewDiscover"] = 100] = "WebViewDiscover";
|
|
6315
|
+
Event[Event["WebViewMutation"] = 101] = "WebViewMutation";
|
|
6316
|
+
Event[Event["MutationError"] = 102] = "MutationError";
|
|
6317
|
+
Event[Event["FragmentVisibility"] = 103] = "FragmentVisibility";
|
|
6318
|
+
Event[Event["Keystrokes"] = 104] = "Keystrokes";
|
|
6319
|
+
Event[Event["BackGesture"] = 105] = "BackGesture";
|
|
6320
|
+
Event[Event["WebViewStatus"] = 106] = "WebViewStatus";
|
|
6321
|
+
Event[Event["AppInstallReferrer"] = 107] = "AppInstallReferrer";
|
|
6322
|
+
// 200-300 reserved for internal use
|
|
6323
|
+
})(Event || (Event = {}));
|
|
6324
|
+
|
|
6325
|
+
var Constant;
|
|
6326
|
+
(function (Constant) {
|
|
6327
|
+
Constant["Empty"] = "";
|
|
6328
|
+
Constant["SvgPrefix"] = "svg:";
|
|
6329
|
+
Constant["DataPrefix"] = "data:";
|
|
6330
|
+
Constant["IFramePrefix"] = "iframe:";
|
|
6331
|
+
Constant["SvgNamespace"] = "http://www.w3.org/2000/svg";
|
|
6332
|
+
Constant["Id"] = "id";
|
|
6333
|
+
Constant["Class"] = "class";
|
|
6334
|
+
Constant["Style"] = "style";
|
|
6335
|
+
Constant["Href"] = "href";
|
|
6336
|
+
Constant["Src"] = "src";
|
|
6337
|
+
Constant["Srcset"] = "srcset";
|
|
6338
|
+
Constant["Hash"] = "#";
|
|
6339
|
+
Constant["Dot"] = ".";
|
|
6340
|
+
Constant["Separator"] = ">";
|
|
6341
|
+
Constant["Tilde"] = "~";
|
|
6342
|
+
Constant["Bang"] = "!";
|
|
6343
|
+
Constant["Period"] = ".";
|
|
6344
|
+
Constant["Comma"] = ",";
|
|
6345
|
+
Constant["DataAttribute"] = "data-";
|
|
6346
|
+
Constant["MaskData"] = "data-clarity-mask";
|
|
6347
|
+
Constant["UnmaskData"] = "data-clarity-unmask";
|
|
6348
|
+
Constant["RegionData"] = "data-clarity-region";
|
|
6349
|
+
Constant["GXDialogModal"] = "gx-dialog-modal";
|
|
6350
|
+
Constant["Type"] = "type";
|
|
6351
|
+
Constant["Submit"] = "submit";
|
|
6352
|
+
Constant["Name"] = "name";
|
|
6353
|
+
Constant["Base"] = "*B";
|
|
6354
|
+
Constant["SameOrigin"] = "*O";
|
|
6355
|
+
Constant["Object"] = "object";
|
|
6356
|
+
Constant["Function"] = "function";
|
|
6357
|
+
Constant["StyleTag"] = "STYLE";
|
|
6358
|
+
Constant["LinkTag"] = "LINK";
|
|
6359
|
+
Constant["InputTag"] = "INPUT";
|
|
6360
|
+
Constant["IFrameTag"] = "IFRAME";
|
|
6361
|
+
Constant["ImageTag"] = "IMG";
|
|
6362
|
+
Constant["TitleTag"] = "TITLE";
|
|
6363
|
+
Constant["BodyTag"] = "BODY";
|
|
6364
|
+
Constant["SvgTag"] = "svg:svg";
|
|
6365
|
+
Constant["BaseTag"] = "BASE";
|
|
6366
|
+
Constant["NativeCode"] = "[native code]";
|
|
6367
|
+
Constant["DocumentTag"] = "*D";
|
|
6368
|
+
Constant["ShadowDomTag"] = "*S";
|
|
6369
|
+
Constant["PolyfillShadowDomTag"] = "*P";
|
|
6370
|
+
Constant["TextTag"] = "*T";
|
|
6371
|
+
Constant["SuspendMutationTag"] = "*M";
|
|
6372
|
+
Constant["ChildList"] = "childList";
|
|
6373
|
+
Constant["Attributes"] = "attributes";
|
|
6374
|
+
Constant["CharacterData"] = "characterData";
|
|
6375
|
+
Constant["Throttle"] = "throttle";
|
|
6376
|
+
Constant["LoadEvent"] = "load";
|
|
6377
|
+
Constant["Pixel"] = "px";
|
|
6378
|
+
Constant["BorderBox"] = "border-box";
|
|
6379
|
+
Constant["Value"] = "value";
|
|
6380
|
+
Constant["MutationObserver"] = "MutationObserver";
|
|
6381
|
+
Constant["JsonLD"] = "application/ld+json";
|
|
6382
|
+
Constant["String"] = "string";
|
|
6383
|
+
Constant["Number"] = "number";
|
|
6384
|
+
Constant["Disable"] = "disable";
|
|
6385
|
+
Constant["HTML"] = "HTML";
|
|
6386
|
+
Constant["Property"] = "property";
|
|
6387
|
+
Constant["Content"] = "content";
|
|
6388
|
+
Constant["Generator"] = "generator";
|
|
6389
|
+
Constant["ogType"] = "og:type";
|
|
6390
|
+
Constant["ogTitle"] = "og:title";
|
|
6391
|
+
Constant["SvgStyle"] = "svg:style";
|
|
6392
|
+
Constant["StyleSheet"] = "stylesheet";
|
|
6393
|
+
})(Constant || (Constant = {}));
|
|
6394
|
+
|
|
6395
|
+
var ShortCircuitStrategy;
|
|
6396
|
+
(function (ShortCircuitStrategy) {
|
|
6397
|
+
ShortCircuitStrategy[ShortCircuitStrategy["None"] = 0] = "None";
|
|
6398
|
+
ShortCircuitStrategy[ShortCircuitStrategy["HashFirstTimestamp"] = 1] = "HashFirstTimestamp";
|
|
6399
|
+
ShortCircuitStrategy[ShortCircuitStrategy["HashFirstTimestampPlusBuffer"] = 2] = "HashFirstTimestampPlusBuffer";
|
|
6400
|
+
ShortCircuitStrategy[ShortCircuitStrategy["HashBeforeDeleted"] = 3] = "HashBeforeDeleted";
|
|
6401
|
+
})(ShortCircuitStrategy || (ShortCircuitStrategy = {}));
|
|
6402
|
+
|
|
6403
|
+
function isShadowDomNode(tag) {
|
|
6404
|
+
return tag === Constant.ShadowDomTag || tag === Constant.PolyfillShadowDomTag;
|
|
6405
|
+
}
|
|
6406
|
+
/** Scan the rendered DOM (including nested shadow roots) to collect tag names of shadow host elements. */
|
|
6407
|
+
function collectShadowHostTags(root, tags = new Set()) {
|
|
6408
|
+
root.querySelectorAll('*').forEach((el) => {
|
|
6409
|
+
if (el.shadowRoot) {
|
|
6410
|
+
tags.add(el.tagName);
|
|
6411
|
+
collectShadowHostTags(el.shadowRoot, tags);
|
|
6412
|
+
}
|
|
6413
|
+
});
|
|
6414
|
+
return tags;
|
|
6415
|
+
}
|
|
6416
|
+
/** Build a shadow subtree ID set from all DOM events.
|
|
6417
|
+
* Two-pass cascade to handle any event ordering:
|
|
6418
|
+
* Pass 1 — seed *S/*P node IDs.
|
|
6419
|
+
* Pass 2 — cascade: any node whose parent is in the set is also in the set (repeat until stable). */
|
|
6420
|
+
function buildShadowSubtreeIds(allDomEvents) {
|
|
6421
|
+
const subtreeIds = new Set();
|
|
6422
|
+
for (const e of allDomEvents) {
|
|
6423
|
+
const data = e.data;
|
|
6424
|
+
for (const node of data ?? []) {
|
|
6425
|
+
if (isShadowDomNode(node.tag))
|
|
6426
|
+
subtreeIds.add(node.id);
|
|
6427
|
+
}
|
|
6428
|
+
}
|
|
6429
|
+
let changed = true;
|
|
6430
|
+
while (changed) {
|
|
6431
|
+
changed = false;
|
|
6432
|
+
for (const e of allDomEvents) {
|
|
6433
|
+
const data = e.data;
|
|
6434
|
+
for (const node of data ?? []) {
|
|
6435
|
+
if (!subtreeIds.has(node.id) && subtreeIds.has(node.parent)) {
|
|
6436
|
+
subtreeIds.add(node.id);
|
|
6437
|
+
changed = true;
|
|
6438
|
+
}
|
|
6439
|
+
}
|
|
6440
|
+
}
|
|
6441
|
+
}
|
|
6442
|
+
return subtreeIds;
|
|
6443
|
+
}
|
|
6444
|
+
function filterShadowNodes(data, subtreeIds, shadowHostTags) {
|
|
6445
|
+
return (data?.filter((node) => {
|
|
6446
|
+
if (isShadowDomNode(node.tag))
|
|
6447
|
+
return true;
|
|
6448
|
+
if (shadowHostTags.has(node.tag ?? '') && subtreeIds.has(node.parent))
|
|
6449
|
+
return true;
|
|
6450
|
+
return subtreeIds.has(node.id);
|
|
6451
|
+
}) ?? []);
|
|
6452
|
+
}
|
|
6453
|
+
/** Extract shadow DOM nodes from merged.dom (initial Discover event, processed by setup()).
|
|
6454
|
+
* Returns a filtered copy of the dom event, or null if no shadow DOM present. */
|
|
6455
|
+
function extractSpecialDom(dom, events, shadowHostTags) {
|
|
6456
|
+
const mutationEvents = events.filter((e) => e.event === Event.Mutation);
|
|
6457
|
+
const subtreeIds = buildShadowSubtreeIds([dom, ...mutationEvents]);
|
|
6458
|
+
const shadowNodes = filterShadowNodes(dom.data, subtreeIds, shadowHostTags);
|
|
6459
|
+
return shadowNodes.length ? { ...dom, data: shadowNodes } : null;
|
|
6460
|
+
}
|
|
6461
|
+
/** Extract shadow DOM mutations + StyleSheet + CustomElement events from merged.events. */
|
|
6462
|
+
function extractSpecialEvents(events, dom, shadowHostTags) {
|
|
6463
|
+
const mutationEvents = events.filter((e) => e.event === Event.Mutation);
|
|
6464
|
+
const subtreeIds = buildShadowSubtreeIds([dom, ...mutationEvents]);
|
|
6465
|
+
const result = [];
|
|
6466
|
+
for (const e of events) {
|
|
6467
|
+
const ev = e.event;
|
|
6468
|
+
if (ev === Event.StyleSheetAdoption ||
|
|
6469
|
+
ev === Event.StyleSheetUpdate ||
|
|
6470
|
+
ev === Event.CustomElement) {
|
|
6471
|
+
result.push(e);
|
|
6472
|
+
continue;
|
|
6473
|
+
}
|
|
6474
|
+
if (ev === Event.Mutation) {
|
|
6475
|
+
const shadowNodes = filterShadowNodes(e.data, subtreeIds, shadowHostTags);
|
|
6476
|
+
if (shadowNodes.length)
|
|
6477
|
+
result.push({ ...e, data: shadowNodes });
|
|
6478
|
+
}
|
|
6479
|
+
}
|
|
6480
|
+
return result;
|
|
6481
|
+
}
|
|
6482
|
+
|
|
6483
|
+
const YIELD_INTERVAL_MS = 16;
|
|
6484
|
+
async function yieldToMain() {
|
|
6485
|
+
if ('scheduler' in globalThis && typeof globalThis.scheduler?.yield === 'function') {
|
|
6486
|
+
await globalThis.scheduler.yield();
|
|
6487
|
+
}
|
|
6488
|
+
else {
|
|
6489
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
6490
|
+
}
|
|
6491
|
+
}
|
|
6112
6492
|
class GXVisualizer extends Visualizer {
|
|
6113
6493
|
attentionMap;
|
|
6114
6494
|
originalClearmap;
|
|
@@ -6120,6 +6500,7 @@ class GXVisualizer extends Visualizer {
|
|
|
6120
6500
|
this.originalClearmap = this.clearmap;
|
|
6121
6501
|
this.clearmap = this.clearmapOverride;
|
|
6122
6502
|
this.setup = this.setupOverride;
|
|
6503
|
+
this.html = this.htmlOverride;
|
|
6123
6504
|
}
|
|
6124
6505
|
setupOverride = async (target, options) => {
|
|
6125
6506
|
this.attentionMap?.clear();
|
|
@@ -6131,6 +6512,99 @@ class GXVisualizer extends Visualizer {
|
|
|
6131
6512
|
this.originalClearmap();
|
|
6132
6513
|
this.attentionMap?.clear();
|
|
6133
6514
|
};
|
|
6515
|
+
renderLoop = async (v, events, hash, useproxy, shortCircuitStrategy) => {
|
|
6516
|
+
let lastYield = performance.now();
|
|
6517
|
+
for (let i = 0; i < events.length; i++) {
|
|
6518
|
+
const now = performance.now();
|
|
6519
|
+
if (now - lastYield > YIELD_INTERVAL_MS) {
|
|
6520
|
+
await yieldToMain();
|
|
6521
|
+
lastYield = performance.now();
|
|
6522
|
+
}
|
|
6523
|
+
const entry = events[i];
|
|
6524
|
+
const entryEvent = entry.event;
|
|
6525
|
+
switch (entryEvent) {
|
|
6526
|
+
case Event.StyleSheetAdoption:
|
|
6527
|
+
case Event.StyleSheetUpdate:
|
|
6528
|
+
v.layout.styleChange(entry);
|
|
6529
|
+
break;
|
|
6530
|
+
case Event.CustomElement:
|
|
6531
|
+
v.layout.customElement(entry);
|
|
6532
|
+
break;
|
|
6533
|
+
case Event.Mutation: {
|
|
6534
|
+
const domEvent = entry;
|
|
6535
|
+
this.renderTime = domEvent.time;
|
|
6536
|
+
if (v.shortCircuitRendering(shortCircuitStrategy, domEvent, hash))
|
|
6537
|
+
return;
|
|
6538
|
+
v.layout.markup(domEvent, useproxy);
|
|
6539
|
+
break;
|
|
6540
|
+
}
|
|
6541
|
+
}
|
|
6542
|
+
}
|
|
6543
|
+
};
|
|
6544
|
+
htmlOverride = async (decoded, target, portalCanvasId, hash = '', useproxy, logerror, shortCircuitStrategy = ShortCircuitStrategy.None) => {
|
|
6545
|
+
if (decoded && decoded.length > 0 && target) {
|
|
6546
|
+
try {
|
|
6547
|
+
const v = this;
|
|
6548
|
+
const merged = v.mergeForHtml(decoded);
|
|
6549
|
+
await this.setup(target, { version: decoded[0].envelope.version, dom: merged.dom, useproxy, portalCanvasId });
|
|
6550
|
+
await this.renderLoop(v, merged.events, hash, useproxy, shortCircuitStrategy);
|
|
6551
|
+
}
|
|
6552
|
+
catch (e) {
|
|
6553
|
+
if (logerror)
|
|
6554
|
+
logerror(e);
|
|
6555
|
+
}
|
|
6556
|
+
}
|
|
6557
|
+
return this;
|
|
6558
|
+
};
|
|
6559
|
+
htmlCached = async (cacheKey, decoded, target, portalCanvasId, hash = '', useproxy, logerror, shortCircuitStrategy = 0) => {
|
|
6560
|
+
if (!decoded || decoded.length === 0 || !target)
|
|
6561
|
+
return this;
|
|
6562
|
+
const fullKey = buildCacheKey(cacheKey, shortCircuitStrategy);
|
|
6563
|
+
const cached = await htmlCache.get(fullKey);
|
|
6564
|
+
if (cached) {
|
|
6565
|
+
try {
|
|
6566
|
+
const v = this;
|
|
6567
|
+
await this.setup(target, { version: cached.version, useproxy, portalCanvasId });
|
|
6568
|
+
target.document.open();
|
|
6569
|
+
target.document.write(cached.html);
|
|
6570
|
+
target.document.close();
|
|
6571
|
+
v.layout.hydrate(target.document);
|
|
6572
|
+
// Replay shadow DOM from initial Discover event (was processed by setup() in full render)
|
|
6573
|
+
if (cached.specialDom) {
|
|
6574
|
+
v.layout.markup(cached.specialDom, useproxy);
|
|
6575
|
+
}
|
|
6576
|
+
// Replay shadow DOM mutations + StyleSheet + CustomElement
|
|
6577
|
+
await this.renderLoop(v, cached.specialEvents, '', useproxy, 0);
|
|
6578
|
+
return this;
|
|
6579
|
+
}
|
|
6580
|
+
catch (e) {
|
|
6581
|
+
if (logerror)
|
|
6582
|
+
logerror(e);
|
|
6583
|
+
}
|
|
6584
|
+
}
|
|
6585
|
+
try {
|
|
6586
|
+
const v = this;
|
|
6587
|
+
const merged = v.mergeForHtml(decoded);
|
|
6588
|
+
await this.setup(target, { version: decoded[0].envelope.version, dom: merged.dom, useproxy, portalCanvasId });
|
|
6589
|
+
await this.renderLoop(v, merged.events, hash, useproxy, shortCircuitStrategy);
|
|
6590
|
+
const shadowHostTags = collectShadowHostTags(target.document);
|
|
6591
|
+
const specialDom = extractSpecialDom(merged.dom, merged.events, shadowHostTags);
|
|
6592
|
+
const specialEvents = extractSpecialEvents(merged.events, merged.dom, shadowHostTags);
|
|
6593
|
+
void htmlCache.set({
|
|
6594
|
+
key: fullKey,
|
|
6595
|
+
html: target.document.documentElement.outerHTML,
|
|
6596
|
+
specialDom: specialDom,
|
|
6597
|
+
specialEvents,
|
|
6598
|
+
version: decoded[0].envelope.version,
|
|
6599
|
+
timestamp: Date.now(),
|
|
6600
|
+
});
|
|
6601
|
+
}
|
|
6602
|
+
catch (e) {
|
|
6603
|
+
if (logerror)
|
|
6604
|
+
logerror(e);
|
|
6605
|
+
}
|
|
6606
|
+
return this;
|
|
6607
|
+
};
|
|
6134
6608
|
/**
|
|
6135
6609
|
* Render attention/engagement map.
|
|
6136
6610
|
* @param attentionData - Array of attention data points with start/end element hashes and time spent
|
|
@@ -6143,93 +6617,72 @@ class GXVisualizer extends Visualizer {
|
|
|
6143
6617
|
};
|
|
6144
6618
|
}
|
|
6145
6619
|
|
|
6146
|
-
const perf = createPerfTimer('Render');
|
|
6147
|
-
const
|
|
6148
|
-
const viewId = useViewIdContext();
|
|
6149
|
-
const data = useHeatmapDataContext((s) => s.data);
|
|
6620
|
+
const perf$1 = createPerfTimer('Render');
|
|
6621
|
+
const useHeatmapIframeProcessor = () => {
|
|
6150
6622
|
const shopId = useHeatmapConfigStore((s) => s.shopId);
|
|
6151
|
-
const excludeClassNames = useHeatmapConfigStore((s) => s.excludeClassNames);
|
|
6152
|
-
const vizRef = useHeatmapVizRectContext((s) => s.vizRef);
|
|
6153
|
-
const setVizRef = useHeatmapVizRectContext((s) => s.setVizRef);
|
|
6154
|
-
const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
|
|
6155
|
-
const setIsRenderedViz = useHeatmapVizContext((s) => s.setIsRenderedViz);
|
|
6156
|
-
const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
|
|
6157
|
-
const contentWidth = useHeatmapWidthByDevice();
|
|
6158
6623
|
const deviceType = useHeatmapSettingContext((s) => s.deviceType);
|
|
6159
|
-
const
|
|
6624
|
+
const viewport = useHeatmapViewportByDevice();
|
|
6625
|
+
const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
|
|
6626
|
+
const setIsDomLoaded = useHeatmapVizContext((s) => s.setIsDomLoaded);
|
|
6160
6627
|
const helperRef = useRef(null);
|
|
6161
|
-
const
|
|
6162
|
-
const
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
const
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
if (contentWidthRef.current === 0 || wrapperHeightRef.current === 0) {
|
|
6169
|
-
pendingDataRef.current = payloads;
|
|
6628
|
+
const pendingRef = useRef(null);
|
|
6629
|
+
const reset = useCallback(() => {
|
|
6630
|
+
pendingRef.current = null;
|
|
6631
|
+
}, []);
|
|
6632
|
+
const run = useCallback((iframe, t0, abort) => {
|
|
6633
|
+
if (viewport.width === 0 || viewport.height === 0) {
|
|
6634
|
+
pendingRef.current = { iframe, t0, abort };
|
|
6170
6635
|
return;
|
|
6171
6636
|
}
|
|
6172
|
-
pendingDataRef.current = null;
|
|
6173
|
-
if (!payloads || payloads.length === 0)
|
|
6174
|
-
return;
|
|
6175
|
-
const iframe = iframeRef.current;
|
|
6176
|
-
if (!iframe?.contentWindow)
|
|
6177
|
-
return;
|
|
6178
|
-
abortRef.current?.abort();
|
|
6179
|
-
const abort = new AbortController();
|
|
6180
|
-
abortRef.current = abort;
|
|
6181
|
-
const t0 = perf.mark('renderHeatmap start');
|
|
6182
|
-
const visualizer = vizRef ?? new GXVisualizer();
|
|
6183
|
-
if (!vizRef)
|
|
6184
|
-
setVizRef(visualizer);
|
|
6185
|
-
visualizer.configure({ excludeClassNames });
|
|
6186
|
-
setIsRenderedViz(false);
|
|
6187
|
-
await perf.wrap('visualizer.html', () => visualizer.html(payloads, iframe.contentWindow, viewId));
|
|
6188
|
-
if (abort.signal.aborted)
|
|
6189
|
-
return;
|
|
6190
|
-
const size = { width: contentWidthRef.current, height: wrapperHeightRef.current };
|
|
6191
6637
|
startIframe({
|
|
6192
6638
|
helperRef,
|
|
6193
6639
|
iframe,
|
|
6194
6640
|
shopId,
|
|
6195
6641
|
deviceType,
|
|
6196
|
-
size,
|
|
6642
|
+
size: viewport,
|
|
6197
6643
|
t0,
|
|
6198
6644
|
onSuccess: (height) => {
|
|
6199
6645
|
if (abort.signal.aborted)
|
|
6200
6646
|
return;
|
|
6201
6647
|
if (height)
|
|
6202
6648
|
setIframeHeight(height);
|
|
6203
|
-
|
|
6649
|
+
setIsDomLoaded(true);
|
|
6204
6650
|
},
|
|
6205
6651
|
});
|
|
6206
6652
|
}, [deviceType]);
|
|
6653
|
+
// Retry when dims become available
|
|
6207
6654
|
useEffect(() => {
|
|
6208
|
-
if (
|
|
6655
|
+
if (viewport.width === 0 || viewport.height === 0)
|
|
6209
6656
|
return;
|
|
6210
|
-
|
|
6211
|
-
renderHeatmap(decoded);
|
|
6212
|
-
return () => { };
|
|
6213
|
-
}, [data, renderHeatmap]);
|
|
6214
|
-
// Retry pending render when dimensions become available
|
|
6215
|
-
useEffect(() => {
|
|
6216
|
-
if (contentWidth === 0 || wrapperHeight === 0)
|
|
6657
|
+
if (!pendingRef.current)
|
|
6217
6658
|
return;
|
|
6218
|
-
|
|
6659
|
+
const { iframe, t0, abort } = pendingRef.current;
|
|
6660
|
+
pendingRef.current = null;
|
|
6661
|
+
if (abort.signal.aborted)
|
|
6219
6662
|
return;
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6663
|
+
startIframe({
|
|
6664
|
+
helperRef,
|
|
6665
|
+
iframe,
|
|
6666
|
+
shopId,
|
|
6667
|
+
deviceType,
|
|
6668
|
+
size: viewport,
|
|
6669
|
+
t0,
|
|
6670
|
+
onSuccess: (height) => {
|
|
6671
|
+
if (abort.signal.aborted)
|
|
6672
|
+
return;
|
|
6673
|
+
if (height)
|
|
6674
|
+
setIframeHeight(height);
|
|
6675
|
+
setIsDomLoaded(true);
|
|
6676
|
+
},
|
|
6677
|
+
});
|
|
6678
|
+
}, [viewport]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
6224
6679
|
useEffect(() => {
|
|
6225
6680
|
return () => {
|
|
6226
|
-
setVizRef(null);
|
|
6227
|
-
abortRef.current?.abort();
|
|
6228
6681
|
helperRef.current?.stop();
|
|
6229
6682
|
helperRef.current = null;
|
|
6230
6683
|
};
|
|
6231
|
-
}, [
|
|
6232
|
-
return {
|
|
6684
|
+
}, []);
|
|
6685
|
+
return { run, reset };
|
|
6233
6686
|
};
|
|
6234
6687
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
6235
6688
|
function startIframe({ helperRef, iframe, shopId, deviceType = EDeviceType.Desktop, size, t0, onSuccess, }) {
|
|
@@ -6238,7 +6691,7 @@ function startIframe({ helperRef, iframe, shopId, deviceType = EDeviceType.Deskt
|
|
|
6238
6691
|
if (docHeight === 0)
|
|
6239
6692
|
return;
|
|
6240
6693
|
helperRef.current?.stop();
|
|
6241
|
-
const tHelper = perf.mark('IframeHelper.start');
|
|
6694
|
+
const tHelper = perf$1.mark('IframeHelper.start');
|
|
6242
6695
|
const helper = createIframeHelper();
|
|
6243
6696
|
helperRef.current = helper;
|
|
6244
6697
|
helper.start({
|
|
@@ -6249,17 +6702,88 @@ function startIframe({ helperRef, iframe, shopId, deviceType = EDeviceType.Deskt
|
|
|
6249
6702
|
debug: true,
|
|
6250
6703
|
shopId,
|
|
6251
6704
|
onSuccess: (data) => {
|
|
6252
|
-
perf.measure('IframeHelper processing', tHelper);
|
|
6253
|
-
perf.measure('Total render', t0);
|
|
6705
|
+
perf$1.measure('IframeHelper processing', tHelper);
|
|
6706
|
+
perf$1.measure('Total render', t0);
|
|
6254
6707
|
iframe.style.height = `${data.height}px`;
|
|
6255
6708
|
onSuccess(data.height);
|
|
6256
6709
|
},
|
|
6257
6710
|
});
|
|
6258
6711
|
}
|
|
6259
6712
|
|
|
6713
|
+
const EShortCircuitStrategy = {
|
|
6714
|
+
None: 0,
|
|
6715
|
+
HashFirstTimestamp: 1,
|
|
6716
|
+
HashFirstTimestampPlusBuffer: 2,
|
|
6717
|
+
HashBeforeDeleted: 3,
|
|
6718
|
+
};
|
|
6719
|
+
const perf = createPerfTimer('Render');
|
|
6720
|
+
const useHeatmapRenderDom = () => {
|
|
6721
|
+
const viewId = useViewIdContext();
|
|
6722
|
+
const data = useHeatmapDataContext((s) => s.data);
|
|
6723
|
+
const excludeClassNames = useHeatmapConfigStore((s) => s.excludeClassNames);
|
|
6724
|
+
const setVizRef = useHeatmapVizRectContext((s) => s.setVizRef);
|
|
6725
|
+
const vizRef = useHeatmapVizRectContext((s) => s.vizRef);
|
|
6726
|
+
const setIsDomLoaded = useHeatmapVizContext((s) => s.setIsDomLoaded);
|
|
6727
|
+
const deviceType = useHeatmapSettingContext((s) => s.deviceType);
|
|
6728
|
+
const heatmapType = useHeatmapSettingContext((s) => s.heatmapType);
|
|
6729
|
+
const elementToShow = useHeatmapDataContext((s) => s.dataInfo?.elementToShow);
|
|
6730
|
+
const dataHash = useHeatmapDataContext((s) => s.dataHash);
|
|
6731
|
+
const iframeRef = useRef(null);
|
|
6732
|
+
const abortRef = useRef(null);
|
|
6733
|
+
const elementToShowRef = useRef(null);
|
|
6734
|
+
const dataHashRef = useRef(null);
|
|
6735
|
+
const heatmapTypeRef = useRef(heatmapType);
|
|
6736
|
+
elementToShowRef.current = elementToShow ?? null;
|
|
6737
|
+
dataHashRef.current = dataHash ?? null;
|
|
6738
|
+
heatmapTypeRef.current = heatmapType;
|
|
6739
|
+
const { run: runIframeSetup, reset: resetIframeSetup } = useHeatmapIframeProcessor();
|
|
6740
|
+
const renderHeatmap = useCallback(async (payloads) => {
|
|
6741
|
+
if (!payloads || payloads.length === 0)
|
|
6742
|
+
return;
|
|
6743
|
+
const iframe = iframeRef.current;
|
|
6744
|
+
const contentWindow = iframe?.contentWindow;
|
|
6745
|
+
if (!contentWindow)
|
|
6746
|
+
return;
|
|
6747
|
+
abortRef.current?.abort();
|
|
6748
|
+
const abort = new AbortController();
|
|
6749
|
+
abortRef.current = abort;
|
|
6750
|
+
resetIframeSetup();
|
|
6751
|
+
const t0 = perf.mark('renderHeatmap start');
|
|
6752
|
+
const visualizer = vizRef ?? new GXVisualizer();
|
|
6753
|
+
if (!vizRef)
|
|
6754
|
+
setVizRef(visualizer);
|
|
6755
|
+
visualizer.configure({ excludeClassNames });
|
|
6756
|
+
setIsDomLoaded(false);
|
|
6757
|
+
// Phase 1: render DOM — does not depend on contentWidth/wrapperHeight
|
|
6758
|
+
const hash = elementToShowRef.current ?? undefined;
|
|
6759
|
+
const cacheKey = dataHashRef.current;
|
|
6760
|
+
const strategy = hash ? EShortCircuitStrategy.HashFirstTimestampPlusBuffer : EShortCircuitStrategy.None;
|
|
6761
|
+
await perf.wrap('visualizer.html', () => cacheKey
|
|
6762
|
+
? visualizer.htmlCached(cacheKey, payloads, contentWindow, viewId, hash, undefined, undefined, strategy)
|
|
6763
|
+
: visualizer.html(payloads, contentWindow, viewId, hash, undefined, undefined, strategy));
|
|
6764
|
+
if (abort.signal.aborted)
|
|
6765
|
+
return;
|
|
6766
|
+
// Phase 2: iframe setup — deferred to useIframeSetup (handles dims dependency)
|
|
6767
|
+
runIframeSetup(iframe, t0, abort);
|
|
6768
|
+
}, [deviceType]);
|
|
6769
|
+
useEffect(() => {
|
|
6770
|
+
if (!data || data.length === 0)
|
|
6771
|
+
return;
|
|
6772
|
+
renderHeatmap(decodeArrayClarity(data));
|
|
6773
|
+
}, [data, renderHeatmap]);
|
|
6774
|
+
useEffect(() => {
|
|
6775
|
+
return () => {
|
|
6776
|
+
iframeRef.current = null;
|
|
6777
|
+
setVizRef(null);
|
|
6778
|
+
// abortRef.current?.abort(); // cancel Phase 2 callbacks
|
|
6779
|
+
};
|
|
6780
|
+
}, [setVizRef]);
|
|
6781
|
+
return { iframeRef };
|
|
6782
|
+
};
|
|
6783
|
+
|
|
6260
6784
|
const useReplayRender = () => {
|
|
6261
6785
|
const data = useHeatmapDataContext((s) => s.data);
|
|
6262
|
-
const
|
|
6786
|
+
const setIsDomLoaded = useHeatmapVizContext((s) => s.setIsDomLoaded);
|
|
6263
6787
|
const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
|
|
6264
6788
|
const visualizerRef = useRef(null);
|
|
6265
6789
|
const iframeRef = useRef(null);
|
|
@@ -6279,7 +6803,7 @@ const useReplayRender = () => {
|
|
|
6279
6803
|
version: envelope.version,
|
|
6280
6804
|
onresize: (height) => {
|
|
6281
6805
|
height && setIframeHeight(height);
|
|
6282
|
-
|
|
6806
|
+
setIsDomLoaded(true);
|
|
6283
6807
|
},
|
|
6284
6808
|
mobile,
|
|
6285
6809
|
vNext: true,
|
|
@@ -6382,10 +6906,12 @@ const useReplayRender = () => {
|
|
|
6382
6906
|
const useHeatmapRenderByMode = (mode) => {
|
|
6383
6907
|
const heatmapResult = useMemo(() => {
|
|
6384
6908
|
switch (mode) {
|
|
6385
|
-
case
|
|
6386
|
-
return
|
|
6387
|
-
case
|
|
6909
|
+
case EHeatmapMode.Heatmap:
|
|
6910
|
+
return useHeatmapRenderDom;
|
|
6911
|
+
case EHeatmapMode.Replay:
|
|
6388
6912
|
return useReplayRender;
|
|
6913
|
+
default:
|
|
6914
|
+
return useHeatmapRenderDom;
|
|
6389
6915
|
}
|
|
6390
6916
|
}, [mode]);
|
|
6391
6917
|
return heatmapResult();
|
|
@@ -6420,22 +6946,10 @@ const useContainerDimensions = (props) => {
|
|
|
6420
6946
|
return { containerWidth, containerHeight };
|
|
6421
6947
|
};
|
|
6422
6948
|
|
|
6423
|
-
const useContentDimensions = ({ iframeRef }) => {
|
|
6424
|
-
const contentWidth = useHeatmapWidthByDevice();
|
|
6425
|
-
useEffect(() => {
|
|
6426
|
-
if (!contentWidth)
|
|
6427
|
-
return;
|
|
6428
|
-
if (!iframeRef.current)
|
|
6429
|
-
return;
|
|
6430
|
-
// iframeRef.current.width = `${contentWidth}px`;
|
|
6431
|
-
}, [contentWidth, iframeRef]);
|
|
6432
|
-
return { contentWidth };
|
|
6433
|
-
};
|
|
6434
|
-
|
|
6435
6949
|
const useObserveIframeHeight = (props) => {
|
|
6436
6950
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
6437
6951
|
const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
|
|
6438
|
-
const
|
|
6952
|
+
const isDomLoaded = useHeatmapVizContext((s) => s.isDomLoaded);
|
|
6439
6953
|
const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
|
|
6440
6954
|
const { iframeRef } = props;
|
|
6441
6955
|
const resizeObserverRef = useRef(null);
|
|
@@ -6496,7 +7010,7 @@ const useObserveIframeHeight = (props) => {
|
|
|
6496
7010
|
}, [updateIframeHeight]);
|
|
6497
7011
|
useEffect(() => {
|
|
6498
7012
|
const iframe = iframeRef.current;
|
|
6499
|
-
if (!iframe || !iframeHeight || !
|
|
7013
|
+
if (!iframe || !iframeHeight || !isDomLoaded)
|
|
6500
7014
|
return;
|
|
6501
7015
|
const setupObservers = () => {
|
|
6502
7016
|
try {
|
|
@@ -6558,7 +7072,7 @@ const useObserveIframeHeight = (props) => {
|
|
|
6558
7072
|
}
|
|
6559
7073
|
iframe.removeEventListener('load', setupObservers);
|
|
6560
7074
|
};
|
|
6561
|
-
}, [iframeRef, iframeHeight,
|
|
7075
|
+
}, [iframeRef, iframeHeight, isDomLoaded]);
|
|
6562
7076
|
return {};
|
|
6563
7077
|
};
|
|
6564
7078
|
|
|
@@ -6571,9 +7085,10 @@ const useScaleCalculation = (props) => {
|
|
|
6571
7085
|
const setScale = useHeatmapVizContext((s) => s.setScale);
|
|
6572
7086
|
const setIsScaledToFit = useHeatmapVizContext((s) => s.setIsScaledToFit);
|
|
6573
7087
|
const setMinZoomRatio = useHeatmapVizContext((s) => s.setMinZoomRatio);
|
|
6574
|
-
const
|
|
7088
|
+
const viewport = useHeatmapViewportByDevice();
|
|
7089
|
+
const { containerWidth, containerHeight, iframeHeight } = props;
|
|
6575
7090
|
const calculateScaleResult = useCallback(() => {
|
|
6576
|
-
if (containerWidth > 0 &&
|
|
7091
|
+
if (containerWidth > 0 && viewport.width > 0 && containerHeight > 0 && iframeHeight > 0) {
|
|
6577
7092
|
// 1. Calculate available dimensions
|
|
6578
7093
|
const availableWidth = containerWidth - HEATMAP_CONFIG['padding'] * 2;
|
|
6579
7094
|
const toolbarHeight = HEATMAP_CONFIG['heightToolbar'] || 0;
|
|
@@ -6581,12 +7096,12 @@ const useScaleCalculation = (props) => {
|
|
|
6581
7096
|
const availableHeight = containerHeight - toolbarHeight - paddingTotal;
|
|
6582
7097
|
// 2. Calculate widthScale (base scale to fit content width into container width)
|
|
6583
7098
|
// This represents 100% zoom (fit to width)
|
|
6584
|
-
const widthScale = Math.min(availableWidth /
|
|
7099
|
+
const widthScale = Math.min(availableWidth / viewport.width, 1);
|
|
6585
7100
|
// 3. Calculate minZoomRatio (zoom ratio to fit height)
|
|
6586
7101
|
// At minZoomRatio, the content should fit entirely within the container height
|
|
6587
|
-
// Formula:
|
|
6588
|
-
// => minZoomRatio = (availableHeight / (
|
|
6589
|
-
const calculatedMinZoomRatio = (availableHeight / (
|
|
7102
|
+
// Formula: iframeHeight * widthScale * (minZoomRatio / 100) = availableHeight
|
|
7103
|
+
// => minZoomRatio = (availableHeight / (iframeHeight * widthScale)) * 100
|
|
7104
|
+
const calculatedMinZoomRatio = (availableHeight / (iframeHeight * widthScale)) * 100;
|
|
6590
7105
|
// Limit minZoomRatio: cannot exceed MAX_ZOOM_RATIO (100%)
|
|
6591
7106
|
// and should have a reasonable minimum (e.g., 1%)
|
|
6592
7107
|
const finalMinZoomRatio = Math.max(1, Math.min(calculatedMinZoomRatio, maxZoomRatio));
|
|
@@ -6605,7 +7120,7 @@ const useScaleCalculation = (props) => {
|
|
|
6605
7120
|
setIsScaledToFit(isCurrentlyFitted);
|
|
6606
7121
|
setMinZoomRatio(finalMinZoomRatio);
|
|
6607
7122
|
}
|
|
6608
|
-
}, [containerWidth, containerHeight,
|
|
7123
|
+
}, [containerWidth, containerHeight, viewport.width, iframeHeight, zoomRatio, maxZoomRatio]);
|
|
6609
7124
|
useEffect(() => {
|
|
6610
7125
|
calculateScaleResult();
|
|
6611
7126
|
}, [calculateScaleResult]);
|
|
@@ -6638,20 +7153,15 @@ const useHeatmapScale = (props) => {
|
|
|
6638
7153
|
// 1. Observe container dimensions
|
|
6639
7154
|
const { containerWidth, containerHeight } = useContainerDimensions({ wrapperRef });
|
|
6640
7155
|
// 2. Get content dimensions from config
|
|
6641
|
-
const
|
|
7156
|
+
const viewport = useHeatmapViewportByDevice();
|
|
6642
7157
|
// 3. Observe iframe height (now reacts to width changes)
|
|
6643
7158
|
useObserveIframeHeight({ iframeRef });
|
|
6644
7159
|
// 4. Calculate scale
|
|
6645
|
-
const { widthScale } = useScaleCalculation({
|
|
6646
|
-
containerWidth,
|
|
6647
|
-
containerHeight,
|
|
6648
|
-
contentWidth,
|
|
6649
|
-
contentHeight: iframeHeight,
|
|
6650
|
-
});
|
|
7160
|
+
const { widthScale } = useScaleCalculation({ containerWidth, containerHeight, iframeHeight });
|
|
6651
7161
|
// 5. Setup scroll sync
|
|
6652
7162
|
const { handleScroll } = useScrollSync({ widthScale, iframeRef });
|
|
6653
7163
|
const scaledHeight = iframeHeight * widthScale;
|
|
6654
|
-
const scaledWidth =
|
|
7164
|
+
const scaledWidth = viewport.width * widthScale;
|
|
6655
7165
|
return {
|
|
6656
7166
|
scaledWidth,
|
|
6657
7167
|
scaledHeight,
|
|
@@ -7690,11 +8200,11 @@ const AutoScrollHandler = ({ visualRef }) => {
|
|
|
7690
8200
|
};
|
|
7691
8201
|
|
|
7692
8202
|
const PortalAreaRenderer = ({ iframeRef, visualRef, shadowRoot, onAreaCreated, onAreaClick, }) => {
|
|
7693
|
-
const
|
|
8203
|
+
const isDomLoaded = useHeatmapVizContext((s) => s.isDomLoaded);
|
|
7694
8204
|
const iframeDocument = iframeRef.current?.contentDocument || undefined;
|
|
7695
8205
|
const { shadowContainer, isReady } = useAreaRendererContainer(iframeDocument, shadowRoot);
|
|
7696
|
-
useAreaRectSync({ iframeDocument, shadowRoot, enabled: isReady &&
|
|
7697
|
-
useAreaPositionsUpdater({ iframeRef, visualRef, enabled: isReady &&
|
|
8206
|
+
useAreaRectSync({ iframeDocument, shadowRoot, enabled: isReady && isDomLoaded });
|
|
8207
|
+
useAreaPositionsUpdater({ iframeRef, visualRef, enabled: isReady && isDomLoaded });
|
|
7698
8208
|
if (!shadowContainer || !isReady)
|
|
7699
8209
|
return null;
|
|
7700
8210
|
return (jsxs(Fragment$1, { children: [jsx(AutoScrollHandler, { visualRef: visualRef }), jsx(AreasPortal, { shadowContainer: shadowContainer, onAreaClick: onAreaClick }), jsx(AreaEditHighlightPortal, { shadowContainer: shadowContainer, iframeRef: iframeRef, customShadowRoot: shadowRoot, onAreaCreated: onAreaCreated })] }));
|
|
@@ -7703,7 +8213,7 @@ const PortalAreaRenderer = ({ iframeRef, visualRef, shadowRoot, onAreaCreated, o
|
|
|
7703
8213
|
const VizAreaClick = ({ iframeRef, visualRef, shadowRoot, autoCreateTopN = 10, enableOverlapResolution = true, onAreaClick, }) => {
|
|
7704
8214
|
const clickAreas = useHeatmapDataContext((s) => s.clickAreas);
|
|
7705
8215
|
const resetView = useHeatmapAreaClickContext((s) => s.resetView);
|
|
7706
|
-
const
|
|
8216
|
+
const isDomLoaded = useHeatmapVizContext((s) => s.isDomLoaded);
|
|
7707
8217
|
useAreaTopAutoDetect({ autoCreateTopN, shadowRoot, disabled: !!clickAreas?.length });
|
|
7708
8218
|
useAreaFilterVisible({ iframeRef, enableOverlapResolution });
|
|
7709
8219
|
useAreaHydration({ shadowRoot });
|
|
@@ -7712,7 +8222,7 @@ const VizAreaClick = ({ iframeRef, visualRef, shadowRoot, autoCreateTopN = 10, e
|
|
|
7712
8222
|
resetView();
|
|
7713
8223
|
};
|
|
7714
8224
|
}, []);
|
|
7715
|
-
if (!iframeRef.current || !
|
|
8225
|
+
if (!iframeRef.current || !isDomLoaded)
|
|
7716
8226
|
return null;
|
|
7717
8227
|
return (jsx(Fragment, { children: jsx(PortalAreaRenderer, { iframeRef: iframeRef, visualRef: visualRef, shadowRoot: shadowRoot, onAreaClick: onAreaClick }) }));
|
|
7718
8228
|
};
|
|
@@ -7843,7 +8353,7 @@ const useAnchorPosition = (calloutRef, props) => {
|
|
|
7843
8353
|
const ElementMissing = ({ show = true, visualRef }) => {
|
|
7844
8354
|
const widthScale = useHeatmapVizContext((s) => s.widthScale);
|
|
7845
8355
|
const missingElementRef = useRef(null);
|
|
7846
|
-
const
|
|
8356
|
+
const viewport = useHeatmapViewportByDevice();
|
|
7847
8357
|
const [scrollPosition, setScrollPosition] = useState({ scrollTop: 0, scrollLeft: 0 });
|
|
7848
8358
|
useEffect(() => {
|
|
7849
8359
|
const container = visualRef.current;
|
|
@@ -7873,7 +8383,7 @@ const ElementMissing = ({ show = true, visualRef }) => {
|
|
|
7873
8383
|
const containerHeight = containerRect?.height ?? 0;
|
|
7874
8384
|
const topPosition = scrollTop + (containerHeight + elementHeightCenter) / 2;
|
|
7875
8385
|
const topPositionScaled = topPosition / widthScale;
|
|
7876
|
-
const leftPosition =
|
|
8386
|
+
const leftPosition = viewport.width / 2;
|
|
7877
8387
|
return (jsxs(Fragment, { children: [jsx("div", { className: "missingElement-backdrop", style: {
|
|
7878
8388
|
position: 'absolute',
|
|
7879
8389
|
top: 0,
|
|
@@ -7998,7 +8508,7 @@ const ElementOverlayComponent = (props) => {
|
|
|
7998
8508
|
const { type, element, onClick, elementId, hideOutline } = props;
|
|
7999
8509
|
const widthScale = useHeatmapVizContext((s) => s.widthScale);
|
|
8000
8510
|
const viewportHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
8001
|
-
const
|
|
8511
|
+
const viewport = useHeatmapViewportByDevice();
|
|
8002
8512
|
const overlayStyle = useMemo(() => {
|
|
8003
8513
|
const isInvalid = !element || (element.width === 0 && element.height === 0);
|
|
8004
8514
|
if (isInvalid)
|
|
@@ -8015,7 +8525,7 @@ const ElementOverlayComponent = (props) => {
|
|
|
8015
8525
|
const isHovered = type === 'hovered';
|
|
8016
8526
|
const badgeWidthScale = isHovered ? 1 : widthScale;
|
|
8017
8527
|
const showCallout = !!element?.mousePosition && !isHovered;
|
|
8018
|
-
return (jsxs(Fragment$1, { children: [jsx("div", { onClick: onClick, className: `heatmapElement heatmapElement--${type} ${hideOutline ? 'heatmapElement--hide-outline' : ''}`, id: elementId, style: overlayStyle, children: showCallout && jsx(ElementCalloutOverlay, { ...props }) }), jsx(BackdropCanvas, { activeElement: overlayStyle, viewportWidth:
|
|
8528
|
+
return (jsxs(Fragment$1, { children: [jsx("div", { onClick: onClick, className: `heatmapElement heatmapElement--${type} ${hideOutline ? 'heatmapElement--hide-outline' : ''}`, id: elementId, style: overlayStyle, children: showCallout && jsx(ElementCalloutOverlay, { ...props }) }), jsx(BackdropCanvas, { activeElement: overlayStyle, viewportWidth: viewport.width, viewportHeight: viewportHeight, show: !isHovered }), jsx(RankBadge, { hash: element.hash, show: isHovered, index: element.rank, elementRect: element, widthScale: badgeWidthScale, clickOnElement: onClick })] }));
|
|
8019
8529
|
};
|
|
8020
8530
|
ElementOverlayComponent.displayName = 'ElementOverlay';
|
|
8021
8531
|
const ElementOverlay = memo(ElementOverlayComponent);
|
|
@@ -8080,7 +8590,7 @@ const HeatmapElements = (props) => {
|
|
|
8080
8590
|
};
|
|
8081
8591
|
|
|
8082
8592
|
const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
|
|
8083
|
-
const
|
|
8593
|
+
const viewport = useHeatmapViewportByDevice();
|
|
8084
8594
|
const dataInfo = useHeatmapDataContext((s) => s.dataInfo);
|
|
8085
8595
|
const vizRef = useHeatmapVizRectContext((s) => s.vizRef);
|
|
8086
8596
|
const visualizer = {
|
|
@@ -8094,7 +8604,7 @@ const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
|
|
|
8094
8604
|
if (!iframeRef.current)
|
|
8095
8605
|
return null;
|
|
8096
8606
|
return (jsx(HeatmapElements, { visualizer: visualizer, visualRef: visualRef, iframeRef: iframeRef, wrapperRef: wrapperRef, heatmapInfo: dataInfo, isVisible: true, positionMode: DEFAULT_POSITION_MODE, isHideTopRank: true, iframeDimensions: {
|
|
8097
|
-
width:
|
|
8607
|
+
width: viewport.width,
|
|
8098
8608
|
position: 'absolute',
|
|
8099
8609
|
top: 0,
|
|
8100
8610
|
left: 0,
|
|
@@ -8358,7 +8868,7 @@ const VizLoadingCanvas = () => {
|
|
|
8358
8868
|
const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHeight, onScroll, }) => {
|
|
8359
8869
|
const isLoadingCanvas = useHeatmapSettingContext((state) => state.isLoadingCanvas);
|
|
8360
8870
|
const widthScale = useHeatmapVizContext((s) => s.widthScale);
|
|
8361
|
-
const
|
|
8871
|
+
const viewport = useHeatmapViewportByDevice();
|
|
8362
8872
|
const contentHeight = calcContentHeight();
|
|
8363
8873
|
return (jsx("div", { ref: visualRef, className: "gx-hm-visual Polaris-Scrollable Polaris-Scrollable--vertical Polaris-Scrollable--scrollbarWidthThin Polaris-Scrollable--scrollbarGutterStable", onScroll: onScroll, style: {
|
|
8364
8874
|
overflowX: 'hidden',
|
|
@@ -8380,7 +8890,7 @@ const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHe
|
|
|
8380
8890
|
paddingBottom: HEATMAP_STYLE['viz']['paddingBottom'],
|
|
8381
8891
|
background: HEATMAP_STYLE['viz']['background'],
|
|
8382
8892
|
}, children: jsx("div", { className: "gx-hm-wrapper", ref: wrapperRef, style: {
|
|
8383
|
-
width:
|
|
8893
|
+
width: viewport.width,
|
|
8384
8894
|
height: iframeHeight,
|
|
8385
8895
|
transform: `scale(${widthScale})`,
|
|
8386
8896
|
transformOrigin: 'top center',
|
|
@@ -8393,14 +8903,14 @@ const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHe
|
|
|
8393
8903
|
}
|
|
8394
8904
|
};
|
|
8395
8905
|
|
|
8396
|
-
const VizDomRenderer = ({ mode
|
|
8906
|
+
const VizDomRenderer = ({ mode }) => {
|
|
8397
8907
|
const viewId = useViewIdContext();
|
|
8398
|
-
const
|
|
8908
|
+
const viewport = useHeatmapViewportByDevice();
|
|
8399
8909
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
8400
8910
|
const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
|
|
8401
8911
|
const wrapperRef = useRef(null);
|
|
8402
8912
|
const visualRef = useRef(null);
|
|
8403
|
-
const { iframeRef } =
|
|
8913
|
+
const { iframeRef } = useHeatmapRenderDom();
|
|
8404
8914
|
const { scaledHeight, handleScroll } = useHeatmapScale({ wrapperRef, iframeRef, visualRef });
|
|
8405
8915
|
useHeatmapCanvas();
|
|
8406
8916
|
useRenderCount('VizDomRenderer');
|
|
@@ -8408,7 +8918,7 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
|
|
|
8408
8918
|
const scrollTop = e.currentTarget.scrollTop;
|
|
8409
8919
|
handleScroll(scrollTop);
|
|
8410
8920
|
};
|
|
8411
|
-
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:
|
|
8921
|
+
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: viewport.width, height: wrapperHeight }), jsx(VizLoadingCanvas, {}), jsx(VizScrollMap, { visualRef: visualRef, iframeRef: iframeRef, wrapperRef: wrapperRef })] }));
|
|
8412
8922
|
};
|
|
8413
8923
|
|
|
8414
8924
|
const VizLoading = () => {
|
|
@@ -8425,8 +8935,9 @@ const VizLoading = () => {
|
|
|
8425
8935
|
const VizDomHeatmap = () => {
|
|
8426
8936
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
8427
8937
|
const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
|
|
8938
|
+
const setWrapperHeight = useHeatmapVizRectContext((s) => s.setWrapperHeight);
|
|
8428
8939
|
const setVizRef = useHeatmapVizRectContext((s) => s.setVizRef);
|
|
8429
|
-
const
|
|
8940
|
+
const setIsDomLoaded = useHeatmapVizContext((s) => s.setIsDomLoaded);
|
|
8430
8941
|
const setSelectedElement = useHeatmapClickContext((s) => s.setSelectedElement);
|
|
8431
8942
|
const setHoveredElement = useHeatmapHoverContext((s) => s.setHoveredElement);
|
|
8432
8943
|
// const setSelectedArea = useHeatmapAreaClickContext((s) => s.setSelectedArea);
|
|
@@ -8436,7 +8947,8 @@ const VizDomHeatmap = () => {
|
|
|
8436
8947
|
const cleanUp = () => {
|
|
8437
8948
|
setVizRef(null);
|
|
8438
8949
|
setIframeHeight(0);
|
|
8439
|
-
|
|
8950
|
+
setWrapperHeight(0);
|
|
8951
|
+
setIsDomLoaded(false);
|
|
8440
8952
|
setSelectedElement(null);
|
|
8441
8953
|
setHoveredElement(null);
|
|
8442
8954
|
// setSelectedArea(null);
|
|
@@ -8445,13 +8957,13 @@ const VizDomHeatmap = () => {
|
|
|
8445
8957
|
};
|
|
8446
8958
|
useEffect(() => {
|
|
8447
8959
|
return cleanUp;
|
|
8448
|
-
}, []);
|
|
8449
|
-
return (jsxs(VizContainer, { isActive: true, children: [jsx(VizDomRenderer, {}), iframeHeight === 0 && jsx(VizLoading, {})] }));
|
|
8960
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
8961
|
+
return (jsxs(VizContainer, { isActive: true, children: [jsx(VizDomRenderer, { mode: EHeatmapMode.Heatmap }), iframeHeight === 0 && jsx(VizLoading, {})] }));
|
|
8450
8962
|
};
|
|
8451
8963
|
VizDomHeatmap.displayName = 'VizDomHeatmap';
|
|
8452
8964
|
|
|
8453
8965
|
const VizLiveRenderer = () => {
|
|
8454
|
-
const
|
|
8966
|
+
const viewport = useHeatmapViewportByDevice();
|
|
8455
8967
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
8456
8968
|
const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
|
|
8457
8969
|
const visualRef = useRef(null);
|
|
@@ -8462,7 +8974,7 @@ const VizLiveRenderer = () => {
|
|
|
8462
8974
|
const scrollTop = e.currentTarget.scrollTop;
|
|
8463
8975
|
handleScroll(scrollTop);
|
|
8464
8976
|
};
|
|
8465
|
-
return (jsx(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, iframeHeight: iframeHeight, onScroll: onScroll, children: jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width:
|
|
8977
|
+
return (jsx(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, iframeHeight: iframeHeight, onScroll: onScroll, children: jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: viewport.width, height: wrapperHeight, scrolling: "no" }) }));
|
|
8466
8978
|
};
|
|
8467
8979
|
|
|
8468
8980
|
const VizLiveHeatmap = () => {
|
|
@@ -8553,4 +9065,4 @@ const HeatmapLayout = ({ shopId, data, clickmap, clickAreas, scrollmap, attentio
|
|
|
8553
9065
|
}
|
|
8554
9066
|
};
|
|
8555
9067
|
|
|
8556
|
-
export { BACKDROP_CONFIG, DEFAULT_SIDEBAR_WIDTH, DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO, EClickMode, EClickRankType, EClickType, EDeviceType, EHeatmapDataSource, EHeatmapMode, EHeatmapType, ELM_CALLOUT_CONFIG, EScrollType, GraphView, HEATMAP_CONFIG, HEATMAP_IFRAME, HEATMAP_STYLE, HeatmapLayout, ViewIdContext, Z_INDEX$1 as Z_INDEX, compareViewPerformance, convertViewportToIframeCoords, createStorePerformanceTracker, createViewContextHook, decodeArrayClarity, decodeClarity, 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, useHeatmapLiveContext, useHeatmapRenderByMode, useHeatmapScale, useHeatmapScroll, useHeatmapScrollContext, useHeatmapSettingContext, useHeatmapVizContext, useHeatmapVizRectContext,
|
|
9068
|
+
export { BACKDROP_CONFIG, DEFAULT_SIDEBAR_WIDTH, DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO, EClickMode, EClickRankType, EClickType, EDeviceType, EHeatmapDataSource, EHeatmapMode, EHeatmapType, ELM_CALLOUT_CONFIG, EScrollType, GraphView, HEATMAP_CONFIG, HEATMAP_IFRAME, HEATMAP_STYLE, HeatmapLayout, ViewIdContext, Z_INDEX$1 as Z_INDEX, compareViewPerformance, convertViewportToIframeCoords, createStorePerformanceTracker, createViewContextHook, decodeArrayClarity, decodeClarity, 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, useHeatmapLiveContext, useHeatmapRenderByMode, useHeatmapScale, useHeatmapScroll, useHeatmapScrollContext, useHeatmapSettingContext, useHeatmapViewportByDevice, useHeatmapVizContext, useHeatmapVizRectContext, useHoveredElement, useMeasureFunction, useRegisterConfig, useRegisterControl, useRegisterData, useRegisterHeatmap, useRenderCount, useScrollmapZones, useTrackHookCall, useViewIdContext, useVizLiveRender, useWhyDidYouUpdate, useWrapperRefHeight, useZonePositions, withPerformanceTracking };
|