@gemx-dev/heatmap-react 3.5.92-dev.16 → 3.5.92-dev.19
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 +683 -187
- package/dist/esm/index.mjs +683 -187
- 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,20 @@ 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);
|
|
3508
3527
|
const start = useCallback(() => {
|
|
3509
|
-
if (!vizRef || !clickmap || clickmap.length === 0 || !
|
|
3528
|
+
if (!vizRef || !clickmap || clickmap.length === 0 || !isDomLoaded)
|
|
3510
3529
|
return;
|
|
3511
3530
|
try {
|
|
3512
|
-
|
|
3513
|
-
|
|
3531
|
+
requestIdleCallback(() => {
|
|
3532
|
+
vizRef?.clearmap?.();
|
|
3533
|
+
vizRef?.clickmap?.(clickmap);
|
|
3534
|
+
}, { timeout: 300 });
|
|
3514
3535
|
}
|
|
3515
3536
|
catch (error) {
|
|
3516
3537
|
console.error(`🚀 🐥 ~ useClickmap ~ error:`, error);
|
|
3517
3538
|
}
|
|
3518
|
-
}, [vizRef, clickmap,
|
|
3539
|
+
}, [vizRef, clickmap, isDomLoaded]);
|
|
3519
3540
|
return { start };
|
|
3520
3541
|
};
|
|
3521
3542
|
|
|
@@ -3523,6 +3544,7 @@ const useScrollmap = () => {
|
|
|
3523
3544
|
const vizRef = useHeatmapVizRectContext((s) => s.vizRef);
|
|
3524
3545
|
const scrollType = useHeatmapSettingContext((s) => s.scrollType);
|
|
3525
3546
|
const scrollmap = useHeatmapDataContext((s) => s.scrollmap);
|
|
3547
|
+
const isDomLoaded = useHeatmapVizContext((s) => s.isDomLoaded);
|
|
3526
3548
|
useMemo(() => {
|
|
3527
3549
|
switch (scrollType) {
|
|
3528
3550
|
case EScrollType.Depth:
|
|
@@ -3536,16 +3558,18 @@ const useScrollmap = () => {
|
|
|
3536
3558
|
}
|
|
3537
3559
|
}, [scrollmap, scrollType]);
|
|
3538
3560
|
const start = useCallback(() => {
|
|
3539
|
-
if (!vizRef || !scrollmap || scrollmap.length === 0)
|
|
3561
|
+
if (!vizRef || !scrollmap || scrollmap.length === 0 || !isDomLoaded)
|
|
3540
3562
|
return;
|
|
3541
3563
|
try {
|
|
3542
|
-
|
|
3543
|
-
|
|
3564
|
+
requestIdleCallback(() => {
|
|
3565
|
+
vizRef?.clearmap?.();
|
|
3566
|
+
vizRef?.scrollmap?.(scrollmap);
|
|
3567
|
+
}, { timeout: 300 });
|
|
3544
3568
|
}
|
|
3545
3569
|
catch (error) {
|
|
3546
3570
|
logger$4.error(`🚀 🐥 ~ useScrollmap ~ error:`, error);
|
|
3547
3571
|
}
|
|
3548
|
-
}, [vizRef, scrollmap]);
|
|
3572
|
+
}, [vizRef, scrollmap, isDomLoaded]);
|
|
3549
3573
|
return { start };
|
|
3550
3574
|
};
|
|
3551
3575
|
|
|
@@ -3709,7 +3733,7 @@ const useHeatmapEffects = ({ isVisible }) => {
|
|
|
3709
3733
|
};
|
|
3710
3734
|
|
|
3711
3735
|
const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
|
|
3712
|
-
const
|
|
3736
|
+
const viewport = useHeatmapViewportByDevice();
|
|
3713
3737
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
3714
3738
|
const widthScale = useHeatmapVizContext((s) => s.widthScale);
|
|
3715
3739
|
const getRect = useCallback((element) => {
|
|
@@ -3737,17 +3761,17 @@ const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
|
|
|
3737
3761
|
const outOfBounds = adjustedTop < 0 ||
|
|
3738
3762
|
adjustedTop > (iframeHeight || Infinity) ||
|
|
3739
3763
|
layout.left < 0 ||
|
|
3740
|
-
(typeof
|
|
3764
|
+
(typeof viewport.width === 'number' && layout.left > viewport.width);
|
|
3741
3765
|
if (outOfBounds)
|
|
3742
3766
|
return null;
|
|
3743
3767
|
return {
|
|
3744
3768
|
left: layout.left,
|
|
3745
3769
|
top: adjustedTop,
|
|
3746
|
-
width: Math.min(layout.width,
|
|
3770
|
+
width: Math.min(layout.width, viewport.width || layout.width),
|
|
3747
3771
|
height: layout.height,
|
|
3748
3772
|
outOfBounds,
|
|
3749
3773
|
};
|
|
3750
|
-
}, [iframeRef, wrapperRef, visualizer,
|
|
3774
|
+
}, [iframeRef, wrapperRef, visualizer, viewport, iframeHeight, widthScale]);
|
|
3751
3775
|
return { getRect };
|
|
3752
3776
|
};
|
|
3753
3777
|
|
|
@@ -4148,7 +4172,7 @@ function flush() {
|
|
|
4148
4172
|
window.__gemxPerf = getReport();
|
|
4149
4173
|
}
|
|
4150
4174
|
// ── Global singleton export ───────────────────────────────────────────────────
|
|
4151
|
-
const perf$
|
|
4175
|
+
const perf$2 = {
|
|
4152
4176
|
startSession,
|
|
4153
4177
|
endSession,
|
|
4154
4178
|
mark: globalMark,
|
|
@@ -4941,7 +4965,7 @@ const YIELD_EVERY_RULES = 100;
|
|
|
4941
4965
|
* Uses `scheduler.yield()` (Chrome 115+) when available; falls back to a
|
|
4942
4966
|
* zero-timeout macrotask which is universally supported.
|
|
4943
4967
|
*/
|
|
4944
|
-
function yieldToMain() {
|
|
4968
|
+
function yieldToMain$1() {
|
|
4945
4969
|
if (typeof globalThis !== 'undefined' && 'scheduler' in globalThis) {
|
|
4946
4970
|
return globalThis.scheduler.yield();
|
|
4947
4971
|
}
|
|
@@ -5101,7 +5125,7 @@ async function processStylesheets(ctx) {
|
|
|
5101
5125
|
rulesSinceYield++;
|
|
5102
5126
|
if (rulesSinceYield >= YIELD_EVERY_RULES) {
|
|
5103
5127
|
rulesSinceYield = 0;
|
|
5104
|
-
await yieldToMain();
|
|
5128
|
+
await yieldToMain$1();
|
|
5105
5129
|
}
|
|
5106
5130
|
}
|
|
5107
5131
|
}
|
|
@@ -5384,52 +5408,52 @@ function configure(debug) {
|
|
|
5384
5408
|
}
|
|
5385
5409
|
async function run$1(ctx, activeGlobal, shopFix) {
|
|
5386
5410
|
// ── Phase 1: beforeProcess ────────────────────────────────────────────────
|
|
5387
|
-
const t1 = perf$
|
|
5411
|
+
const t1 = perf$2.mark('phase1.beforeProcess');
|
|
5388
5412
|
for (const fix of activeGlobal) {
|
|
5389
5413
|
if (fix.beforeProcess) {
|
|
5390
5414
|
logger.log(`[beforeProcess] ${fix.name}`);
|
|
5391
|
-
const t = perf$
|
|
5415
|
+
const t = perf$2.mark(`phase1.${fix.name}.beforeProcess`);
|
|
5392
5416
|
await fix.beforeProcess(ctx);
|
|
5393
|
-
perf$
|
|
5417
|
+
perf$2.measure(`phase1.${fix.name}.beforeProcess`, t);
|
|
5394
5418
|
}
|
|
5395
5419
|
}
|
|
5396
5420
|
if (shopFix?.beforeProcess) {
|
|
5397
5421
|
logger.log('[beforeProcess] shop');
|
|
5398
|
-
const t = perf$
|
|
5422
|
+
const t = perf$2.mark('phase1.shop.beforeProcess');
|
|
5399
5423
|
await shopFix.beforeProcess(ctx);
|
|
5400
|
-
perf$
|
|
5424
|
+
perf$2.measure('phase1.shop.beforeProcess', t);
|
|
5401
5425
|
}
|
|
5402
|
-
perf$
|
|
5426
|
+
perf$2.measure('phase1.beforeProcess', t1);
|
|
5403
5427
|
// ── Phase 2: process ──────────────────────────────────────────────────────
|
|
5404
|
-
const t2 = perf$
|
|
5428
|
+
const t2 = perf$2.mark('phase2.process');
|
|
5405
5429
|
for (const fix of activeGlobal) {
|
|
5406
5430
|
if (fix.process) {
|
|
5407
5431
|
logger.log(`[process] ${fix.name}`);
|
|
5408
|
-
const t = perf$
|
|
5432
|
+
const t = perf$2.mark(`phase2.${fix.name}.process`);
|
|
5409
5433
|
await fix.process(ctx);
|
|
5410
|
-
perf$
|
|
5434
|
+
perf$2.measure(`phase2.${fix.name}.process`, t);
|
|
5411
5435
|
}
|
|
5412
5436
|
}
|
|
5413
|
-
perf$
|
|
5437
|
+
perf$2.measure('phase2.process', t2);
|
|
5414
5438
|
// ── Phase 3: afterProcess ─────────────────────────────────────────────────
|
|
5415
|
-
const t3 = perf$
|
|
5439
|
+
const t3 = perf$2.mark('phase3.afterProcess');
|
|
5416
5440
|
if (shopFix?.afterProcess) {
|
|
5417
5441
|
logger.log('[afterProcess] shop');
|
|
5418
|
-
const t = perf$
|
|
5442
|
+
const t = perf$2.mark('phase3.shop.afterProcess');
|
|
5419
5443
|
await shopFix.afterProcess(ctx);
|
|
5420
|
-
perf$
|
|
5444
|
+
perf$2.measure('phase3.shop.afterProcess', t);
|
|
5421
5445
|
}
|
|
5422
5446
|
for (const fix of activeGlobal) {
|
|
5423
5447
|
if (fix.afterProcess) {
|
|
5424
5448
|
logger.log(`[afterProcess] ${fix.name}`);
|
|
5425
|
-
const t = perf$
|
|
5449
|
+
const t = perf$2.mark(`phase3.${fix.name}.afterProcess`);
|
|
5426
5450
|
await fix.afterProcess(ctx);
|
|
5427
|
-
perf$
|
|
5451
|
+
perf$2.measure(`phase3.${fix.name}.afterProcess`, t);
|
|
5428
5452
|
}
|
|
5429
5453
|
}
|
|
5430
|
-
perf$
|
|
5454
|
+
perf$2.measure('phase3.afterProcess', t3);
|
|
5431
5455
|
// ── Phase 4: getDimensions ────────────────────────────────────────────────
|
|
5432
|
-
const t4 = perf$
|
|
5456
|
+
const t4 = perf$2.mark('phase4.getDimensions');
|
|
5433
5457
|
return new Promise((resolve) => {
|
|
5434
5458
|
requestAnimationFrame(() => {
|
|
5435
5459
|
let dimensions = null;
|
|
@@ -5454,7 +5478,7 @@ async function run$1(ctx, activeGlobal, shopFix) {
|
|
|
5454
5478
|
dimensions = { height: getFinalHeight(ctx.doc, ctx.win), width: getFinalWidth(ctx.doc) };
|
|
5455
5479
|
}
|
|
5456
5480
|
logger.log('Final dimensions:', dimensions);
|
|
5457
|
-
perf$
|
|
5481
|
+
perf$2.measure('phase4.getDimensions', t4);
|
|
5458
5482
|
resolve(dimensions);
|
|
5459
5483
|
});
|
|
5460
5484
|
});
|
|
@@ -5582,14 +5606,14 @@ async function run(s) {
|
|
|
5582
5606
|
const activeGlobal = getActiveFixes(ctx);
|
|
5583
5607
|
if (activeGlobal.length > 0)
|
|
5584
5608
|
s.logger.log(`Active global fixes: ${activeGlobal.map((f) => f.name).join(', ')}`);
|
|
5585
|
-
const tRun = perf$
|
|
5609
|
+
const tRun = perf$2.mark('viewport.run');
|
|
5586
5610
|
try {
|
|
5587
5611
|
const result = await run$1(ctx, activeGlobal, s.shopFix);
|
|
5588
|
-
perf$
|
|
5612
|
+
perf$2.measure('viewport.run', tRun);
|
|
5589
5613
|
return result;
|
|
5590
5614
|
}
|
|
5591
5615
|
catch (err) {
|
|
5592
|
-
perf$
|
|
5616
|
+
perf$2.measure('viewport.run', tRun);
|
|
5593
5617
|
s.logger.error('Critical error:', err);
|
|
5594
5618
|
return { height: s.doc.body?.scrollHeight || 1000, width: s.doc.body?.scrollWidth || 1000 };
|
|
5595
5619
|
}
|
|
@@ -5639,22 +5663,22 @@ async function process(s) {
|
|
|
5639
5663
|
return;
|
|
5640
5664
|
}
|
|
5641
5665
|
const sessionId = `render-${Date.now()}`;
|
|
5642
|
-
perf$
|
|
5643
|
-
const t0 = perf$
|
|
5666
|
+
perf$2.startSession(sessionId);
|
|
5667
|
+
const t0 = perf$2.mark('orchestrator.process');
|
|
5644
5668
|
try {
|
|
5645
5669
|
s.logger.log('Processing viewport units...');
|
|
5646
5670
|
s.viewportReplacer.start(s.iframe, s.config);
|
|
5647
5671
|
s.navigationBlocker.start(s.iframe, { debug: s.config.debug });
|
|
5648
5672
|
const result = await s.viewportReplacer.run();
|
|
5649
|
-
perf$
|
|
5650
|
-
perf$
|
|
5673
|
+
perf$2.measure('orchestrator.process', t0);
|
|
5674
|
+
perf$2.endSession();
|
|
5651
5675
|
s.logger.log('Process completed:', result);
|
|
5652
5676
|
s.config.onSuccess?.(result);
|
|
5653
5677
|
dispatchDimensionsEvent(result);
|
|
5654
5678
|
}
|
|
5655
5679
|
catch (error) {
|
|
5656
|
-
perf$
|
|
5657
|
-
perf$
|
|
5680
|
+
perf$2.measure('orchestrator.process', t0);
|
|
5681
|
+
perf$2.endSession();
|
|
5658
5682
|
s.logger.error('Failed to process:', error);
|
|
5659
5683
|
s.config.onError?.(error);
|
|
5660
5684
|
}
|
|
@@ -5805,13 +5829,13 @@ function useVizLiveRender() {
|
|
|
5805
5829
|
const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
|
|
5806
5830
|
const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
|
|
5807
5831
|
const wrapperWidth = useHeatmapVizRectContext((s) => s.wrapperWidth);
|
|
5808
|
-
const
|
|
5832
|
+
const setIsDomLoaded = useHeatmapVizContext((s) => s.setIsDomLoaded);
|
|
5809
5833
|
const htmlContent = useHeatmapLiveContext((s) => s.htmlContent);
|
|
5810
5834
|
const targetUrl = useHeatmapLiveContext((s) => s.targetUrl);
|
|
5811
5835
|
const deviceType = useHeatmapSettingContext((s) => s.deviceType);
|
|
5812
5836
|
const renderMode = useHeatmapLiveContext((s) => s.renderMode);
|
|
5813
5837
|
const storefrontPassword = useHeatmapLiveContext((s) => s.storefrontPassword);
|
|
5814
|
-
|
|
5838
|
+
useHeatmapViewportByDevice();
|
|
5815
5839
|
const { iframeRef, isReady } = useVizLiveIframeMsg();
|
|
5816
5840
|
// Handle iframe rendering based on mode
|
|
5817
5841
|
useEffect(() => {
|
|
@@ -5851,10 +5875,10 @@ function useVizLiveRender() {
|
|
|
5851
5875
|
const hasContent = (renderMode === 'portal' && targetUrl) || (renderMode === 'inline' && htmlContent);
|
|
5852
5876
|
if (!iframe || !hasContent)
|
|
5853
5877
|
return;
|
|
5854
|
-
|
|
5878
|
+
setIsDomLoaded(true);
|
|
5855
5879
|
startIframe$1(iframe, deviceType, { width: wrapperWidth, height: wrapperHeight }, (height) => {
|
|
5856
5880
|
height && setIframeHeight(height);
|
|
5857
|
-
|
|
5881
|
+
setIsDomLoaded(true);
|
|
5858
5882
|
});
|
|
5859
5883
|
return () => { };
|
|
5860
5884
|
}, [
|
|
@@ -5866,7 +5890,7 @@ function useVizLiveRender() {
|
|
|
5866
5890
|
targetUrl,
|
|
5867
5891
|
htmlContent,
|
|
5868
5892
|
iframeRef,
|
|
5869
|
-
|
|
5893
|
+
setIsDomLoaded,
|
|
5870
5894
|
setIframeHeight,
|
|
5871
5895
|
]);
|
|
5872
5896
|
return {
|
|
@@ -5901,6 +5925,109 @@ function startIframe$1(iframe, deviceType = EDeviceType.Desktop, rect, onSuccess
|
|
|
5901
5925
|
iframeHelper.enableNavigationBlocking();
|
|
5902
5926
|
}
|
|
5903
5927
|
|
|
5928
|
+
const DEFAULT_CONFIG = {
|
|
5929
|
+
dbName: 'gx-viz-html-cache',
|
|
5930
|
+
maxEntries: 20,
|
|
5931
|
+
ttlMs: 24 * 60 * 60 * 1000, // 24 hours
|
|
5932
|
+
cacheVersion: 3.0,
|
|
5933
|
+
};
|
|
5934
|
+
let _config = { ...DEFAULT_CONFIG };
|
|
5935
|
+
function getHtmlCacheConfig() {
|
|
5936
|
+
return _config;
|
|
5937
|
+
}
|
|
5938
|
+
/** Build a full cache key that includes the cache version to handle invalidation. */
|
|
5939
|
+
function buildCacheKey(baseKey, shortCircuitStrategy) {
|
|
5940
|
+
return `v${_config.cacheVersion}:${baseKey}:${shortCircuitStrategy}`;
|
|
5941
|
+
}
|
|
5942
|
+
|
|
5943
|
+
const STORE_NAME = 'entries';
|
|
5944
|
+
const IDB_SCHEMA_VERSION = 1;
|
|
5945
|
+
function openDb() {
|
|
5946
|
+
const { dbName } = getHtmlCacheConfig();
|
|
5947
|
+
return new Promise((resolve, reject) => {
|
|
5948
|
+
const req = indexedDB.open(dbName, IDB_SCHEMA_VERSION);
|
|
5949
|
+
req.onupgradeneeded = () => {
|
|
5950
|
+
const db = req.result;
|
|
5951
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
5952
|
+
const store = db.createObjectStore(STORE_NAME, { keyPath: 'key' });
|
|
5953
|
+
store.createIndex('timestamp', 'timestamp');
|
|
5954
|
+
}
|
|
5955
|
+
};
|
|
5956
|
+
req.onsuccess = () => resolve(req.result);
|
|
5957
|
+
req.onerror = () => reject(req.error);
|
|
5958
|
+
});
|
|
5959
|
+
}
|
|
5960
|
+
async function evict(db) {
|
|
5961
|
+
const { maxEntries } = getHtmlCacheConfig();
|
|
5962
|
+
return new Promise((resolve) => {
|
|
5963
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
5964
|
+
const store = tx.objectStore(STORE_NAME);
|
|
5965
|
+
const countReq = store.count();
|
|
5966
|
+
countReq.onsuccess = () => {
|
|
5967
|
+
if (countReq.result <= maxEntries) {
|
|
5968
|
+
resolve();
|
|
5969
|
+
return;
|
|
5970
|
+
}
|
|
5971
|
+
const idx = store.index('timestamp');
|
|
5972
|
+
const cursorReq = idx.openCursor();
|
|
5973
|
+
let toDelete = countReq.result - maxEntries;
|
|
5974
|
+
cursorReq.onsuccess = () => {
|
|
5975
|
+
const cursor = cursorReq.result;
|
|
5976
|
+
if (cursor && toDelete > 0) {
|
|
5977
|
+
cursor.delete();
|
|
5978
|
+
toDelete--;
|
|
5979
|
+
cursor.continue();
|
|
5980
|
+
}
|
|
5981
|
+
else {
|
|
5982
|
+
resolve();
|
|
5983
|
+
}
|
|
5984
|
+
};
|
|
5985
|
+
cursorReq.onerror = () => resolve();
|
|
5986
|
+
};
|
|
5987
|
+
countReq.onerror = () => resolve();
|
|
5988
|
+
});
|
|
5989
|
+
}
|
|
5990
|
+
const htmlCache = {
|
|
5991
|
+
async get(key) {
|
|
5992
|
+
try {
|
|
5993
|
+
const { ttlMs } = getHtmlCacheConfig();
|
|
5994
|
+
const db = await openDb();
|
|
5995
|
+
return new Promise((resolve) => {
|
|
5996
|
+
const tx = db.transaction(STORE_NAME, 'readonly');
|
|
5997
|
+
const req = tx.objectStore(STORE_NAME).get(key);
|
|
5998
|
+
req.onsuccess = () => {
|
|
5999
|
+
const entry = req.result;
|
|
6000
|
+
if (!entry || Date.now() - entry.timestamp > ttlMs) {
|
|
6001
|
+
resolve(null);
|
|
6002
|
+
}
|
|
6003
|
+
else {
|
|
6004
|
+
resolve(entry);
|
|
6005
|
+
}
|
|
6006
|
+
};
|
|
6007
|
+
req.onerror = () => resolve(null);
|
|
6008
|
+
});
|
|
6009
|
+
}
|
|
6010
|
+
catch {
|
|
6011
|
+
return null;
|
|
6012
|
+
}
|
|
6013
|
+
},
|
|
6014
|
+
async set(entry) {
|
|
6015
|
+
try {
|
|
6016
|
+
const db = await openDb();
|
|
6017
|
+
await new Promise((resolve, reject) => {
|
|
6018
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
6019
|
+
tx.objectStore(STORE_NAME).put(entry);
|
|
6020
|
+
tx.oncomplete = () => resolve();
|
|
6021
|
+
tx.onerror = () => reject(tx.error);
|
|
6022
|
+
});
|
|
6023
|
+
await evict(db);
|
|
6024
|
+
}
|
|
6025
|
+
catch {
|
|
6026
|
+
// ignore cache write errors
|
|
6027
|
+
}
|
|
6028
|
+
},
|
|
6029
|
+
};
|
|
6030
|
+
|
|
5904
6031
|
const CANVAS_ID = 'clarity-heatmap-canvas';
|
|
5905
6032
|
const ATTENTION_HUES = [240, 210, 180, 150, 120, 90, 60, 30, 0];
|
|
5906
6033
|
const CANVAS_MAX_HEIGHT = 65535;
|
|
@@ -6109,6 +6236,250 @@ class AttentionMapRenderer {
|
|
|
6109
6236
|
};
|
|
6110
6237
|
}
|
|
6111
6238
|
|
|
6239
|
+
var Event;
|
|
6240
|
+
(function (Event) {
|
|
6241
|
+
/* Data */
|
|
6242
|
+
Event[Event["Metric"] = 0] = "Metric";
|
|
6243
|
+
Event[Event["Dimension"] = 1] = "Dimension";
|
|
6244
|
+
Event[Event["Upload"] = 2] = "Upload";
|
|
6245
|
+
Event[Event["Upgrade"] = 3] = "Upgrade";
|
|
6246
|
+
Event[Event["Baseline"] = 4] = "Baseline";
|
|
6247
|
+
Event[Event["Discover"] = 5] = "Discover";
|
|
6248
|
+
Event[Event["Mutation"] = 6] = "Mutation";
|
|
6249
|
+
Event[Event["Region"] = 7] = "Region";
|
|
6250
|
+
Event[Event["Document"] = 8] = "Document";
|
|
6251
|
+
Event[Event["Click"] = 9] = "Click";
|
|
6252
|
+
Event[Event["Scroll"] = 10] = "Scroll";
|
|
6253
|
+
Event[Event["Resize"] = 11] = "Resize";
|
|
6254
|
+
Event[Event["MouseMove"] = 12] = "MouseMove";
|
|
6255
|
+
Event[Event["MouseDown"] = 13] = "MouseDown";
|
|
6256
|
+
Event[Event["MouseUp"] = 14] = "MouseUp";
|
|
6257
|
+
Event[Event["MouseWheel"] = 15] = "MouseWheel";
|
|
6258
|
+
Event[Event["DoubleClick"] = 16] = "DoubleClick";
|
|
6259
|
+
Event[Event["TouchStart"] = 17] = "TouchStart";
|
|
6260
|
+
Event[Event["TouchEnd"] = 18] = "TouchEnd";
|
|
6261
|
+
Event[Event["TouchMove"] = 19] = "TouchMove";
|
|
6262
|
+
Event[Event["TouchCancel"] = 20] = "TouchCancel";
|
|
6263
|
+
Event[Event["Selection"] = 21] = "Selection";
|
|
6264
|
+
Event[Event["Timeline"] = 22] = "Timeline";
|
|
6265
|
+
Event[Event["Page"] = 23] = "Page";
|
|
6266
|
+
Event[Event["Custom"] = 24] = "Custom";
|
|
6267
|
+
Event[Event["Ping"] = 25] = "Ping";
|
|
6268
|
+
Event[Event["Unload"] = 26] = "Unload";
|
|
6269
|
+
Event[Event["Input"] = 27] = "Input";
|
|
6270
|
+
Event[Event["Visibility"] = 28] = "Visibility";
|
|
6271
|
+
Event[Event["Navigation"] = 29] = "Navigation";
|
|
6272
|
+
/**
|
|
6273
|
+
* @deprecated No longer support Network Connection
|
|
6274
|
+
*/
|
|
6275
|
+
Event[Event["Connection"] = 30] = "Connection";
|
|
6276
|
+
Event[Event["ScriptError"] = 31] = "ScriptError";
|
|
6277
|
+
/**
|
|
6278
|
+
* @deprecated No longer support Image Error
|
|
6279
|
+
*/
|
|
6280
|
+
Event[Event["ImageError"] = 32] = "ImageError";
|
|
6281
|
+
Event[Event["Log"] = 33] = "Log";
|
|
6282
|
+
Event[Event["Variable"] = 34] = "Variable";
|
|
6283
|
+
Event[Event["Limit"] = 35] = "Limit";
|
|
6284
|
+
Event[Event["Summary"] = 36] = "Summary";
|
|
6285
|
+
/**
|
|
6286
|
+
* @deprecated No longer support Box event
|
|
6287
|
+
*/
|
|
6288
|
+
Event[Event["Box"] = 37] = "Box";
|
|
6289
|
+
Event[Event["Clipboard"] = 38] = "Clipboard";
|
|
6290
|
+
Event[Event["Submit"] = 39] = "Submit";
|
|
6291
|
+
Event[Event["Extract"] = 40] = "Extract";
|
|
6292
|
+
Event[Event["Fraud"] = 41] = "Fraud";
|
|
6293
|
+
Event[Event["Change"] = 42] = "Change";
|
|
6294
|
+
Event[Event["Snapshot"] = 43] = "Snapshot";
|
|
6295
|
+
Event[Event["Animation"] = 44] = "Animation";
|
|
6296
|
+
Event[Event["StyleSheetAdoption"] = 45] = "StyleSheetAdoption";
|
|
6297
|
+
Event[Event["StyleSheetUpdate"] = 46] = "StyleSheetUpdate";
|
|
6298
|
+
Event[Event["Consent"] = 47] = "Consent";
|
|
6299
|
+
Event[Event["ContextMenu"] = 48] = "ContextMenu";
|
|
6300
|
+
// 49 is reserved for internal use
|
|
6301
|
+
Event[Event["Focus"] = 50] = "Focus";
|
|
6302
|
+
Event[Event["CustomElement"] = 51] = "CustomElement";
|
|
6303
|
+
Event[Event["Chat"] = 52] = "Chat";
|
|
6304
|
+
// Apps specific events
|
|
6305
|
+
Event[Event["WebViewDiscover"] = 100] = "WebViewDiscover";
|
|
6306
|
+
Event[Event["WebViewMutation"] = 101] = "WebViewMutation";
|
|
6307
|
+
Event[Event["MutationError"] = 102] = "MutationError";
|
|
6308
|
+
Event[Event["FragmentVisibility"] = 103] = "FragmentVisibility";
|
|
6309
|
+
Event[Event["Keystrokes"] = 104] = "Keystrokes";
|
|
6310
|
+
Event[Event["BackGesture"] = 105] = "BackGesture";
|
|
6311
|
+
Event[Event["WebViewStatus"] = 106] = "WebViewStatus";
|
|
6312
|
+
Event[Event["AppInstallReferrer"] = 107] = "AppInstallReferrer";
|
|
6313
|
+
// 200-300 reserved for internal use
|
|
6314
|
+
})(Event || (Event = {}));
|
|
6315
|
+
|
|
6316
|
+
var Constant;
|
|
6317
|
+
(function (Constant) {
|
|
6318
|
+
Constant["Empty"] = "";
|
|
6319
|
+
Constant["SvgPrefix"] = "svg:";
|
|
6320
|
+
Constant["DataPrefix"] = "data:";
|
|
6321
|
+
Constant["IFramePrefix"] = "iframe:";
|
|
6322
|
+
Constant["SvgNamespace"] = "http://www.w3.org/2000/svg";
|
|
6323
|
+
Constant["Id"] = "id";
|
|
6324
|
+
Constant["Class"] = "class";
|
|
6325
|
+
Constant["Style"] = "style";
|
|
6326
|
+
Constant["Href"] = "href";
|
|
6327
|
+
Constant["Src"] = "src";
|
|
6328
|
+
Constant["Srcset"] = "srcset";
|
|
6329
|
+
Constant["Hash"] = "#";
|
|
6330
|
+
Constant["Dot"] = ".";
|
|
6331
|
+
Constant["Separator"] = ">";
|
|
6332
|
+
Constant["Tilde"] = "~";
|
|
6333
|
+
Constant["Bang"] = "!";
|
|
6334
|
+
Constant["Period"] = ".";
|
|
6335
|
+
Constant["Comma"] = ",";
|
|
6336
|
+
Constant["DataAttribute"] = "data-";
|
|
6337
|
+
Constant["MaskData"] = "data-clarity-mask";
|
|
6338
|
+
Constant["UnmaskData"] = "data-clarity-unmask";
|
|
6339
|
+
Constant["RegionData"] = "data-clarity-region";
|
|
6340
|
+
Constant["GXDialogModal"] = "gx-dialog-modal";
|
|
6341
|
+
Constant["Type"] = "type";
|
|
6342
|
+
Constant["Submit"] = "submit";
|
|
6343
|
+
Constant["Name"] = "name";
|
|
6344
|
+
Constant["Base"] = "*B";
|
|
6345
|
+
Constant["SameOrigin"] = "*O";
|
|
6346
|
+
Constant["Object"] = "object";
|
|
6347
|
+
Constant["Function"] = "function";
|
|
6348
|
+
Constant["StyleTag"] = "STYLE";
|
|
6349
|
+
Constant["LinkTag"] = "LINK";
|
|
6350
|
+
Constant["InputTag"] = "INPUT";
|
|
6351
|
+
Constant["IFrameTag"] = "IFRAME";
|
|
6352
|
+
Constant["ImageTag"] = "IMG";
|
|
6353
|
+
Constant["TitleTag"] = "TITLE";
|
|
6354
|
+
Constant["BodyTag"] = "BODY";
|
|
6355
|
+
Constant["SvgTag"] = "svg:svg";
|
|
6356
|
+
Constant["BaseTag"] = "BASE";
|
|
6357
|
+
Constant["NativeCode"] = "[native code]";
|
|
6358
|
+
Constant["DocumentTag"] = "*D";
|
|
6359
|
+
Constant["ShadowDomTag"] = "*S";
|
|
6360
|
+
Constant["PolyfillShadowDomTag"] = "*P";
|
|
6361
|
+
Constant["TextTag"] = "*T";
|
|
6362
|
+
Constant["SuspendMutationTag"] = "*M";
|
|
6363
|
+
Constant["ChildList"] = "childList";
|
|
6364
|
+
Constant["Attributes"] = "attributes";
|
|
6365
|
+
Constant["CharacterData"] = "characterData";
|
|
6366
|
+
Constant["Throttle"] = "throttle";
|
|
6367
|
+
Constant["LoadEvent"] = "load";
|
|
6368
|
+
Constant["Pixel"] = "px";
|
|
6369
|
+
Constant["BorderBox"] = "border-box";
|
|
6370
|
+
Constant["Value"] = "value";
|
|
6371
|
+
Constant["MutationObserver"] = "MutationObserver";
|
|
6372
|
+
Constant["JsonLD"] = "application/ld+json";
|
|
6373
|
+
Constant["String"] = "string";
|
|
6374
|
+
Constant["Number"] = "number";
|
|
6375
|
+
Constant["Disable"] = "disable";
|
|
6376
|
+
Constant["HTML"] = "HTML";
|
|
6377
|
+
Constant["Property"] = "property";
|
|
6378
|
+
Constant["Content"] = "content";
|
|
6379
|
+
Constant["Generator"] = "generator";
|
|
6380
|
+
Constant["ogType"] = "og:type";
|
|
6381
|
+
Constant["ogTitle"] = "og:title";
|
|
6382
|
+
Constant["SvgStyle"] = "svg:style";
|
|
6383
|
+
Constant["StyleSheet"] = "stylesheet";
|
|
6384
|
+
})(Constant || (Constant = {}));
|
|
6385
|
+
|
|
6386
|
+
var ShortCircuitStrategy;
|
|
6387
|
+
(function (ShortCircuitStrategy) {
|
|
6388
|
+
ShortCircuitStrategy[ShortCircuitStrategy["None"] = 0] = "None";
|
|
6389
|
+
ShortCircuitStrategy[ShortCircuitStrategy["HashFirstTimestamp"] = 1] = "HashFirstTimestamp";
|
|
6390
|
+
ShortCircuitStrategy[ShortCircuitStrategy["HashFirstTimestampPlusBuffer"] = 2] = "HashFirstTimestampPlusBuffer";
|
|
6391
|
+
ShortCircuitStrategy[ShortCircuitStrategy["HashBeforeDeleted"] = 3] = "HashBeforeDeleted";
|
|
6392
|
+
})(ShortCircuitStrategy || (ShortCircuitStrategy = {}));
|
|
6393
|
+
|
|
6394
|
+
function isShadowDomNode(tag) {
|
|
6395
|
+
return tag === Constant.ShadowDomTag || tag === Constant.PolyfillShadowDomTag;
|
|
6396
|
+
}
|
|
6397
|
+
/** Scan the rendered DOM (including nested shadow roots) to collect tag names of shadow host elements. */
|
|
6398
|
+
function collectShadowHostTags(root, tags = new Set()) {
|
|
6399
|
+
root.querySelectorAll('*').forEach((el) => {
|
|
6400
|
+
if (el.shadowRoot) {
|
|
6401
|
+
tags.add(el.tagName);
|
|
6402
|
+
collectShadowHostTags(el.shadowRoot, tags);
|
|
6403
|
+
}
|
|
6404
|
+
});
|
|
6405
|
+
return tags;
|
|
6406
|
+
}
|
|
6407
|
+
/** Build a shadow subtree ID set from all DOM events.
|
|
6408
|
+
* Two-pass cascade to handle any event ordering:
|
|
6409
|
+
* Pass 1 — seed *S/*P node IDs.
|
|
6410
|
+
* Pass 2 — cascade: any node whose parent is in the set is also in the set (repeat until stable). */
|
|
6411
|
+
function buildShadowSubtreeIds(allDomEvents) {
|
|
6412
|
+
const subtreeIds = new Set();
|
|
6413
|
+
for (const e of allDomEvents) {
|
|
6414
|
+
const data = e.data;
|
|
6415
|
+
for (const node of data ?? []) {
|
|
6416
|
+
if (isShadowDomNode(node.tag))
|
|
6417
|
+
subtreeIds.add(node.id);
|
|
6418
|
+
}
|
|
6419
|
+
}
|
|
6420
|
+
let changed = true;
|
|
6421
|
+
while (changed) {
|
|
6422
|
+
changed = false;
|
|
6423
|
+
for (const e of allDomEvents) {
|
|
6424
|
+
const data = e.data;
|
|
6425
|
+
for (const node of data ?? []) {
|
|
6426
|
+
if (!subtreeIds.has(node.id) && subtreeIds.has(node.parent)) {
|
|
6427
|
+
subtreeIds.add(node.id);
|
|
6428
|
+
changed = true;
|
|
6429
|
+
}
|
|
6430
|
+
}
|
|
6431
|
+
}
|
|
6432
|
+
}
|
|
6433
|
+
return subtreeIds;
|
|
6434
|
+
}
|
|
6435
|
+
function filterShadowNodes(data, subtreeIds, shadowHostTags) {
|
|
6436
|
+
return (data?.filter((node) => {
|
|
6437
|
+
if (isShadowDomNode(node.tag))
|
|
6438
|
+
return true;
|
|
6439
|
+
if (shadowHostTags.has(node.tag ?? '') && subtreeIds.has(node.parent))
|
|
6440
|
+
return true;
|
|
6441
|
+
return subtreeIds.has(node.id);
|
|
6442
|
+
}) ?? []);
|
|
6443
|
+
}
|
|
6444
|
+
/** Extract shadow DOM nodes from merged.dom (initial Discover event, processed by setup()).
|
|
6445
|
+
* Returns a filtered copy of the dom event, or null if no shadow DOM present. */
|
|
6446
|
+
function extractSpecialDom(dom, events, shadowHostTags) {
|
|
6447
|
+
const mutationEvents = events.filter((e) => e.event === Event.Mutation);
|
|
6448
|
+
const subtreeIds = buildShadowSubtreeIds([dom, ...mutationEvents]);
|
|
6449
|
+
const shadowNodes = filterShadowNodes(dom.data, subtreeIds, shadowHostTags);
|
|
6450
|
+
return shadowNodes.length ? { ...dom, data: shadowNodes } : null;
|
|
6451
|
+
}
|
|
6452
|
+
/** Extract shadow DOM mutations + StyleSheet + CustomElement events from merged.events. */
|
|
6453
|
+
function extractSpecialEvents(events, dom, shadowHostTags) {
|
|
6454
|
+
const mutationEvents = events.filter((e) => e.event === Event.Mutation);
|
|
6455
|
+
const subtreeIds = buildShadowSubtreeIds([dom, ...mutationEvents]);
|
|
6456
|
+
const result = [];
|
|
6457
|
+
for (const e of events) {
|
|
6458
|
+
const ev = e.event;
|
|
6459
|
+
if (ev === Event.StyleSheetAdoption ||
|
|
6460
|
+
ev === Event.StyleSheetUpdate ||
|
|
6461
|
+
ev === Event.CustomElement) {
|
|
6462
|
+
result.push(e);
|
|
6463
|
+
continue;
|
|
6464
|
+
}
|
|
6465
|
+
if (ev === Event.Mutation) {
|
|
6466
|
+
const shadowNodes = filterShadowNodes(e.data, subtreeIds, shadowHostTags);
|
|
6467
|
+
if (shadowNodes.length)
|
|
6468
|
+
result.push({ ...e, data: shadowNodes });
|
|
6469
|
+
}
|
|
6470
|
+
}
|
|
6471
|
+
return result;
|
|
6472
|
+
}
|
|
6473
|
+
|
|
6474
|
+
const YIELD_INTERVAL_MS = 16;
|
|
6475
|
+
async function yieldToMain() {
|
|
6476
|
+
if ('scheduler' in globalThis && typeof globalThis.scheduler?.yield === 'function') {
|
|
6477
|
+
await globalThis.scheduler.yield();
|
|
6478
|
+
}
|
|
6479
|
+
else {
|
|
6480
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
6481
|
+
}
|
|
6482
|
+
}
|
|
6112
6483
|
class GXVisualizer extends Visualizer {
|
|
6113
6484
|
attentionMap;
|
|
6114
6485
|
originalClearmap;
|
|
@@ -6120,6 +6491,7 @@ class GXVisualizer extends Visualizer {
|
|
|
6120
6491
|
this.originalClearmap = this.clearmap;
|
|
6121
6492
|
this.clearmap = this.clearmapOverride;
|
|
6122
6493
|
this.setup = this.setupOverride;
|
|
6494
|
+
this.html = this.htmlOverride;
|
|
6123
6495
|
}
|
|
6124
6496
|
setupOverride = async (target, options) => {
|
|
6125
6497
|
this.attentionMap?.clear();
|
|
@@ -6131,6 +6503,99 @@ class GXVisualizer extends Visualizer {
|
|
|
6131
6503
|
this.originalClearmap();
|
|
6132
6504
|
this.attentionMap?.clear();
|
|
6133
6505
|
};
|
|
6506
|
+
renderLoop = async (v, events, hash, useproxy, shortCircuitStrategy) => {
|
|
6507
|
+
let lastYield = performance.now();
|
|
6508
|
+
for (let i = 0; i < events.length; i++) {
|
|
6509
|
+
const now = performance.now();
|
|
6510
|
+
if (now - lastYield > YIELD_INTERVAL_MS) {
|
|
6511
|
+
await yieldToMain();
|
|
6512
|
+
lastYield = performance.now();
|
|
6513
|
+
}
|
|
6514
|
+
const entry = events[i];
|
|
6515
|
+
const entryEvent = entry.event;
|
|
6516
|
+
switch (entryEvent) {
|
|
6517
|
+
case Event.StyleSheetAdoption:
|
|
6518
|
+
case Event.StyleSheetUpdate:
|
|
6519
|
+
v.layout.styleChange(entry);
|
|
6520
|
+
break;
|
|
6521
|
+
case Event.CustomElement:
|
|
6522
|
+
v.layout.customElement(entry);
|
|
6523
|
+
break;
|
|
6524
|
+
case Event.Mutation: {
|
|
6525
|
+
const domEvent = entry;
|
|
6526
|
+
this.renderTime = domEvent.time;
|
|
6527
|
+
if (v.shortCircuitRendering(shortCircuitStrategy, domEvent, hash))
|
|
6528
|
+
return;
|
|
6529
|
+
v.layout.markup(domEvent, useproxy);
|
|
6530
|
+
break;
|
|
6531
|
+
}
|
|
6532
|
+
}
|
|
6533
|
+
}
|
|
6534
|
+
};
|
|
6535
|
+
htmlOverride = async (decoded, target, portalCanvasId, hash = '', useproxy, logerror, shortCircuitStrategy = ShortCircuitStrategy.None) => {
|
|
6536
|
+
if (decoded && decoded.length > 0 && target) {
|
|
6537
|
+
try {
|
|
6538
|
+
const v = this;
|
|
6539
|
+
const merged = v.mergeForHtml(decoded);
|
|
6540
|
+
await this.setup(target, { version: decoded[0].envelope.version, dom: merged.dom, useproxy, portalCanvasId });
|
|
6541
|
+
await this.renderLoop(v, merged.events, hash, useproxy, shortCircuitStrategy);
|
|
6542
|
+
}
|
|
6543
|
+
catch (e) {
|
|
6544
|
+
if (logerror)
|
|
6545
|
+
logerror(e);
|
|
6546
|
+
}
|
|
6547
|
+
}
|
|
6548
|
+
return this;
|
|
6549
|
+
};
|
|
6550
|
+
htmlCached = async (cacheKey, decoded, target, portalCanvasId, hash = '', useproxy, logerror, shortCircuitStrategy = 0) => {
|
|
6551
|
+
if (!decoded || decoded.length === 0 || !target)
|
|
6552
|
+
return this;
|
|
6553
|
+
const fullKey = buildCacheKey(cacheKey, 0);
|
|
6554
|
+
const cached = await htmlCache.get(fullKey);
|
|
6555
|
+
if (cached) {
|
|
6556
|
+
try {
|
|
6557
|
+
const v = this;
|
|
6558
|
+
await this.setup(target, { version: cached.version, useproxy, portalCanvasId });
|
|
6559
|
+
target.document.open();
|
|
6560
|
+
target.document.write(cached.html);
|
|
6561
|
+
target.document.close();
|
|
6562
|
+
v.layout.hydrate(target.document);
|
|
6563
|
+
// Replay shadow DOM from initial Discover event (was processed by setup() in full render)
|
|
6564
|
+
if (cached.specialDom) {
|
|
6565
|
+
v.layout.markup(cached.specialDom, useproxy);
|
|
6566
|
+
}
|
|
6567
|
+
// Replay shadow DOM mutations + StyleSheet + CustomElement
|
|
6568
|
+
await this.renderLoop(v, cached.specialEvents, '', useproxy, 0);
|
|
6569
|
+
return this;
|
|
6570
|
+
}
|
|
6571
|
+
catch (e) {
|
|
6572
|
+
if (logerror)
|
|
6573
|
+
logerror(e);
|
|
6574
|
+
}
|
|
6575
|
+
}
|
|
6576
|
+
try {
|
|
6577
|
+
const v = this;
|
|
6578
|
+
const merged = v.mergeForHtml(decoded);
|
|
6579
|
+
await this.setup(target, { version: decoded[0].envelope.version, dom: merged.dom, useproxy, portalCanvasId });
|
|
6580
|
+
await this.renderLoop(v, merged.events, hash, useproxy, shortCircuitStrategy);
|
|
6581
|
+
const shadowHostTags = collectShadowHostTags(target.document);
|
|
6582
|
+
const specialDom = extractSpecialDom(merged.dom, merged.events, shadowHostTags);
|
|
6583
|
+
const specialEvents = extractSpecialEvents(merged.events, merged.dom, shadowHostTags);
|
|
6584
|
+
void htmlCache.set({
|
|
6585
|
+
key: fullKey,
|
|
6586
|
+
html: target.document.documentElement.outerHTML,
|
|
6587
|
+
specialDom: specialDom,
|
|
6588
|
+
specialEvents,
|
|
6589
|
+
version: decoded[0].envelope.version,
|
|
6590
|
+
timestamp: Date.now(),
|
|
6591
|
+
});
|
|
6592
|
+
}
|
|
6593
|
+
catch (e) {
|
|
6594
|
+
if (logerror)
|
|
6595
|
+
logerror(e);
|
|
6596
|
+
}
|
|
6597
|
+
return this;
|
|
6598
|
+
};
|
|
6134
6599
|
/**
|
|
6135
6600
|
* Render attention/engagement map.
|
|
6136
6601
|
* @param attentionData - Array of attention data points with start/end element hashes and time spent
|
|
@@ -6143,93 +6608,72 @@ class GXVisualizer extends Visualizer {
|
|
|
6143
6608
|
};
|
|
6144
6609
|
}
|
|
6145
6610
|
|
|
6146
|
-
const perf = createPerfTimer('Render');
|
|
6147
|
-
const
|
|
6148
|
-
const viewId = useViewIdContext();
|
|
6149
|
-
const data = useHeatmapDataContext((s) => s.data);
|
|
6611
|
+
const perf$1 = createPerfTimer('Render');
|
|
6612
|
+
const useHeatmapIframeProcessor = () => {
|
|
6150
6613
|
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
6614
|
const deviceType = useHeatmapSettingContext((s) => s.deviceType);
|
|
6159
|
-
const
|
|
6615
|
+
const viewport = useHeatmapViewportByDevice();
|
|
6616
|
+
const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
|
|
6617
|
+
const setIsDomLoaded = useHeatmapVizContext((s) => s.setIsDomLoaded);
|
|
6160
6618
|
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;
|
|
6619
|
+
const pendingRef = useRef(null);
|
|
6620
|
+
const reset = useCallback(() => {
|
|
6621
|
+
pendingRef.current = null;
|
|
6622
|
+
}, []);
|
|
6623
|
+
const run = useCallback((iframe, t0, abort) => {
|
|
6624
|
+
if (viewport.width === 0 || viewport.height === 0) {
|
|
6625
|
+
pendingRef.current = { iframe, t0, abort };
|
|
6170
6626
|
return;
|
|
6171
6627
|
}
|
|
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
6628
|
startIframe({
|
|
6192
6629
|
helperRef,
|
|
6193
6630
|
iframe,
|
|
6194
6631
|
shopId,
|
|
6195
6632
|
deviceType,
|
|
6196
|
-
size,
|
|
6633
|
+
size: viewport,
|
|
6197
6634
|
t0,
|
|
6198
6635
|
onSuccess: (height) => {
|
|
6199
6636
|
if (abort.signal.aborted)
|
|
6200
6637
|
return;
|
|
6201
6638
|
if (height)
|
|
6202
6639
|
setIframeHeight(height);
|
|
6203
|
-
|
|
6640
|
+
setIsDomLoaded(true);
|
|
6204
6641
|
},
|
|
6205
6642
|
});
|
|
6206
6643
|
}, [deviceType]);
|
|
6644
|
+
// Retry when dims become available
|
|
6207
6645
|
useEffect(() => {
|
|
6208
|
-
if (
|
|
6646
|
+
if (viewport.width === 0 || viewport.height === 0)
|
|
6209
6647
|
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)
|
|
6648
|
+
if (!pendingRef.current)
|
|
6217
6649
|
return;
|
|
6218
|
-
|
|
6650
|
+
const { iframe, t0, abort } = pendingRef.current;
|
|
6651
|
+
pendingRef.current = null;
|
|
6652
|
+
if (abort.signal.aborted)
|
|
6219
6653
|
return;
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6654
|
+
startIframe({
|
|
6655
|
+
helperRef,
|
|
6656
|
+
iframe,
|
|
6657
|
+
shopId,
|
|
6658
|
+
deviceType,
|
|
6659
|
+
size: viewport,
|
|
6660
|
+
t0,
|
|
6661
|
+
onSuccess: (height) => {
|
|
6662
|
+
if (abort.signal.aborted)
|
|
6663
|
+
return;
|
|
6664
|
+
if (height)
|
|
6665
|
+
setIframeHeight(height);
|
|
6666
|
+
setIsDomLoaded(true);
|
|
6667
|
+
},
|
|
6668
|
+
});
|
|
6669
|
+
}, [viewport]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
6224
6670
|
useEffect(() => {
|
|
6225
6671
|
return () => {
|
|
6226
|
-
setVizRef(null);
|
|
6227
|
-
abortRef.current?.abort();
|
|
6228
6672
|
helperRef.current?.stop();
|
|
6229
6673
|
helperRef.current = null;
|
|
6230
6674
|
};
|
|
6231
|
-
}, [
|
|
6232
|
-
return {
|
|
6675
|
+
}, []);
|
|
6676
|
+
return { run, reset };
|
|
6233
6677
|
};
|
|
6234
6678
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
6235
6679
|
function startIframe({ helperRef, iframe, shopId, deviceType = EDeviceType.Desktop, size, t0, onSuccess, }) {
|
|
@@ -6238,7 +6682,7 @@ function startIframe({ helperRef, iframe, shopId, deviceType = EDeviceType.Deskt
|
|
|
6238
6682
|
if (docHeight === 0)
|
|
6239
6683
|
return;
|
|
6240
6684
|
helperRef.current?.stop();
|
|
6241
|
-
const tHelper = perf.mark('IframeHelper.start');
|
|
6685
|
+
const tHelper = perf$1.mark('IframeHelper.start');
|
|
6242
6686
|
const helper = createIframeHelper();
|
|
6243
6687
|
helperRef.current = helper;
|
|
6244
6688
|
helper.start({
|
|
@@ -6249,17 +6693,81 @@ function startIframe({ helperRef, iframe, shopId, deviceType = EDeviceType.Deskt
|
|
|
6249
6693
|
debug: true,
|
|
6250
6694
|
shopId,
|
|
6251
6695
|
onSuccess: (data) => {
|
|
6252
|
-
perf.measure('IframeHelper processing', tHelper);
|
|
6253
|
-
perf.measure('Total render', t0);
|
|
6696
|
+
perf$1.measure('IframeHelper processing', tHelper);
|
|
6697
|
+
perf$1.measure('Total render', t0);
|
|
6254
6698
|
iframe.style.height = `${data.height}px`;
|
|
6255
6699
|
onSuccess(data.height);
|
|
6256
6700
|
},
|
|
6257
6701
|
});
|
|
6258
6702
|
}
|
|
6259
6703
|
|
|
6704
|
+
const EShortCircuitStrategy = {
|
|
6705
|
+
None: 0,
|
|
6706
|
+
HashFirstTimestamp: 1,
|
|
6707
|
+
HashFirstTimestampPlusBuffer: 2,
|
|
6708
|
+
HashBeforeDeleted: 3,
|
|
6709
|
+
};
|
|
6710
|
+
const perf = createPerfTimer('Render');
|
|
6711
|
+
const useHeatmapRenderDom = () => {
|
|
6712
|
+
const viewId = useViewIdContext();
|
|
6713
|
+
const data = useHeatmapDataContext((s) => s.data);
|
|
6714
|
+
const excludeClassNames = useHeatmapConfigStore((s) => s.excludeClassNames);
|
|
6715
|
+
const setVizRef = useHeatmapVizRectContext((s) => s.setVizRef);
|
|
6716
|
+
const vizRef = useHeatmapVizRectContext((s) => s.vizRef);
|
|
6717
|
+
const setIsDomLoaded = useHeatmapVizContext((s) => s.setIsDomLoaded);
|
|
6718
|
+
const deviceType = useHeatmapSettingContext((s) => s.deviceType);
|
|
6719
|
+
const heatmapType = useHeatmapSettingContext((s) => s.heatmapType);
|
|
6720
|
+
const elementToShow = useHeatmapDataContext((s) => s.dataInfo?.elementToShow);
|
|
6721
|
+
const dataHash = useHeatmapDataContext((s) => s.dataHash);
|
|
6722
|
+
const iframeRef = useRef(null);
|
|
6723
|
+
const abortRef = useRef(null);
|
|
6724
|
+
const elementToShowRef = useRef(null);
|
|
6725
|
+
const dataHashRef = useRef(null);
|
|
6726
|
+
const heatmapTypeRef = useRef(heatmapType);
|
|
6727
|
+
elementToShowRef.current = elementToShow ?? null;
|
|
6728
|
+
dataHashRef.current = dataHash ?? null;
|
|
6729
|
+
heatmapTypeRef.current = heatmapType;
|
|
6730
|
+
const { run: runIframeSetup, reset: resetIframeSetup } = useHeatmapIframeProcessor();
|
|
6731
|
+
const renderHeatmap = useCallback(async (payloads) => {
|
|
6732
|
+
if (!payloads || payloads.length === 0)
|
|
6733
|
+
return;
|
|
6734
|
+
const iframe = iframeRef.current;
|
|
6735
|
+
const contentWindow = iframe?.contentWindow;
|
|
6736
|
+
if (!contentWindow)
|
|
6737
|
+
return;
|
|
6738
|
+
abortRef.current?.abort();
|
|
6739
|
+
const abort = new AbortController();
|
|
6740
|
+
abortRef.current = abort;
|
|
6741
|
+
resetIframeSetup();
|
|
6742
|
+
const t0 = perf.mark('renderHeatmap start');
|
|
6743
|
+
const visualizer = vizRef ?? new GXVisualizer();
|
|
6744
|
+
if (!vizRef)
|
|
6745
|
+
setVizRef(visualizer);
|
|
6746
|
+
visualizer.configure({ excludeClassNames });
|
|
6747
|
+
setIsDomLoaded(false);
|
|
6748
|
+
// Phase 1: render DOM — does not depend on contentWidth/wrapperHeight
|
|
6749
|
+
const hash = elementToShowRef.current ?? undefined;
|
|
6750
|
+
const cacheKey = dataHashRef.current;
|
|
6751
|
+
const strategy = hash ? EShortCircuitStrategy.HashFirstTimestampPlusBuffer : EShortCircuitStrategy.None;
|
|
6752
|
+
await perf.wrap('visualizer.html', () => cacheKey
|
|
6753
|
+
? visualizer.htmlCached(cacheKey, payloads, contentWindow, viewId, hash, undefined, undefined, strategy)
|
|
6754
|
+
: visualizer.html(payloads, contentWindow, viewId, hash, undefined, undefined, strategy));
|
|
6755
|
+
if (abort.signal.aborted)
|
|
6756
|
+
return;
|
|
6757
|
+
// Phase 2: iframe setup — deferred to useIframeSetup (handles dims dependency)
|
|
6758
|
+
runIframeSetup(iframe, t0, abort);
|
|
6759
|
+
}, [deviceType]);
|
|
6760
|
+
useEffect(() => {
|
|
6761
|
+
if (!data || data.length === 0)
|
|
6762
|
+
return;
|
|
6763
|
+
renderHeatmap(decodeArrayClarity(data));
|
|
6764
|
+
}, [data, renderHeatmap]);
|
|
6765
|
+
return { iframeRef };
|
|
6766
|
+
};
|
|
6767
|
+
|
|
6260
6768
|
const useReplayRender = () => {
|
|
6261
6769
|
const data = useHeatmapDataContext((s) => s.data);
|
|
6262
|
-
const
|
|
6770
|
+
const setIsDomLoaded = useHeatmapVizContext((s) => s.setIsDomLoaded);
|
|
6263
6771
|
const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
|
|
6264
6772
|
const visualizerRef = useRef(null);
|
|
6265
6773
|
const iframeRef = useRef(null);
|
|
@@ -6279,7 +6787,7 @@ const useReplayRender = () => {
|
|
|
6279
6787
|
version: envelope.version,
|
|
6280
6788
|
onresize: (height) => {
|
|
6281
6789
|
height && setIframeHeight(height);
|
|
6282
|
-
|
|
6790
|
+
setIsDomLoaded(true);
|
|
6283
6791
|
},
|
|
6284
6792
|
mobile,
|
|
6285
6793
|
vNext: true,
|
|
@@ -6382,10 +6890,12 @@ const useReplayRender = () => {
|
|
|
6382
6890
|
const useHeatmapRenderByMode = (mode) => {
|
|
6383
6891
|
const heatmapResult = useMemo(() => {
|
|
6384
6892
|
switch (mode) {
|
|
6385
|
-
case
|
|
6386
|
-
return
|
|
6387
|
-
case
|
|
6893
|
+
case EHeatmapMode.Heatmap:
|
|
6894
|
+
return useHeatmapRenderDom;
|
|
6895
|
+
case EHeatmapMode.Replay:
|
|
6388
6896
|
return useReplayRender;
|
|
6897
|
+
default:
|
|
6898
|
+
return useHeatmapRenderDom;
|
|
6389
6899
|
}
|
|
6390
6900
|
}, [mode]);
|
|
6391
6901
|
return heatmapResult();
|
|
@@ -6420,22 +6930,10 @@ const useContainerDimensions = (props) => {
|
|
|
6420
6930
|
return { containerWidth, containerHeight };
|
|
6421
6931
|
};
|
|
6422
6932
|
|
|
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
6933
|
const useObserveIframeHeight = (props) => {
|
|
6436
6934
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
6437
6935
|
const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
|
|
6438
|
-
const
|
|
6936
|
+
const isDomLoaded = useHeatmapVizContext((s) => s.isDomLoaded);
|
|
6439
6937
|
const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
|
|
6440
6938
|
const { iframeRef } = props;
|
|
6441
6939
|
const resizeObserverRef = useRef(null);
|
|
@@ -6496,7 +6994,7 @@ const useObserveIframeHeight = (props) => {
|
|
|
6496
6994
|
}, [updateIframeHeight]);
|
|
6497
6995
|
useEffect(() => {
|
|
6498
6996
|
const iframe = iframeRef.current;
|
|
6499
|
-
if (!iframe || !iframeHeight || !
|
|
6997
|
+
if (!iframe || !iframeHeight || !isDomLoaded)
|
|
6500
6998
|
return;
|
|
6501
6999
|
const setupObservers = () => {
|
|
6502
7000
|
try {
|
|
@@ -6558,7 +7056,7 @@ const useObserveIframeHeight = (props) => {
|
|
|
6558
7056
|
}
|
|
6559
7057
|
iframe.removeEventListener('load', setupObservers);
|
|
6560
7058
|
};
|
|
6561
|
-
}, [iframeRef, iframeHeight,
|
|
7059
|
+
}, [iframeRef, iframeHeight, isDomLoaded]);
|
|
6562
7060
|
return {};
|
|
6563
7061
|
};
|
|
6564
7062
|
|
|
@@ -6571,9 +7069,10 @@ const useScaleCalculation = (props) => {
|
|
|
6571
7069
|
const setScale = useHeatmapVizContext((s) => s.setScale);
|
|
6572
7070
|
const setIsScaledToFit = useHeatmapVizContext((s) => s.setIsScaledToFit);
|
|
6573
7071
|
const setMinZoomRatio = useHeatmapVizContext((s) => s.setMinZoomRatio);
|
|
6574
|
-
const
|
|
7072
|
+
const viewport = useHeatmapViewportByDevice();
|
|
7073
|
+
const { containerWidth, containerHeight, iframeHeight } = props;
|
|
6575
7074
|
const calculateScaleResult = useCallback(() => {
|
|
6576
|
-
if (containerWidth > 0 &&
|
|
7075
|
+
if (containerWidth > 0 && viewport.width > 0 && containerHeight > 0 && iframeHeight > 0) {
|
|
6577
7076
|
// 1. Calculate available dimensions
|
|
6578
7077
|
const availableWidth = containerWidth - HEATMAP_CONFIG['padding'] * 2;
|
|
6579
7078
|
const toolbarHeight = HEATMAP_CONFIG['heightToolbar'] || 0;
|
|
@@ -6581,12 +7080,12 @@ const useScaleCalculation = (props) => {
|
|
|
6581
7080
|
const availableHeight = containerHeight - toolbarHeight - paddingTotal;
|
|
6582
7081
|
// 2. Calculate widthScale (base scale to fit content width into container width)
|
|
6583
7082
|
// This represents 100% zoom (fit to width)
|
|
6584
|
-
const widthScale = Math.min(availableWidth /
|
|
7083
|
+
const widthScale = Math.min(availableWidth / viewport.width, 1);
|
|
6585
7084
|
// 3. Calculate minZoomRatio (zoom ratio to fit height)
|
|
6586
7085
|
// At minZoomRatio, the content should fit entirely within the container height
|
|
6587
|
-
// Formula:
|
|
6588
|
-
// => minZoomRatio = (availableHeight / (
|
|
6589
|
-
const calculatedMinZoomRatio = (availableHeight / (
|
|
7086
|
+
// Formula: iframeHeight * widthScale * (minZoomRatio / 100) = availableHeight
|
|
7087
|
+
// => minZoomRatio = (availableHeight / (iframeHeight * widthScale)) * 100
|
|
7088
|
+
const calculatedMinZoomRatio = (availableHeight / (iframeHeight * widthScale)) * 100;
|
|
6590
7089
|
// Limit minZoomRatio: cannot exceed MAX_ZOOM_RATIO (100%)
|
|
6591
7090
|
// and should have a reasonable minimum (e.g., 1%)
|
|
6592
7091
|
const finalMinZoomRatio = Math.max(1, Math.min(calculatedMinZoomRatio, maxZoomRatio));
|
|
@@ -6605,7 +7104,7 @@ const useScaleCalculation = (props) => {
|
|
|
6605
7104
|
setIsScaledToFit(isCurrentlyFitted);
|
|
6606
7105
|
setMinZoomRatio(finalMinZoomRatio);
|
|
6607
7106
|
}
|
|
6608
|
-
}, [containerWidth, containerHeight,
|
|
7107
|
+
}, [containerWidth, containerHeight, viewport.width, iframeHeight, zoomRatio, maxZoomRatio]);
|
|
6609
7108
|
useEffect(() => {
|
|
6610
7109
|
calculateScaleResult();
|
|
6611
7110
|
}, [calculateScaleResult]);
|
|
@@ -6638,20 +7137,15 @@ const useHeatmapScale = (props) => {
|
|
|
6638
7137
|
// 1. Observe container dimensions
|
|
6639
7138
|
const { containerWidth, containerHeight } = useContainerDimensions({ wrapperRef });
|
|
6640
7139
|
// 2. Get content dimensions from config
|
|
6641
|
-
const
|
|
7140
|
+
const viewport = useHeatmapViewportByDevice();
|
|
6642
7141
|
// 3. Observe iframe height (now reacts to width changes)
|
|
6643
7142
|
useObserveIframeHeight({ iframeRef });
|
|
6644
7143
|
// 4. Calculate scale
|
|
6645
|
-
const { widthScale } = useScaleCalculation({
|
|
6646
|
-
containerWidth,
|
|
6647
|
-
containerHeight,
|
|
6648
|
-
contentWidth,
|
|
6649
|
-
contentHeight: iframeHeight,
|
|
6650
|
-
});
|
|
7144
|
+
const { widthScale } = useScaleCalculation({ containerWidth, containerHeight, iframeHeight });
|
|
6651
7145
|
// 5. Setup scroll sync
|
|
6652
7146
|
const { handleScroll } = useScrollSync({ widthScale, iframeRef });
|
|
6653
7147
|
const scaledHeight = iframeHeight * widthScale;
|
|
6654
|
-
const scaledWidth =
|
|
7148
|
+
const scaledWidth = viewport.width * widthScale;
|
|
6655
7149
|
return {
|
|
6656
7150
|
scaledWidth,
|
|
6657
7151
|
scaledHeight,
|
|
@@ -7690,11 +8184,11 @@ const AutoScrollHandler = ({ visualRef }) => {
|
|
|
7690
8184
|
};
|
|
7691
8185
|
|
|
7692
8186
|
const PortalAreaRenderer = ({ iframeRef, visualRef, shadowRoot, onAreaCreated, onAreaClick, }) => {
|
|
7693
|
-
const
|
|
8187
|
+
const isDomLoaded = useHeatmapVizContext((s) => s.isDomLoaded);
|
|
7694
8188
|
const iframeDocument = iframeRef.current?.contentDocument || undefined;
|
|
7695
8189
|
const { shadowContainer, isReady } = useAreaRendererContainer(iframeDocument, shadowRoot);
|
|
7696
|
-
useAreaRectSync({ iframeDocument, shadowRoot, enabled: isReady &&
|
|
7697
|
-
useAreaPositionsUpdater({ iframeRef, visualRef, enabled: isReady &&
|
|
8190
|
+
useAreaRectSync({ iframeDocument, shadowRoot, enabled: isReady && isDomLoaded });
|
|
8191
|
+
useAreaPositionsUpdater({ iframeRef, visualRef, enabled: isReady && isDomLoaded });
|
|
7698
8192
|
if (!shadowContainer || !isReady)
|
|
7699
8193
|
return null;
|
|
7700
8194
|
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 +8197,7 @@ const PortalAreaRenderer = ({ iframeRef, visualRef, shadowRoot, onAreaCreated, o
|
|
|
7703
8197
|
const VizAreaClick = ({ iframeRef, visualRef, shadowRoot, autoCreateTopN = 10, enableOverlapResolution = true, onAreaClick, }) => {
|
|
7704
8198
|
const clickAreas = useHeatmapDataContext((s) => s.clickAreas);
|
|
7705
8199
|
const resetView = useHeatmapAreaClickContext((s) => s.resetView);
|
|
7706
|
-
const
|
|
8200
|
+
const isDomLoaded = useHeatmapVizContext((s) => s.isDomLoaded);
|
|
7707
8201
|
useAreaTopAutoDetect({ autoCreateTopN, shadowRoot, disabled: !!clickAreas?.length });
|
|
7708
8202
|
useAreaFilterVisible({ iframeRef, enableOverlapResolution });
|
|
7709
8203
|
useAreaHydration({ shadowRoot });
|
|
@@ -7712,7 +8206,7 @@ const VizAreaClick = ({ iframeRef, visualRef, shadowRoot, autoCreateTopN = 10, e
|
|
|
7712
8206
|
resetView();
|
|
7713
8207
|
};
|
|
7714
8208
|
}, []);
|
|
7715
|
-
if (!iframeRef.current || !
|
|
8209
|
+
if (!iframeRef.current || !isDomLoaded)
|
|
7716
8210
|
return null;
|
|
7717
8211
|
return (jsx(Fragment, { children: jsx(PortalAreaRenderer, { iframeRef: iframeRef, visualRef: visualRef, shadowRoot: shadowRoot, onAreaClick: onAreaClick }) }));
|
|
7718
8212
|
};
|
|
@@ -7843,7 +8337,7 @@ const useAnchorPosition = (calloutRef, props) => {
|
|
|
7843
8337
|
const ElementMissing = ({ show = true, visualRef }) => {
|
|
7844
8338
|
const widthScale = useHeatmapVizContext((s) => s.widthScale);
|
|
7845
8339
|
const missingElementRef = useRef(null);
|
|
7846
|
-
const
|
|
8340
|
+
const viewport = useHeatmapViewportByDevice();
|
|
7847
8341
|
const [scrollPosition, setScrollPosition] = useState({ scrollTop: 0, scrollLeft: 0 });
|
|
7848
8342
|
useEffect(() => {
|
|
7849
8343
|
const container = visualRef.current;
|
|
@@ -7873,7 +8367,7 @@ const ElementMissing = ({ show = true, visualRef }) => {
|
|
|
7873
8367
|
const containerHeight = containerRect?.height ?? 0;
|
|
7874
8368
|
const topPosition = scrollTop + (containerHeight + elementHeightCenter) / 2;
|
|
7875
8369
|
const topPositionScaled = topPosition / widthScale;
|
|
7876
|
-
const leftPosition =
|
|
8370
|
+
const leftPosition = viewport.width / 2;
|
|
7877
8371
|
return (jsxs(Fragment, { children: [jsx("div", { className: "missingElement-backdrop", style: {
|
|
7878
8372
|
position: 'absolute',
|
|
7879
8373
|
top: 0,
|
|
@@ -7998,7 +8492,7 @@ const ElementOverlayComponent = (props) => {
|
|
|
7998
8492
|
const { type, element, onClick, elementId, hideOutline } = props;
|
|
7999
8493
|
const widthScale = useHeatmapVizContext((s) => s.widthScale);
|
|
8000
8494
|
const viewportHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
8001
|
-
const
|
|
8495
|
+
const viewport = useHeatmapViewportByDevice();
|
|
8002
8496
|
const overlayStyle = useMemo(() => {
|
|
8003
8497
|
const isInvalid = !element || (element.width === 0 && element.height === 0);
|
|
8004
8498
|
if (isInvalid)
|
|
@@ -8015,7 +8509,7 @@ const ElementOverlayComponent = (props) => {
|
|
|
8015
8509
|
const isHovered = type === 'hovered';
|
|
8016
8510
|
const badgeWidthScale = isHovered ? 1 : widthScale;
|
|
8017
8511
|
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:
|
|
8512
|
+
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
8513
|
};
|
|
8020
8514
|
ElementOverlayComponent.displayName = 'ElementOverlay';
|
|
8021
8515
|
const ElementOverlay = memo(ElementOverlayComponent);
|
|
@@ -8080,7 +8574,7 @@ const HeatmapElements = (props) => {
|
|
|
8080
8574
|
};
|
|
8081
8575
|
|
|
8082
8576
|
const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
|
|
8083
|
-
const
|
|
8577
|
+
const viewport = useHeatmapViewportByDevice();
|
|
8084
8578
|
const dataInfo = useHeatmapDataContext((s) => s.dataInfo);
|
|
8085
8579
|
const vizRef = useHeatmapVizRectContext((s) => s.vizRef);
|
|
8086
8580
|
const visualizer = {
|
|
@@ -8094,7 +8588,7 @@ const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
|
|
|
8094
8588
|
if (!iframeRef.current)
|
|
8095
8589
|
return null;
|
|
8096
8590
|
return (jsx(HeatmapElements, { visualizer: visualizer, visualRef: visualRef, iframeRef: iframeRef, wrapperRef: wrapperRef, heatmapInfo: dataInfo, isVisible: true, positionMode: DEFAULT_POSITION_MODE, isHideTopRank: true, iframeDimensions: {
|
|
8097
|
-
width:
|
|
8591
|
+
width: viewport.width,
|
|
8098
8592
|
position: 'absolute',
|
|
8099
8593
|
top: 0,
|
|
8100
8594
|
left: 0,
|
|
@@ -8358,7 +8852,7 @@ const VizLoadingCanvas = () => {
|
|
|
8358
8852
|
const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHeight, onScroll, }) => {
|
|
8359
8853
|
const isLoadingCanvas = useHeatmapSettingContext((state) => state.isLoadingCanvas);
|
|
8360
8854
|
const widthScale = useHeatmapVizContext((s) => s.widthScale);
|
|
8361
|
-
const
|
|
8855
|
+
const viewport = useHeatmapViewportByDevice();
|
|
8362
8856
|
const contentHeight = calcContentHeight();
|
|
8363
8857
|
return (jsx("div", { ref: visualRef, className: "gx-hm-visual Polaris-Scrollable Polaris-Scrollable--vertical Polaris-Scrollable--scrollbarWidthThin Polaris-Scrollable--scrollbarGutterStable", onScroll: onScroll, style: {
|
|
8364
8858
|
overflowX: 'hidden',
|
|
@@ -8380,7 +8874,7 @@ const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHe
|
|
|
8380
8874
|
paddingBottom: HEATMAP_STYLE['viz']['paddingBottom'],
|
|
8381
8875
|
background: HEATMAP_STYLE['viz']['background'],
|
|
8382
8876
|
}, children: jsx("div", { className: "gx-hm-wrapper", ref: wrapperRef, style: {
|
|
8383
|
-
width:
|
|
8877
|
+
width: viewport.width,
|
|
8384
8878
|
height: iframeHeight,
|
|
8385
8879
|
transform: `scale(${widthScale})`,
|
|
8386
8880
|
transformOrigin: 'top center',
|
|
@@ -8393,14 +8887,14 @@ const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHe
|
|
|
8393
8887
|
}
|
|
8394
8888
|
};
|
|
8395
8889
|
|
|
8396
|
-
const VizDomRenderer = ({ mode
|
|
8890
|
+
const VizDomRenderer = ({ mode }) => {
|
|
8397
8891
|
const viewId = useViewIdContext();
|
|
8398
|
-
const
|
|
8892
|
+
const viewport = useHeatmapViewportByDevice();
|
|
8399
8893
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
8400
8894
|
const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
|
|
8401
8895
|
const wrapperRef = useRef(null);
|
|
8402
8896
|
const visualRef = useRef(null);
|
|
8403
|
-
const { iframeRef } =
|
|
8897
|
+
const { iframeRef } = useHeatmapRenderDom();
|
|
8404
8898
|
const { scaledHeight, handleScroll } = useHeatmapScale({ wrapperRef, iframeRef, visualRef });
|
|
8405
8899
|
useHeatmapCanvas();
|
|
8406
8900
|
useRenderCount('VizDomRenderer');
|
|
@@ -8408,7 +8902,7 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
|
|
|
8408
8902
|
const scrollTop = e.currentTarget.scrollTop;
|
|
8409
8903
|
handleScroll(scrollTop);
|
|
8410
8904
|
};
|
|
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:
|
|
8905
|
+
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
8906
|
};
|
|
8413
8907
|
|
|
8414
8908
|
const VizLoading = () => {
|
|
@@ -8425,8 +8919,9 @@ const VizLoading = () => {
|
|
|
8425
8919
|
const VizDomHeatmap = () => {
|
|
8426
8920
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
8427
8921
|
const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
|
|
8922
|
+
const setWrapperHeight = useHeatmapVizRectContext((s) => s.setWrapperHeight);
|
|
8428
8923
|
const setVizRef = useHeatmapVizRectContext((s) => s.setVizRef);
|
|
8429
|
-
const
|
|
8924
|
+
const setIsDomLoaded = useHeatmapVizContext((s) => s.setIsDomLoaded);
|
|
8430
8925
|
const setSelectedElement = useHeatmapClickContext((s) => s.setSelectedElement);
|
|
8431
8926
|
const setHoveredElement = useHeatmapHoverContext((s) => s.setHoveredElement);
|
|
8432
8927
|
// const setSelectedArea = useHeatmapAreaClickContext((s) => s.setSelectedArea);
|
|
@@ -8436,7 +8931,8 @@ const VizDomHeatmap = () => {
|
|
|
8436
8931
|
const cleanUp = () => {
|
|
8437
8932
|
setVizRef(null);
|
|
8438
8933
|
setIframeHeight(0);
|
|
8439
|
-
|
|
8934
|
+
setWrapperHeight(0);
|
|
8935
|
+
setIsDomLoaded(false);
|
|
8440
8936
|
setSelectedElement(null);
|
|
8441
8937
|
setHoveredElement(null);
|
|
8442
8938
|
// setSelectedArea(null);
|
|
@@ -8445,13 +8941,13 @@ const VizDomHeatmap = () => {
|
|
|
8445
8941
|
};
|
|
8446
8942
|
useEffect(() => {
|
|
8447
8943
|
return cleanUp;
|
|
8448
|
-
}, []);
|
|
8449
|
-
return (jsxs(VizContainer, { isActive: true, children: [jsx(VizDomRenderer, {}), iframeHeight === 0 && jsx(VizLoading, {})] }));
|
|
8944
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
8945
|
+
return (jsxs(VizContainer, { isActive: true, children: [jsx(VizDomRenderer, { mode: EHeatmapMode.Heatmap }), iframeHeight === 0 && jsx(VizLoading, {})] }));
|
|
8450
8946
|
};
|
|
8451
8947
|
VizDomHeatmap.displayName = 'VizDomHeatmap';
|
|
8452
8948
|
|
|
8453
8949
|
const VizLiveRenderer = () => {
|
|
8454
|
-
const
|
|
8950
|
+
const viewport = useHeatmapViewportByDevice();
|
|
8455
8951
|
const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
|
|
8456
8952
|
const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
|
|
8457
8953
|
const visualRef = useRef(null);
|
|
@@ -8462,7 +8958,7 @@ const VizLiveRenderer = () => {
|
|
|
8462
8958
|
const scrollTop = e.currentTarget.scrollTop;
|
|
8463
8959
|
handleScroll(scrollTop);
|
|
8464
8960
|
};
|
|
8465
|
-
return (jsx(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, iframeHeight: iframeHeight, onScroll: onScroll, children: jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width:
|
|
8961
|
+
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
8962
|
};
|
|
8467
8963
|
|
|
8468
8964
|
const VizLiveHeatmap = () => {
|
|
@@ -8553,4 +9049,4 @@ const HeatmapLayout = ({ shopId, data, clickmap, clickAreas, scrollmap, attentio
|
|
|
8553
9049
|
}
|
|
8554
9050
|
};
|
|
8555
9051
|
|
|
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,
|
|
9052
|
+
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 };
|