@gemx-dev/heatmap-react 3.5.46 → 3.5.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/Layout/HeatmapLayout.d.ts +3 -2
- package/dist/esm/components/Layout/HeatmapLayout.d.ts.map +1 -1
- package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/esm/components/VizElement/HeatmapElements.d.ts +2 -2
- package/dist/esm/components/VizElement/HeatmapElements.d.ts.map +1 -1
- package/dist/esm/components/VizElement/HeatmapExample.d.ts +2 -0
- package/dist/esm/components/VizElement/HeatmapExample.d.ts.map +1 -0
- package/dist/esm/components/VizElement/VizElements.d.ts.map +1 -1
- package/dist/esm/components/VizLive/VizLiveHeatmap.d.ts.map +1 -1
- package/dist/esm/components/VizLive/VizLiveRenderer.d.ts.map +1 -1
- package/dist/esm/components/VizScrollmap/AverageFoldLine.d.ts +8 -0
- package/dist/esm/components/VizScrollmap/AverageFoldLine.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/HoverZones.d.ts +10 -0
- package/dist/esm/components/VizScrollmap/HoverZones.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/MetricRow.d.ts +1 -0
- package/dist/esm/components/VizScrollmap/MetricRow.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollMapMinimap.d.ts +8 -0
- package/dist/esm/components/VizScrollmap/ScrollMapMinimap.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollMapOverlay.d.ts +7 -0
- package/dist/esm/components/VizScrollmap/ScrollMapOverlay.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollZoneHoverArea.d.ts +14 -0
- package/dist/esm/components/VizScrollmap/ScrollZoneHoverArea.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollZoneTooltip.d.ts +10 -0
- package/dist/esm/components/VizScrollmap/ScrollZoneTooltip.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/ScrollmapMarker.d.ts +7 -0
- package/dist/esm/components/VizScrollmap/ScrollmapMarker.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmap/VizScrollMap.d.ts +7 -0
- package/dist/esm/components/VizScrollmap/VizScrollMap.d.ts.map +1 -0
- package/{src/components/VizScrollmap/index.ts → dist/esm/components/VizScrollmap/index.d.ts} +1 -0
- package/dist/esm/components/VizScrollmap/index.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts +5 -0
- package/dist/esm/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts.map +1 -0
- package/{src/components/VizScrollmapV2/index.ts → dist/esm/components/VizScrollmapV2/index.d.ts} +1 -0
- package/dist/esm/components/VizScrollmapV2/index.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmapV2/scrollmap.types.d.ts +18 -0
- package/dist/esm/components/VizScrollmapV2/scrollmap.types.d.ts.map +1 -0
- package/dist/esm/components/VizScrollmapV2/useScrollmapOverlay.d.ts +16 -0
- package/dist/esm/components/VizScrollmapV2/useScrollmapOverlay.d.ts.map +1 -0
- package/dist/esm/configs/style.d.ts +2 -0
- package/dist/esm/configs/style.d.ts.map +1 -1
- package/dist/esm/helpers/elm-getter.d.ts +2 -2
- package/dist/esm/helpers/elm-getter.d.ts.map +1 -1
- package/dist/esm/helpers/iframe-helper/fixer.d.ts +18 -0
- package/dist/esm/helpers/iframe-helper/fixer.d.ts.map +1 -0
- package/dist/esm/helpers/iframe-helper/index.d.ts +2 -0
- package/dist/esm/helpers/iframe-helper/index.d.ts.map +1 -0
- package/dist/esm/helpers/iframe-helper/init.d.ts +5 -0
- package/dist/esm/helpers/iframe-helper/init.d.ts.map +1 -0
- package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts +28 -0
- package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +1 -0
- package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts +20 -0
- package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts.map +1 -0
- package/dist/esm/helpers/iframe-helper/style-replacer.d.ts +25 -0
- package/dist/esm/helpers/iframe-helper/style-replacer.d.ts.map +1 -0
- package/dist/esm/helpers/index.d.ts +2 -2
- package/dist/esm/helpers/index.d.ts.map +1 -1
- package/dist/esm/helpers/viz-canvas/area-clustering.d.ts +44 -0
- package/dist/esm/helpers/viz-canvas/area-clustering.d.ts.map +1 -0
- package/dist/esm/helpers/viz-canvas/area-overlay-manager-v2.d.ts +17 -0
- package/dist/esm/helpers/viz-canvas/area-overlay-manager-v2.d.ts.map +1 -0
- package/dist/esm/helpers/viz-canvas/area-overlay-manager.d.ts +51 -0
- package/dist/esm/helpers/viz-canvas/area-overlay-manager.d.ts.map +1 -0
- package/dist/esm/helpers/viz-canvas/hierarchical-area-clustering.d.ts +73 -0
- package/dist/esm/helpers/viz-canvas/hierarchical-area-clustering.d.ts.map +1 -0
- package/{src/helpers/viz-canvas/index.ts → dist/esm/helpers/viz-canvas/index.d.ts} +1 -0
- package/dist/esm/helpers/viz-canvas/index.d.ts.map +1 -0
- package/dist/esm/hooks/index.d.ts +2 -1
- package/dist/esm/hooks/index.d.ts.map +1 -1
- package/dist/esm/hooks/register/useRegisterData.d.ts +2 -2
- package/dist/esm/hooks/register/useRegisterData.d.ts.map +1 -1
- package/dist/esm/hooks/register/useRegisterHeatmap.d.ts +7 -2
- package/dist/esm/hooks/register/useRegisterHeatmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-area/useAreaHeatmap.d.ts +59 -0
- package/dist/esm/hooks/viz-area/useAreaHeatmap.d.ts.map +1 -0
- package/dist/esm/hooks/viz-area/useAreaHeatmapManager.d.ts +77 -0
- package/dist/esm/hooks/viz-area/useAreaHeatmapManager.d.ts.map +1 -0
- package/dist/esm/hooks/viz-canvas/index.d.ts +1 -1
- package/dist/esm/hooks/viz-canvas/index.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useAreamap.d.ts +14 -0
- package/dist/esm/hooks/viz-canvas/useAreamap.d.ts.map +1 -0
- package/dist/esm/hooks/viz-canvas/useClickmap.d.ts +3 -1
- package/dist/esm/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useHeatmapCanvas.d.ts +4 -0
- package/dist/esm/hooks/viz-canvas/useHeatmapCanvas.d.ts.map +1 -0
- package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts +3 -1
- package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/esm/hooks/{vix-elements → viz-elements}/index.d.ts.map +1 -1
- package/dist/esm/hooks/{vix-elements → viz-elements}/useClickedElement.d.ts.map +1 -1
- package/dist/esm/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts.map +1 -1
- package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts.map +1 -1
- package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts.map +1 -1
- package/dist/esm/hooks/viz-elements/useHeatmapMouseHandler.d.ts +34 -0
- package/dist/esm/hooks/viz-elements/useHeatmapMouseHandler.d.ts.map +1 -0
- package/dist/esm/hooks/{vix-elements → viz-elements}/useHoveredElement.d.ts +4 -0
- package/dist/esm/hooks/viz-elements/useHoveredElement.d.ts.map +1 -0
- package/dist/esm/hooks/viz-live/index.d.ts +1 -1
- package/dist/{umd/hooks/viz-live/useIframeMessage.d.ts → esm/hooks/viz-live/useVizLiveIframeMsg.d.ts} +2 -10
- package/dist/esm/hooks/viz-live/useVizLiveIframeMsg.d.ts.map +1 -0
- package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts +4 -0
- package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts.map +1 -0
- package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useContainerDimensions.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts +1 -1
- package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
- package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts +10 -0
- package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts.map +1 -0
- package/{src/hooks/viz-scrollmap/index.ts → dist/esm/hooks/viz-scrollmap/index.d.ts} +1 -0
- package/dist/esm/hooks/viz-scrollmap/index.d.ts.map +1 -0
- package/dist/esm/hooks/viz-scrollmap/useScrollmapZones.d.ts +29 -0
- package/dist/esm/hooks/viz-scrollmap/useScrollmapZones.d.ts.map +1 -0
- package/dist/esm/hooks/viz-scrollmap/useZonePositions.d.ts +12 -0
- package/dist/esm/hooks/viz-scrollmap/useZonePositions.d.ts.map +1 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1181 -210
- package/dist/esm/index.mjs +1181 -210
- package/dist/esm/stores/config.d.ts +5 -1
- package/dist/esm/stores/config.d.ts.map +1 -1
- package/dist/esm/stores/data.d.ts +5 -3
- package/dist/esm/stores/data.d.ts.map +1 -1
- package/dist/esm/stores/index.d.ts +2 -0
- package/dist/esm/stores/index.d.ts.map +1 -1
- package/dist/esm/stores/interaction.d.ts.map +1 -1
- package/dist/esm/stores/mode-live.d.ts +4 -0
- package/dist/esm/stores/mode-live.d.ts.map +1 -1
- package/dist/esm/stores/mode-single.d.ts +9 -0
- package/dist/esm/stores/mode-single.d.ts.map +1 -0
- package/dist/esm/stores/viz-scrollmap.d.ts +11 -0
- package/dist/esm/stores/viz-scrollmap.d.ts.map +1 -0
- package/dist/esm/stores/viz.d.ts +0 -4
- package/dist/esm/stores/viz.d.ts.map +1 -1
- package/dist/esm/types/clarity.d.ts +5 -0
- package/dist/esm/types/clarity.d.ts.map +1 -1
- package/dist/esm/types/heatmap-info.d.ts +11 -0
- package/dist/esm/types/heatmap-info.d.ts.map +1 -0
- package/dist/esm/types/heatmap.d.ts +13 -0
- package/dist/esm/types/heatmap.d.ts.map +1 -1
- package/dist/esm/types/iframe-helper.d.ts +20 -0
- package/dist/esm/types/iframe-helper.d.ts.map +1 -0
- package/dist/esm/types/index.d.ts +4 -1
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/types/viz-canvas.d.ts +23 -0
- package/dist/esm/types/viz-canvas.d.ts.map +1 -0
- package/dist/esm/types/viz-element.d.ts +0 -6
- package/dist/esm/types/viz-element.d.ts.map +1 -1
- package/dist/esm/types/viz-scrollmap.d.ts +27 -0
- package/dist/esm/types/viz-scrollmap.d.ts.map +1 -0
- package/dist/umd/components/Layout/HeatmapLayout.d.ts +3 -2
- package/dist/umd/components/Layout/HeatmapLayout.d.ts.map +1 -1
- package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/umd/components/VizElement/HeatmapElements.d.ts +2 -2
- package/dist/umd/components/VizElement/HeatmapElements.d.ts.map +1 -1
- package/dist/umd/components/VizElement/HeatmapExample.d.ts +2 -0
- package/dist/umd/components/VizElement/HeatmapExample.d.ts.map +1 -0
- package/dist/umd/components/VizElement/VizElements.d.ts.map +1 -1
- package/dist/umd/components/VizLive/VizLiveHeatmap.d.ts.map +1 -1
- package/dist/umd/components/VizLive/VizLiveRenderer.d.ts.map +1 -1
- package/dist/umd/components/VizScrollmap/AverageFoldLine.d.ts +8 -0
- package/dist/umd/components/VizScrollmap/AverageFoldLine.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/HoverZones.d.ts +10 -0
- package/dist/umd/components/VizScrollmap/HoverZones.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/MetricRow.d.ts +1 -0
- package/dist/umd/components/VizScrollmap/MetricRow.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollMapMinimap.d.ts +8 -0
- package/dist/umd/components/VizScrollmap/ScrollMapMinimap.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollMapOverlay.d.ts +7 -0
- package/dist/umd/components/VizScrollmap/ScrollMapOverlay.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollZoneHoverArea.d.ts +14 -0
- package/dist/umd/components/VizScrollmap/ScrollZoneHoverArea.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollZoneTooltip.d.ts +10 -0
- package/dist/umd/components/VizScrollmap/ScrollZoneTooltip.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/ScrollmapMarker.d.ts +7 -0
- package/dist/umd/components/VizScrollmap/ScrollmapMarker.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/VizScrollMap.d.ts +7 -0
- package/dist/umd/components/VizScrollmap/VizScrollMap.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmap/index.d.ts +2 -0
- package/dist/umd/components/VizScrollmap/index.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts +5 -0
- package/dist/umd/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmapV2/index.d.ts +2 -0
- package/dist/umd/components/VizScrollmapV2/index.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmapV2/scrollmap.types.d.ts +18 -0
- package/dist/umd/components/VizScrollmapV2/scrollmap.types.d.ts.map +1 -0
- package/dist/umd/components/VizScrollmapV2/useScrollmapOverlay.d.ts +16 -0
- package/dist/umd/components/VizScrollmapV2/useScrollmapOverlay.d.ts.map +1 -0
- package/dist/umd/configs/style.d.ts +2 -0
- package/dist/umd/configs/style.d.ts.map +1 -1
- package/dist/umd/helpers/elm-getter.d.ts +2 -2
- package/dist/umd/helpers/elm-getter.d.ts.map +1 -1
- package/dist/umd/helpers/iframe-helper/fixer.d.ts +18 -0
- package/dist/umd/helpers/iframe-helper/fixer.d.ts.map +1 -0
- package/dist/umd/helpers/iframe-helper/index.d.ts +2 -0
- package/dist/umd/helpers/iframe-helper/index.d.ts.map +1 -0
- package/dist/umd/helpers/iframe-helper/init.d.ts +5 -0
- package/dist/umd/helpers/iframe-helper/init.d.ts.map +1 -0
- package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts +28 -0
- package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +1 -0
- package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts +20 -0
- package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts.map +1 -0
- package/dist/umd/helpers/iframe-helper/style-replacer.d.ts +25 -0
- package/dist/umd/helpers/iframe-helper/style-replacer.d.ts.map +1 -0
- package/dist/umd/helpers/index.d.ts +2 -2
- package/dist/umd/helpers/index.d.ts.map +1 -1
- package/dist/umd/helpers/viz-canvas/area-clustering.d.ts +44 -0
- package/dist/umd/helpers/viz-canvas/area-clustering.d.ts.map +1 -0
- package/dist/umd/helpers/viz-canvas/area-overlay-manager-v2.d.ts +17 -0
- package/dist/umd/helpers/viz-canvas/area-overlay-manager-v2.d.ts.map +1 -0
- package/dist/umd/helpers/viz-canvas/area-overlay-manager.d.ts +51 -0
- package/dist/umd/helpers/viz-canvas/area-overlay-manager.d.ts.map +1 -0
- package/dist/umd/helpers/viz-canvas/hierarchical-area-clustering.d.ts +73 -0
- package/dist/umd/helpers/viz-canvas/hierarchical-area-clustering.d.ts.map +1 -0
- package/dist/umd/helpers/viz-canvas/index.d.ts +3 -0
- package/dist/umd/helpers/viz-canvas/index.d.ts.map +1 -0
- package/dist/umd/hooks/index.d.ts +2 -1
- package/dist/umd/hooks/index.d.ts.map +1 -1
- package/dist/umd/hooks/register/useRegisterData.d.ts +2 -2
- package/dist/umd/hooks/register/useRegisterData.d.ts.map +1 -1
- package/dist/umd/hooks/register/useRegisterHeatmap.d.ts +7 -2
- package/dist/umd/hooks/register/useRegisterHeatmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-area/useAreaHeatmap.d.ts +59 -0
- package/dist/umd/hooks/viz-area/useAreaHeatmap.d.ts.map +1 -0
- package/dist/umd/hooks/viz-area/useAreaHeatmapManager.d.ts +77 -0
- package/dist/umd/hooks/viz-area/useAreaHeatmapManager.d.ts.map +1 -0
- package/dist/umd/hooks/viz-canvas/index.d.ts +1 -1
- package/dist/umd/hooks/viz-canvas/index.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useAreamap.d.ts +14 -0
- package/dist/umd/hooks/viz-canvas/useAreamap.d.ts.map +1 -0
- package/dist/umd/hooks/viz-canvas/useClickmap.d.ts +3 -1
- package/dist/umd/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useHeatmapCanvas.d.ts +4 -0
- package/dist/umd/hooks/viz-canvas/useHeatmapCanvas.d.ts.map +1 -0
- package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts +3 -1
- package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/umd/hooks/{vix-elements → viz-elements}/index.d.ts.map +1 -1
- package/dist/umd/hooks/{vix-elements → viz-elements}/useClickedElement.d.ts.map +1 -1
- package/dist/umd/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts.map +1 -1
- package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts.map +1 -1
- package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts.map +1 -1
- package/dist/umd/hooks/viz-elements/useHeatmapMouseHandler.d.ts +34 -0
- package/dist/umd/hooks/viz-elements/useHeatmapMouseHandler.d.ts.map +1 -0
- package/dist/umd/hooks/{vix-elements → viz-elements}/useHoveredElement.d.ts +4 -0
- package/dist/umd/hooks/viz-elements/useHoveredElement.d.ts.map +1 -0
- package/dist/umd/hooks/viz-live/index.d.ts +1 -1
- package/dist/{esm/hooks/viz-live/useIframeMessage.d.ts → umd/hooks/viz-live/useVizLiveIframeMsg.d.ts} +2 -10
- package/dist/umd/hooks/viz-live/useVizLiveIframeMsg.d.ts.map +1 -0
- package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts +4 -0
- package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts.map +1 -0
- package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useContainerDimensions.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts +1 -1
- package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
- package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts +10 -0
- package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts.map +1 -0
- package/dist/umd/hooks/viz-scrollmap/index.d.ts +3 -0
- package/dist/umd/hooks/viz-scrollmap/index.d.ts.map +1 -0
- package/dist/umd/hooks/viz-scrollmap/useScrollmapZones.d.ts +29 -0
- package/dist/umd/hooks/viz-scrollmap/useScrollmapZones.d.ts.map +1 -0
- package/dist/umd/hooks/viz-scrollmap/useZonePositions.d.ts +12 -0
- package/dist/umd/hooks/viz-scrollmap/useZonePositions.d.ts.map +1 -0
- package/dist/umd/index.d.ts +1 -1
- package/dist/umd/index.d.ts.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/stores/config.d.ts +5 -1
- package/dist/umd/stores/config.d.ts.map +1 -1
- package/dist/umd/stores/data.d.ts +5 -3
- package/dist/umd/stores/data.d.ts.map +1 -1
- package/dist/umd/stores/index.d.ts +2 -0
- package/dist/umd/stores/index.d.ts.map +1 -1
- package/dist/umd/stores/interaction.d.ts.map +1 -1
- package/dist/umd/stores/mode-live.d.ts +4 -0
- package/dist/umd/stores/mode-live.d.ts.map +1 -1
- package/dist/umd/stores/mode-single.d.ts +9 -0
- package/dist/umd/stores/mode-single.d.ts.map +1 -0
- package/dist/umd/stores/viz-scrollmap.d.ts +11 -0
- package/dist/umd/stores/viz-scrollmap.d.ts.map +1 -0
- package/dist/umd/stores/viz.d.ts +0 -4
- package/dist/umd/stores/viz.d.ts.map +1 -1
- package/dist/umd/types/clarity.d.ts +5 -0
- package/dist/umd/types/clarity.d.ts.map +1 -1
- package/dist/umd/types/heatmap-info.d.ts +11 -0
- package/dist/umd/types/heatmap-info.d.ts.map +1 -0
- package/dist/umd/types/heatmap.d.ts +13 -0
- package/dist/umd/types/heatmap.d.ts.map +1 -1
- package/dist/umd/types/iframe-helper.d.ts +20 -0
- package/dist/umd/types/iframe-helper.d.ts.map +1 -0
- package/dist/umd/types/index.d.ts +4 -1
- package/dist/umd/types/index.d.ts.map +1 -1
- package/dist/umd/types/viz-canvas.d.ts +23 -0
- package/dist/umd/types/viz-canvas.d.ts.map +1 -0
- package/dist/umd/types/viz-element.d.ts +0 -6
- package/dist/umd/types/viz-element.d.ts.map +1 -1
- package/dist/umd/types/viz-scrollmap.d.ts +27 -0
- package/dist/umd/types/viz-scrollmap.d.ts.map +1 -0
- package/package.json +14 -11
- package/dist/esm/components/Layout/ContentHeader.d.ts +0 -4
- package/dist/esm/components/Layout/ContentHeader.d.ts.map +0 -1
- package/dist/esm/components/Layout/VizMode.d.ts +0 -2
- package/dist/esm/components/Layout/VizMode.d.ts.map +0 -1
- package/dist/esm/components/Test.d.ts +0 -121
- package/dist/esm/components/Test.d.ts.map +0 -1
- package/dist/esm/components/VizDom/VizDomContainer.d.ts +0 -6
- package/dist/esm/components/VizDom/VizDomContainer.d.ts.map +0 -1
- package/dist/esm/components/VizElement/ClickedElementOverlay.d.ts +0 -17
- package/dist/esm/components/VizElement/ClickedElementOverlay.d.ts.map +0 -1
- package/dist/esm/components/VizElement/HoveredElementOverlay.d.ts +0 -12
- package/dist/esm/components/VizElement/HoveredElementOverlay.d.ts.map +0 -1
- package/dist/esm/components/VizElement/MissingElementMessage.d.ts +0 -7
- package/dist/esm/components/VizElement/MissingElementMessage.d.ts.map +0 -1
- package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts +0 -150
- package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts.map +0 -1
- package/dist/esm/components/VizElement/temp/VizElementRank.d.ts +0 -74
- package/dist/esm/components/VizElement/temp/VizElementRank.d.ts.map +0 -1
- package/dist/esm/components/VizLive/VizLive.d.ts +0 -2
- package/dist/esm/components/VizLive/VizLive.d.ts.map +0 -1
- package/dist/esm/helpers/viewport-fixer.d.ts +0 -13
- package/dist/esm/helpers/viewport-fixer.d.ts.map +0 -1
- package/dist/esm/helpers/viewport-replacer.d.ts +0 -26
- package/dist/esm/helpers/viewport-replacer.d.ts.map +0 -1
- package/dist/esm/hooks/vix-elements/useHoveredElement.d.ts.map +0 -1
- package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +0 -2
- package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +0 -1
- package/dist/esm/hooks/viz-live/useIframeMessage.d.ts.map +0 -1
- package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts +0 -10
- package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts.map +0 -1
- package/dist/esm/types/viewport-fixer.d.ts +0 -31
- package/dist/esm/types/viewport-fixer.d.ts.map +0 -1
- package/dist/umd/components/Layout/ContentHeader.d.ts +0 -4
- package/dist/umd/components/Layout/ContentHeader.d.ts.map +0 -1
- package/dist/umd/components/Test.d.ts +0 -121
- package/dist/umd/components/Test.d.ts.map +0 -1
- package/dist/umd/components/VizDom/VizDomContainer.d.ts +0 -2
- package/dist/umd/components/VizDom/VizDomContainer.d.ts.map +0 -1
- package/dist/umd/components/VizElement/ClickedElementOverlay.d.ts +0 -17
- package/dist/umd/components/VizElement/ClickedElementOverlay.d.ts.map +0 -1
- package/dist/umd/components/VizElement/HoveredElementOverlay.d.ts +0 -12
- package/dist/umd/components/VizElement/HoveredElementOverlay.d.ts.map +0 -1
- package/dist/umd/components/VizElement/MissingElementMessage.d.ts +0 -7
- package/dist/umd/components/VizElement/MissingElementMessage.d.ts.map +0 -1
- package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts +0 -150
- package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts.map +0 -1
- package/dist/umd/components/VizElement/temp/VizElementRank.d.ts +0 -74
- package/dist/umd/components/VizElement/temp/VizElementRank.d.ts.map +0 -1
- package/dist/umd/helpers/viewport-fixer.d.ts +0 -13
- package/dist/umd/helpers/viewport-fixer.d.ts.map +0 -1
- package/dist/umd/helpers/viewport-replacer.d.ts +0 -26
- package/dist/umd/helpers/viewport-replacer.d.ts.map +0 -1
- package/dist/umd/hooks/vix-elements/useHoveredElement.d.ts.map +0 -1
- package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +0 -2
- package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +0 -1
- package/dist/umd/hooks/viz-live/useIframeMessage.d.ts.map +0 -1
- package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts +0 -10
- package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts.map +0 -1
- package/dist/umd/types/viewport-fixer.d.ts +0 -31
- package/dist/umd/types/viewport-fixer.d.ts.map +0 -1
- package/src/components/GraphView.tsx +0 -58
- package/src/components/Layout/ContentMetricBar.tsx +0 -23
- package/src/components/Layout/ContentToolbar.tsx +0 -22
- package/src/components/Layout/ContentTopBar.tsx +0 -24
- package/src/components/Layout/ContentVizByMode.tsx +0 -14
- package/src/components/Layout/HeatmapLayout.tsx +0 -60
- package/src/components/Layout/LeftSidebar.tsx +0 -44
- package/src/components/Layout/WrapperLayout.tsx +0 -12
- package/src/components/Layout/WrapperPreview.tsx +0 -24
- package/src/components/Layout/index.ts +0 -1
- package/src/components/VizDom/ReplayControls.tsx +0 -48
- package/src/components/VizDom/VizContainer.tsx +0 -40
- package/src/components/VizDom/VizDomHeatmap.tsx +0 -28
- package/src/components/VizDom/VizDomRenderer.tsx +0 -82
- package/src/components/VizDom/VizLoading.tsx +0 -8
- package/src/components/VizDom/WrapperVisual.tsx +0 -73
- package/src/components/VizDom/index.ts +0 -5
- package/src/components/VizElement/DefaultRankBadges.tsx +0 -36
- package/src/components/VizElement/ElementCallout.tsx +0 -82
- package/src/components/VizElement/ElementMissing.tsx +0 -35
- package/src/components/VizElement/ElementOverlay.tsx +0 -66
- package/src/components/VizElement/HeatmapElements.tsx +0 -127
- package/src/components/VizElement/HeatmapExample.tsx +0 -70
- package/src/components/VizElement/RankBadge.tsx +0 -25
- package/src/components/VizElement/VizElements.tsx +0 -57
- package/src/components/VizElement/index.ts +0 -1
- package/src/components/VizLive/VizLiveHeatmap.tsx +0 -27
- package/src/components/VizLive/VizLiveRenderer.tsx +0 -47
- package/src/components/VizLive/index.ts +0 -1
- package/src/components/VizScrollmap/AverageFoldLine.tsx +0 -57
- package/src/components/VizScrollmap/HoverZones.tsx +0 -58
- package/src/components/VizScrollmap/MetricRow.tsx +0 -0
- package/src/components/VizScrollmap/ScrollMapMinimap.tsx +0 -64
- package/src/components/VizScrollmap/ScrollMapOverlay.tsx +0 -79
- package/src/components/VizScrollmap/ScrollZoneHoverArea.tsx +0 -35
- package/src/components/VizScrollmap/ScrollZoneTooltip.tsx +0 -146
- package/src/components/VizScrollmap/ScrollmapMarker.tsx +0 -106
- package/src/components/VizScrollmap/VizScrollMap.tsx +0 -36
- package/src/components/VizScrollmapV2/ScrollmapOverlay.css +0 -94
- package/src/components/VizScrollmapV2/ScrollmapOverlayV2.tsx +0 -130
- package/src/components/VizScrollmapV2/scrollmap.types.ts +0 -21
- package/src/components/VizScrollmapV2/useScrollmapOverlay.ts +0 -187
- package/src/components/index.tsx +0 -2
- package/src/configs/iframe.ts +0 -15
- package/src/configs/index.ts +0 -2
- package/src/configs/style.ts +0 -21
- package/src/constants/index.ts +0 -4
- package/src/global.d.ts +0 -5
- package/src/helpers/elm-callout.ts +0 -347
- package/src/helpers/elm-getter.ts +0 -70
- package/src/helpers/iframe-helper/fixer.ts +0 -100
- package/src/helpers/iframe-helper/index.ts +0 -1
- package/src/helpers/iframe-helper/init.ts +0 -56
- package/src/helpers/iframe-helper/navigation-blocker-v2.ts +0 -371
- package/src/helpers/iframe-helper/navigation-blocker.ts +0 -367
- package/src/helpers/iframe-helper/style-replacer.ts +0 -231
- package/src/helpers/iframe.ts +0 -42
- package/src/helpers/index.ts +0 -8
- package/src/helpers/viz-canvas/area-clustering.ts +0 -234
- package/src/helpers/viz-canvas/area-overlay-manager-v2.ts +0 -176
- package/src/helpers/viz-canvas/area-overlay-manager.ts +0 -273
- package/src/helpers/viz-canvas/hierarchical-area-clustering.ts +0 -420
- package/src/helpers/viz-elements.ts +0 -43
- package/src/hooks/index.ts +0 -8
- package/src/hooks/register/index.ts +0 -4
- package/src/hooks/register/useRegisterConfig.ts +0 -17
- package/src/hooks/register/useRegisterControl.ts +0 -13
- package/src/hooks/register/useRegisterData.ts +0 -36
- package/src/hooks/register/useRegisterHeatmap.ts +0 -38
- package/src/hooks/viz-area/useAreaHeatmap.ts +0 -336
- package/src/hooks/viz-area/useAreaHeatmapManager.ts +0 -692
- package/src/hooks/viz-canvas/index.ts +0 -1
- package/src/hooks/viz-canvas/useAreamap.ts +0 -162
- package/src/hooks/viz-canvas/useClickmap.ts +0 -24
- package/src/hooks/viz-canvas/useHeatmapCanvas.ts +0 -27
- package/src/hooks/viz-canvas/useScrollmap.ts +0 -22
- package/src/hooks/viz-elements/index.ts +0 -5
- package/src/hooks/viz-elements/useClickedElement.ts +0 -86
- package/src/hooks/viz-elements/useElementCalloutVisible.ts +0 -45
- package/src/hooks/viz-elements/useHeatmapEffects.ts +0 -30
- package/src/hooks/viz-elements/useHeatmapElementPosition.ts +0 -60
- package/src/hooks/viz-elements/useHeatmapMouseHandler.ts +0 -255
- package/src/hooks/viz-elements/useHoveredElement.ts +0 -170
- package/src/hooks/viz-live/index.ts +0 -1
- package/src/hooks/viz-live/useVizLiveIframeMsg.ts +0 -88
- package/src/hooks/viz-live/useVizLiveRender.ts +0 -67
- package/src/hooks/viz-render/index.ts +0 -1
- package/src/hooks/viz-render/useHeatmapRender.ts +0 -71
- package/src/hooks/viz-render/useHeatmapVizRender.ts +0 -20
- package/src/hooks/viz-render/useReplayRender.ts +0 -160
- package/src/hooks/viz-scale/index.ts +0 -2
- package/src/hooks/viz-scale/useContainerDimensions.ts +0 -48
- package/src/hooks/viz-scale/useContentDimensions.ts +0 -25
- package/src/hooks/viz-scale/useHeatmapScale.ts +0 -52
- package/src/hooks/viz-scale/useObserveIframeHeight.ts +0 -162
- package/src/hooks/viz-scale/useScaleCalculation.ts +0 -31
- package/src/hooks/viz-scale/useScrollSync.ts +0 -36
- package/src/hooks/viz-scale/useWrapperRefHeight.ts +0 -91
- package/src/hooks/viz-scrollmap/useScrollmapZones.ts +0 -165
- package/src/hooks/viz-scrollmap/useZonePositions.ts +0 -38
- package/src/index.ts +0 -10
- package/src/stores/comp.ts +0 -31
- package/src/stores/config.ts +0 -37
- package/src/stores/data.ts +0 -30
- package/src/stores/index.ts +0 -10
- package/src/stores/interaction.ts +0 -32
- package/src/stores/mode-live.ts +0 -38
- package/src/stores/mode-single.ts +0 -18
- package/src/stores/viz-scrollmap.ts +0 -22
- package/src/stores/viz.ts +0 -17
- package/src/styles/base.css +0 -1
- package/src/styles/style.css +0 -137
- package/src/types/clarity.ts +0 -45
- package/src/types/control.ts +0 -10
- package/src/types/elm-callout.ts +0 -9
- package/src/types/heatmap-info.ts +0 -11
- package/src/types/heatmap.ts +0 -25
- package/src/types/iframe-helper.ts +0 -18
- package/src/types/index.ts +0 -12
- package/src/types/viz-canvas.ts +0 -20
- package/src/types/viz-element.ts +0 -34
- package/src/types/viz-scrollmap.ts +0 -28
- package/src/ui/BoxStack/BoxStack.tsx +0 -136
- package/src/ui/BoxStack/index.ts +0 -1
- package/src/ui/index.ts +0 -1
- package/src/utils/debounce.ts +0 -10
- package/src/utils/device.ts +0 -7
- package/src/utils/retry.ts +0 -20
- package/src/utils/sort.ts +0 -5
- /package/dist/esm/hooks/{vix-elements → viz-elements}/index.d.ts +0 -0
- /package/dist/esm/hooks/{vix-elements → viz-elements}/useClickedElement.d.ts +0 -0
- /package/dist/esm/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts +0 -0
- /package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts +0 -0
- /package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts +0 -0
- /package/dist/umd/hooks/{vix-elements → viz-elements}/index.d.ts +0 -0
- /package/dist/umd/hooks/{vix-elements → viz-elements}/useClickedElement.d.ts +0 -0
- /package/dist/umd/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts +0 -0
- /package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts +0 -0
- /package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts +0 -0
package/dist/esm/index.mjs
CHANGED
|
@@ -61,6 +61,8 @@ const HEATMAP_STYLE = {
|
|
|
61
61
|
},
|
|
62
62
|
wrapper: {
|
|
63
63
|
padding: `${HEATMAP_CONFIG.padding}px 0`,
|
|
64
|
+
paddingBlock: `${HEATMAP_CONFIG.padding}px`,
|
|
65
|
+
paddingInline: `${HEATMAP_CONFIG.padding}px`,
|
|
64
66
|
},
|
|
65
67
|
};
|
|
66
68
|
const DEFAULT_SIDEBAR_WIDTH = 260;
|
|
@@ -91,18 +93,37 @@ var IHeatmapType;
|
|
|
91
93
|
IHeatmapType["Click"] = "click";
|
|
92
94
|
IHeatmapType["Scroll"] = "scroll";
|
|
93
95
|
})(IHeatmapType || (IHeatmapType = {}));
|
|
96
|
+
var IClickType;
|
|
97
|
+
(function (IClickType) {
|
|
98
|
+
IClickType["Total"] = "total-clicks";
|
|
99
|
+
IClickType["Rage"] = "rage-clicks";
|
|
100
|
+
IClickType["Dead"] = "dead-clicks";
|
|
101
|
+
IClickType["Error"] = "error-clicks";
|
|
102
|
+
IClickType["First"] = "first-clicks";
|
|
103
|
+
IClickType["Last"] = "last-clicks";
|
|
104
|
+
})(IClickType || (IClickType = {}));
|
|
105
|
+
var IScrollType;
|
|
106
|
+
(function (IScrollType) {
|
|
107
|
+
IScrollType["Depth"] = "scroll-depth";
|
|
108
|
+
IScrollType["Attention"] = "attention-scroll";
|
|
109
|
+
IScrollType["Revenue"] = "revenue-scroll";
|
|
110
|
+
})(IScrollType || (IScrollType = {}));
|
|
94
111
|
|
|
95
112
|
const useHeatmapConfigStore = create()((set, get) => {
|
|
96
113
|
return {
|
|
97
114
|
mode: 'single',
|
|
98
115
|
width: 1440,
|
|
99
116
|
sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
|
|
100
|
-
heatmapType: IHeatmapType.
|
|
117
|
+
heatmapType: IHeatmapType.Scroll,
|
|
118
|
+
clickType: IClickType.Total,
|
|
119
|
+
scrollType: IScrollType.Depth,
|
|
101
120
|
setMode: (mode) => set({ mode }),
|
|
102
121
|
resetMode: () => set({ mode: 'single' }),
|
|
103
122
|
setWidth: (width) => set({ width }),
|
|
104
123
|
setSidebarWidth: (sidebarWidth) => set({ sidebarWidth }),
|
|
105
124
|
setHeatmapType: (heatmapType) => set({ heatmapType }),
|
|
125
|
+
setClickType: (clickType) => set({ clickType }),
|
|
126
|
+
setScrollType: (scrollType) => set({ scrollType }),
|
|
106
127
|
};
|
|
107
128
|
});
|
|
108
129
|
|
|
@@ -111,11 +132,13 @@ const useHeatmapDataStore = create()((set, get) => {
|
|
|
111
132
|
data: undefined,
|
|
112
133
|
clickmap: undefined,
|
|
113
134
|
dataInfo: undefined,
|
|
135
|
+
scrollmap: undefined,
|
|
114
136
|
isRendering: true,
|
|
115
137
|
setIsRendering: (isRendering) => set({ isRendering }),
|
|
116
138
|
setDataInfo: (dataInfo) => set({ dataInfo }),
|
|
117
139
|
setData: (data) => set({ data }),
|
|
118
140
|
setClickmap: (clickmap) => set({ clickmap }),
|
|
141
|
+
setScrollmap: (scrollmap) => set({ scrollmap }),
|
|
119
142
|
};
|
|
120
143
|
});
|
|
121
144
|
|
|
@@ -139,15 +162,23 @@ const useHeatmapVizStore = create()((set, get) => {
|
|
|
139
162
|
isRenderViz: false,
|
|
140
163
|
setIsRenderViz: (isRenderViz) => set({ isRenderViz }),
|
|
141
164
|
scale: 1,
|
|
142
|
-
vizRef: undefined,
|
|
143
|
-
iframeHeight: 0,
|
|
144
165
|
setScale: (scale) => set({ scale }),
|
|
145
|
-
|
|
146
|
-
|
|
166
|
+
};
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const useHeatmapVizScrollmapStore = create()((set, get) => {
|
|
170
|
+
return {
|
|
171
|
+
zones: [],
|
|
172
|
+
hoveredZone: null,
|
|
173
|
+
showMinimap: true,
|
|
174
|
+
setZones: (zones) => set({ zones }),
|
|
175
|
+
setHoveredZone: (hoveredZone) => set({ hoveredZone }),
|
|
176
|
+
setShowMinimap: (showMinimap) => set({ showMinimap }),
|
|
147
177
|
};
|
|
148
178
|
});
|
|
149
179
|
|
|
150
180
|
const initialState = {
|
|
181
|
+
payloads: [],
|
|
151
182
|
htmlContent: '',
|
|
152
183
|
wrapperHeight: 0,
|
|
153
184
|
iframeHeight: 0,
|
|
@@ -156,12 +187,23 @@ const useHeatmapLiveStore = create()((set, get) => {
|
|
|
156
187
|
return {
|
|
157
188
|
...initialState,
|
|
158
189
|
reset: () => set(initialState),
|
|
190
|
+
setPayloads: (payloads) => set({ payloads }),
|
|
191
|
+
addPayload: (payload) => set((state) => ({ payloads: [...state.payloads, payload] })),
|
|
159
192
|
setHtmlContent: (htmlContent) => set({ htmlContent }),
|
|
160
193
|
setWrapperHeight: (wrapperHeight) => set({ wrapperHeight }),
|
|
161
194
|
setIframeHeight: (iframeHeight) => set({ iframeHeight }),
|
|
162
195
|
};
|
|
163
196
|
});
|
|
164
197
|
|
|
198
|
+
const useHeatmapSingleStore = create()((set, get) => {
|
|
199
|
+
return {
|
|
200
|
+
vizRef: null,
|
|
201
|
+
iframeHeight: 0,
|
|
202
|
+
setVizRef: (vizRef) => set({ vizRef }),
|
|
203
|
+
setIframeHeight: (iframeHeight) => set({ iframeHeight }),
|
|
204
|
+
};
|
|
205
|
+
});
|
|
206
|
+
|
|
165
207
|
const useRegisterConfig = () => {
|
|
166
208
|
const mode = useHeatmapConfigStore((state) => state.mode);
|
|
167
209
|
const width = useHeatmapConfigStore((state) => state.width);
|
|
@@ -209,16 +251,25 @@ const useRegisterData = (data, dataInfo) => {
|
|
|
209
251
|
}, [dataInfo]);
|
|
210
252
|
};
|
|
211
253
|
|
|
212
|
-
const useRegisterHeatmap = (clickmap) => {
|
|
254
|
+
const useRegisterHeatmap = ({ clickmap, scrollmap }) => {
|
|
213
255
|
const setClickmap = useHeatmapDataStore((state) => state.setClickmap);
|
|
256
|
+
const setScrollmap = useHeatmapDataStore((state) => state.setScrollmap);
|
|
214
257
|
const handleSetClickmap = useCallback((clickmap) => {
|
|
215
258
|
if (!clickmap)
|
|
216
259
|
return;
|
|
217
260
|
setClickmap(clickmap);
|
|
218
261
|
}, [clickmap]);
|
|
262
|
+
const handleSetScrollmap = useCallback((scrollmap) => {
|
|
263
|
+
if (!scrollmap)
|
|
264
|
+
return;
|
|
265
|
+
setScrollmap(scrollmap);
|
|
266
|
+
}, [scrollmap]);
|
|
219
267
|
useEffect(() => {
|
|
220
268
|
handleSetClickmap(clickmap);
|
|
221
269
|
}, [clickmap]);
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
handleSetScrollmap(scrollmap);
|
|
272
|
+
}, [scrollmap]);
|
|
222
273
|
};
|
|
223
274
|
|
|
224
275
|
const PADDING = 0;
|
|
@@ -501,91 +552,311 @@ function isElementInViewport(elementRect, visualRef, scale) {
|
|
|
501
552
|
return elementBottom > viewportTop && elementTop < viewportBottom;
|
|
502
553
|
}
|
|
503
554
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
class ViewportUnitsFixer {
|
|
519
|
-
iframe = null;
|
|
520
|
-
config;
|
|
521
|
-
constructor(config) {
|
|
522
|
-
this.config = config;
|
|
523
|
-
this.iframe = config.iframe;
|
|
555
|
+
class IframeNavigationBlockerV2 {
|
|
556
|
+
doc;
|
|
557
|
+
win;
|
|
558
|
+
isEnabled = false;
|
|
559
|
+
showMessage = false;
|
|
560
|
+
originalWindowOpen;
|
|
561
|
+
observers = [];
|
|
562
|
+
constructor(iframe) {
|
|
563
|
+
if (!iframe.contentDocument || !iframe.contentWindow) {
|
|
564
|
+
throw new Error('Iframe document or window not accessible');
|
|
565
|
+
}
|
|
566
|
+
this.doc = iframe.contentDocument;
|
|
567
|
+
this.win = iframe.contentWindow;
|
|
568
|
+
this.originalWindowOpen = this.win.open.bind(this.win);
|
|
524
569
|
this.init();
|
|
525
570
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
571
|
+
init() {
|
|
572
|
+
console.log('[NavigationBlocker] Initializing...');
|
|
573
|
+
try {
|
|
574
|
+
// Chặn navigation qua links
|
|
575
|
+
this.blockLinkNavigation();
|
|
576
|
+
// Chặn form submissions
|
|
577
|
+
this.blockFormSubmissions();
|
|
578
|
+
// Chặn window.open (này an toàn)
|
|
579
|
+
this.blockWindowOpen();
|
|
580
|
+
// Chặn beforeunload để prevent navigation
|
|
581
|
+
this.blockBeforeUnload();
|
|
582
|
+
// Monitor DOM changes để block dynamic links
|
|
583
|
+
this.monitorDOMChanges();
|
|
584
|
+
// Inject CSP nếu có thể
|
|
585
|
+
this.injectCSP();
|
|
535
586
|
}
|
|
536
|
-
|
|
537
|
-
|
|
587
|
+
catch (error) {
|
|
588
|
+
console.error('[NavigationBlocker] Init error:', error);
|
|
538
589
|
}
|
|
539
590
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
591
|
+
blockLinkNavigation() {
|
|
592
|
+
// Sử dụng capture phase để chặn sớm nhất
|
|
593
|
+
this.doc.addEventListener('click', (e) => {
|
|
594
|
+
if (!this.isEnabled)
|
|
595
|
+
return;
|
|
596
|
+
const target = e.target;
|
|
597
|
+
const link = target.closest('a');
|
|
598
|
+
if (link) {
|
|
599
|
+
const href = link.getAttribute('href');
|
|
600
|
+
// Cho phép hash links và empty links
|
|
601
|
+
if (!href || href === '' || href === '#' || href.startsWith('#')) {
|
|
602
|
+
console.log('[NavigationBlocker] Allowed hash navigation:', href);
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
// Chặn tất cả các loại navigation
|
|
606
|
+
console.log('[NavigationBlocker] Blocked link navigation to:', href);
|
|
607
|
+
e.preventDefault();
|
|
608
|
+
e.stopPropagation();
|
|
609
|
+
e.stopImmediatePropagation();
|
|
610
|
+
this.notifyBlockedNavigation(href);
|
|
611
|
+
}
|
|
612
|
+
}, true);
|
|
613
|
+
// Chặn cả middle click và right click "open in new tab"
|
|
614
|
+
this.doc.addEventListener('auxclick', (e) => {
|
|
615
|
+
if (!this.isEnabled)
|
|
616
|
+
return;
|
|
617
|
+
const target = e.target;
|
|
618
|
+
const link = target.closest('a');
|
|
619
|
+
if (link) {
|
|
620
|
+
const href = link.getAttribute('href');
|
|
621
|
+
if (href && !href.startsWith('#')) {
|
|
622
|
+
console.log('[NavigationBlocker] Blocked auxclick navigation');
|
|
623
|
+
e.preventDefault();
|
|
624
|
+
e.stopPropagation();
|
|
625
|
+
e.stopImmediatePropagation();
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}, true);
|
|
629
|
+
// Disable tất cả links ngay từ đầu
|
|
630
|
+
this.disableAllLinks();
|
|
631
|
+
}
|
|
632
|
+
disableAllLinks() {
|
|
633
|
+
this.doc.querySelectorAll('a[href]').forEach((link) => {
|
|
634
|
+
const href = link.getAttribute('href');
|
|
635
|
+
if (href && !href.startsWith('#')) {
|
|
636
|
+
// Thêm pointer-events: none và cursor
|
|
637
|
+
link.style.cursor = 'not-allowed';
|
|
638
|
+
link.setAttribute('data-navigation-blocked', 'true');
|
|
639
|
+
// Remove href để browser không hiện preview
|
|
640
|
+
link.setAttribute('data-original-href', href);
|
|
641
|
+
link.removeAttribute('href');
|
|
642
|
+
// Hoặc giữ href nhưng disable
|
|
643
|
+
// link.setAttribute('onclick', 'return false');
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
blockFormSubmissions() {
|
|
648
|
+
this.doc.addEventListener('submit', (e) => {
|
|
649
|
+
if (!this.isEnabled)
|
|
650
|
+
return;
|
|
651
|
+
const form = e.target;
|
|
652
|
+
const action = form.getAttribute('action');
|
|
653
|
+
// Cho phép forms không có action
|
|
654
|
+
if (!action || action === '' || action === '#') {
|
|
655
|
+
console.log('[NavigationBlocker] Allowed same-page form');
|
|
656
|
+
e.preventDefault();
|
|
657
|
+
this.handleFormSubmit(form);
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
// Chặn tất cả external submissions
|
|
661
|
+
console.log('[NavigationBlocker] Blocked form submission to:', action);
|
|
662
|
+
e.preventDefault();
|
|
663
|
+
e.stopPropagation();
|
|
664
|
+
e.stopImmediatePropagation();
|
|
665
|
+
this.notifyBlockedNavigation(action);
|
|
666
|
+
}, true);
|
|
667
|
+
}
|
|
668
|
+
blockWindowOpen() {
|
|
669
|
+
// Override window.open - đây là safe
|
|
670
|
+
this.win.open = ((...args) => {
|
|
671
|
+
if (!this.isEnabled) {
|
|
672
|
+
return this.originalWindowOpen(...args);
|
|
673
|
+
}
|
|
674
|
+
const url = args[0]?.toString() || 'popup';
|
|
675
|
+
console.log('[NavigationBlocker] Blocked window.open:', url);
|
|
676
|
+
this.notifyBlockedNavigation(url);
|
|
677
|
+
return null;
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
blockBeforeUnload() {
|
|
681
|
+
// Chặn unload
|
|
682
|
+
this.win.addEventListener('beforeunload', (e) => {
|
|
683
|
+
if (!this.isEnabled)
|
|
684
|
+
return;
|
|
685
|
+
console.log('[NavigationBlocker] Blocked beforeunload');
|
|
686
|
+
e.preventDefault();
|
|
687
|
+
e.returnValue = '';
|
|
688
|
+
return '';
|
|
689
|
+
}, true);
|
|
690
|
+
// Chặn unload
|
|
691
|
+
this.win.addEventListener('unload', (e) => {
|
|
692
|
+
if (!this.isEnabled)
|
|
693
|
+
return;
|
|
694
|
+
console.log('[NavigationBlocker] Blocked unload');
|
|
695
|
+
e.preventDefault();
|
|
696
|
+
e.stopPropagation();
|
|
697
|
+
}, true);
|
|
698
|
+
// Monitor popstate
|
|
699
|
+
this.win.addEventListener('popstate', (e) => {
|
|
700
|
+
if (!this.isEnabled)
|
|
701
|
+
return;
|
|
702
|
+
console.log('[NavigationBlocker] Blocked popstate');
|
|
703
|
+
e.preventDefault();
|
|
704
|
+
e.stopPropagation();
|
|
705
|
+
}, true);
|
|
706
|
+
}
|
|
707
|
+
monitorDOMChanges() {
|
|
708
|
+
// Monitor khi có links mới được thêm vào
|
|
709
|
+
const observer = new MutationObserver((mutations) => {
|
|
710
|
+
if (!this.isEnabled)
|
|
711
|
+
return;
|
|
712
|
+
mutations.forEach((mutation) => {
|
|
713
|
+
mutation.addedNodes.forEach((node) => {
|
|
714
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
715
|
+
const element = node;
|
|
716
|
+
// Nếu là link
|
|
717
|
+
if (element.tagName === 'A') {
|
|
718
|
+
const href = element.getAttribute('href');
|
|
719
|
+
if (href && !href.startsWith('#')) {
|
|
720
|
+
element.style.cursor = 'not-allowed';
|
|
721
|
+
element.setAttribute('data-navigation-blocked', 'true');
|
|
722
|
+
element.setAttribute('data-original-href', href);
|
|
723
|
+
element.removeAttribute('href');
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
// Tìm links trong subtree
|
|
727
|
+
element.querySelectorAll('a[href]').forEach((link) => {
|
|
728
|
+
const href = link.getAttribute('href');
|
|
729
|
+
if (href && !href.startsWith('#')) {
|
|
730
|
+
link.style.cursor = 'not-allowed';
|
|
731
|
+
link.setAttribute('data-navigation-blocked', 'true');
|
|
732
|
+
link.setAttribute('data-original-href', href);
|
|
733
|
+
link.removeAttribute('href');
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
});
|
|
555
738
|
});
|
|
556
|
-
};
|
|
557
|
-
doc.
|
|
739
|
+
});
|
|
740
|
+
observer.observe(this.doc.body, {
|
|
741
|
+
childList: true,
|
|
742
|
+
subtree: true,
|
|
743
|
+
});
|
|
744
|
+
this.observers.push(observer);
|
|
745
|
+
}
|
|
746
|
+
injectCSP() {
|
|
747
|
+
// Thêm CSP meta tag nếu chưa có (optional)
|
|
748
|
+
try {
|
|
749
|
+
const existingCSP = this.doc.querySelector('meta[http-equiv="Content-Security-Policy"]');
|
|
750
|
+
if (!existingCSP) {
|
|
751
|
+
const meta = this.doc.createElement('meta');
|
|
752
|
+
meta.httpEquiv = 'Content-Security-Policy';
|
|
753
|
+
meta.content = "navigate-to 'none'"; // Chặn tất cả navigation
|
|
754
|
+
this.doc.head.appendChild(meta);
|
|
755
|
+
console.log('[NavigationBlocker] Injected CSP');
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
catch (error) {
|
|
759
|
+
console.warn('[NavigationBlocker] Could not inject CSP:', error);
|
|
760
|
+
}
|
|
558
761
|
}
|
|
559
|
-
|
|
560
|
-
const
|
|
561
|
-
|
|
762
|
+
handleFormSubmit(form) {
|
|
763
|
+
const formData = new FormData(form);
|
|
764
|
+
const data = {};
|
|
765
|
+
formData.forEach((value, key) => {
|
|
766
|
+
data[key] = value;
|
|
767
|
+
});
|
|
768
|
+
console.log('[NavigationBlocker] Handling form data:', data);
|
|
769
|
+
window.dispatchEvent(new CustomEvent('iframe-form-submit', {
|
|
770
|
+
detail: { form, data },
|
|
771
|
+
}));
|
|
772
|
+
}
|
|
773
|
+
notifyBlockedNavigation(url) {
|
|
774
|
+
console.warn('[NavigationBlocker] Navigation blocked to:', url);
|
|
775
|
+
window.dispatchEvent(new CustomEvent('iframe-navigation-blocked', {
|
|
776
|
+
detail: { url, timestamp: Date.now() },
|
|
777
|
+
}));
|
|
778
|
+
if (this.shouldShowMessage(url)) {
|
|
779
|
+
this.showBlockedMessage(url);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
shouldShowMessage(url) {
|
|
783
|
+
return !url.startsWith('#') && url !== 'reload' && url !== 'popup';
|
|
784
|
+
}
|
|
785
|
+
showBlockedMessage(url) {
|
|
786
|
+
if (!this.showMessage)
|
|
562
787
|
return;
|
|
563
|
-
this.
|
|
788
|
+
const message = this.doc.createElement('div');
|
|
789
|
+
message.style.cssText = `
|
|
790
|
+
position: fixed;
|
|
791
|
+
top: 20px;
|
|
792
|
+
right: 20px;
|
|
793
|
+
background: #ff6b6b;
|
|
794
|
+
color: white;
|
|
795
|
+
padding: 12px 20px;
|
|
796
|
+
border-radius: 8px;
|
|
797
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
798
|
+
z-index: 999999;
|
|
799
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
800
|
+
font-size: 14px;
|
|
801
|
+
max-width: 300px;
|
|
802
|
+
word-break: break-word;
|
|
803
|
+
pointer-events: none;
|
|
804
|
+
`;
|
|
805
|
+
const shortUrl = url.length > 50 ? url.substring(0, 47) + '...' : url;
|
|
806
|
+
message.innerHTML = `
|
|
807
|
+
<div style="font-weight: 600; margin-bottom: 4px;">🚫 Navigation Blocked</div>
|
|
808
|
+
<div style="font-size: 12px; opacity: 0.9;">${this.escapeHtml(shortUrl)}</div>
|
|
809
|
+
`;
|
|
810
|
+
this.doc.body.appendChild(message);
|
|
811
|
+
setTimeout(() => {
|
|
812
|
+
message.style.opacity = '0';
|
|
813
|
+
message.style.transition = 'opacity 0.3s';
|
|
814
|
+
setTimeout(() => message.remove(), 300);
|
|
815
|
+
}, 3000);
|
|
564
816
|
}
|
|
565
|
-
|
|
566
|
-
this.
|
|
817
|
+
escapeHtml(text) {
|
|
818
|
+
const div = this.doc.createElement('div');
|
|
819
|
+
div.textContent = text;
|
|
820
|
+
return div.innerHTML;
|
|
821
|
+
}
|
|
822
|
+
enable() {
|
|
823
|
+
this.isEnabled = true;
|
|
824
|
+
console.log('[NavigationBlocker] Enabled');
|
|
825
|
+
}
|
|
826
|
+
enableMessage() {
|
|
827
|
+
this.showMessage = true;
|
|
828
|
+
console.log('[NavigationBlocker] Enabled message');
|
|
829
|
+
}
|
|
830
|
+
disable() {
|
|
831
|
+
this.isEnabled = false;
|
|
832
|
+
console.log('[NavigationBlocker] Disabled');
|
|
833
|
+
}
|
|
834
|
+
disableMessage() {
|
|
835
|
+
this.showMessage = false;
|
|
836
|
+
console.log('[NavigationBlocker] Disabled message');
|
|
837
|
+
}
|
|
838
|
+
destroy() {
|
|
839
|
+
this.isEnabled = false;
|
|
840
|
+
this.showMessage = false;
|
|
841
|
+
// Cleanup observers
|
|
842
|
+
this.observers.forEach((observer) => observer.disconnect());
|
|
843
|
+
this.observers = [];
|
|
844
|
+
console.log('[NavigationBlocker] Destroyed');
|
|
567
845
|
}
|
|
568
|
-
}
|
|
569
|
-
function initViewportFixer(config) {
|
|
570
|
-
const fixer = new ViewportUnitsFixer(config);
|
|
571
|
-
window.viewportFixer = fixer;
|
|
572
|
-
window.addEventListener('iframe-dimensions-applied', ((e) => {
|
|
573
|
-
const ev = e;
|
|
574
|
-
console.log('Iframe dimensions finalized:', ev.detail);
|
|
575
|
-
}));
|
|
576
|
-
return fixer;
|
|
577
846
|
}
|
|
578
847
|
|
|
579
|
-
class
|
|
848
|
+
class IframeStyleReplacer {
|
|
849
|
+
doc;
|
|
850
|
+
win;
|
|
580
851
|
config;
|
|
581
852
|
regex = /([-.\d]+)(vh|svh|lvh|dvh|vw|svw|lvw|dvw)/gi;
|
|
582
|
-
constructor() {
|
|
583
|
-
if (!
|
|
584
|
-
throw new Error('
|
|
853
|
+
constructor(iframe, config) {
|
|
854
|
+
if (!iframe.contentDocument || !iframe.contentWindow) {
|
|
855
|
+
throw new Error('Iframe document or window not accessible');
|
|
585
856
|
}
|
|
586
|
-
this.
|
|
587
|
-
|
|
588
|
-
this.
|
|
857
|
+
this.doc = iframe.contentDocument;
|
|
858
|
+
this.win = iframe.contentWindow;
|
|
859
|
+
this.config = config;
|
|
589
860
|
}
|
|
590
861
|
px(value) {
|
|
591
862
|
return `${value.toFixed(2)}px`;
|
|
@@ -611,26 +882,28 @@ class ViewportUnitsReplacer {
|
|
|
611
882
|
}
|
|
612
883
|
processInlineStyles() {
|
|
613
884
|
let count = 0;
|
|
614
|
-
|
|
885
|
+
this.doc.querySelectorAll('[style]').forEach((el) => {
|
|
615
886
|
const style = el.getAttribute('style');
|
|
616
887
|
if (style && this.regex.test(style)) {
|
|
888
|
+
this.regex.lastIndex = 0;
|
|
617
889
|
el.setAttribute('style', this.replaceInText(style));
|
|
618
890
|
count++;
|
|
619
891
|
}
|
|
620
892
|
});
|
|
621
|
-
console.log(`[
|
|
893
|
+
console.log(`[IframeStyleReplacer] Replaced ${count} inline style elements`);
|
|
622
894
|
return count;
|
|
623
895
|
}
|
|
624
896
|
processStyleTags() {
|
|
625
897
|
let count = 0;
|
|
626
|
-
|
|
898
|
+
this.doc.querySelectorAll('style').forEach((tag) => {
|
|
627
899
|
const css = tag.textContent || '';
|
|
628
900
|
if (this.regex.test(css)) {
|
|
901
|
+
this.regex.lastIndex = 0;
|
|
629
902
|
tag.textContent = this.replaceInText(css);
|
|
630
903
|
count++;
|
|
631
904
|
}
|
|
632
905
|
});
|
|
633
|
-
console.log(`[
|
|
906
|
+
console.log(`[IframeStyleReplacer] Replaced ${count} <style> tags`);
|
|
634
907
|
return count;
|
|
635
908
|
}
|
|
636
909
|
processRule(rule) {
|
|
@@ -641,6 +914,7 @@ class ViewportUnitsReplacer {
|
|
|
641
914
|
const prop = style[i];
|
|
642
915
|
const value = style.getPropertyValue(prop);
|
|
643
916
|
if (value && this.regex.test(value)) {
|
|
917
|
+
this.regex.lastIndex = 0;
|
|
644
918
|
style.setProperty(prop, this.replaceInText(value), style.getPropertyPriority(prop));
|
|
645
919
|
count++;
|
|
646
920
|
}
|
|
@@ -656,11 +930,11 @@ class ViewportUnitsReplacer {
|
|
|
656
930
|
}
|
|
657
931
|
processStylesheets() {
|
|
658
932
|
let total = 0;
|
|
659
|
-
Array.from(
|
|
933
|
+
Array.from(this.doc.styleSheets).forEach((sheet) => {
|
|
660
934
|
try {
|
|
661
935
|
// Bỏ qua external CSS (cross-origin)
|
|
662
|
-
if (sheet.href && !sheet.href.startsWith(location.origin)) {
|
|
663
|
-
console.log('[
|
|
936
|
+
if (sheet.href && !sheet.href.startsWith(this.win.location.origin)) {
|
|
937
|
+
console.log('[IframeStyleReplacer] Skipping external CSS:', sheet.href);
|
|
664
938
|
return;
|
|
665
939
|
}
|
|
666
940
|
const rules = sheet.cssRules || sheet.rules;
|
|
@@ -671,26 +945,27 @@ class ViewportUnitsReplacer {
|
|
|
671
945
|
}
|
|
672
946
|
}
|
|
673
947
|
catch (e) {
|
|
674
|
-
console.warn('[
|
|
948
|
+
console.warn('[IframeStyleReplacer] Cannot read stylesheet (CORS?):', e.message);
|
|
675
949
|
}
|
|
676
950
|
});
|
|
677
|
-
console.log(`[
|
|
951
|
+
console.log(`[IframeStyleReplacer] Replaced ${total} rules in stylesheets`);
|
|
678
952
|
return total;
|
|
679
953
|
}
|
|
680
954
|
async processLinkedStylesheets() {
|
|
681
|
-
const links =
|
|
955
|
+
const links = this.doc.querySelectorAll('link[rel="stylesheet"]');
|
|
682
956
|
let count = 0;
|
|
683
957
|
for (const link of Array.from(links)) {
|
|
684
|
-
if (!link.href.startsWith(location.origin)) {
|
|
685
|
-
console.log('[
|
|
958
|
+
if (!link.href.startsWith(this.win.location.origin)) {
|
|
959
|
+
console.log('[IframeStyleReplacer] Skipping external CSS:', link.href);
|
|
686
960
|
continue;
|
|
687
961
|
}
|
|
688
962
|
try {
|
|
689
963
|
const res = await fetch(link.href);
|
|
690
964
|
let css = await res.text();
|
|
691
965
|
if (this.regex.test(css)) {
|
|
966
|
+
this.regex.lastIndex = 0;
|
|
692
967
|
css = this.replaceInText(css);
|
|
693
|
-
const style =
|
|
968
|
+
const style = this.doc.createElement('style');
|
|
694
969
|
style.textContent = css;
|
|
695
970
|
style.dataset.originalHref = link.href;
|
|
696
971
|
link.parentNode?.insertBefore(style, link);
|
|
@@ -699,30 +974,25 @@ class ViewportUnitsReplacer {
|
|
|
699
974
|
}
|
|
700
975
|
}
|
|
701
976
|
catch (e) {
|
|
702
|
-
console.warn('[
|
|
977
|
+
console.warn('[IframeStyleReplacer] Cannot load CSS:', link.href, e);
|
|
703
978
|
}
|
|
704
979
|
}
|
|
705
|
-
console.log(`[
|
|
980
|
+
console.log(`[IframeStyleReplacer] Replaced ${count} linked CSS files`);
|
|
706
981
|
return count;
|
|
707
982
|
}
|
|
708
983
|
getFinalHeight() {
|
|
709
984
|
// Trigger reflow
|
|
710
|
-
void
|
|
711
|
-
return Math.max(
|
|
985
|
+
void this.doc.body.offsetHeight;
|
|
986
|
+
return Math.max(this.doc.body.scrollHeight, this.doc.body.offsetHeight, this.doc.documentElement.scrollHeight, this.doc.documentElement.offsetHeight, this.doc.documentElement.clientHeight);
|
|
712
987
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
type: 'IFRAME_HEIGHT_CALCULATED',
|
|
716
|
-
height,
|
|
717
|
-
width: document.body.scrollWidth,
|
|
718
|
-
}, '*');
|
|
719
|
-
console.log('[Iframe] Sent height to parent:', height);
|
|
988
|
+
getFinalWidth() {
|
|
989
|
+
return Math.max(this.doc.body.scrollWidth, this.doc.body.offsetWidth, this.doc.documentElement.scrollWidth, this.doc.documentElement.offsetWidth, this.doc.documentElement.clientWidth);
|
|
720
990
|
}
|
|
721
991
|
async waitForResources() {
|
|
722
|
-
if ('fonts' in
|
|
723
|
-
await
|
|
992
|
+
if ('fonts' in this.doc) {
|
|
993
|
+
await this.doc.fonts.ready;
|
|
724
994
|
}
|
|
725
|
-
const images = Array.from(
|
|
995
|
+
const images = Array.from(this.doc.images).filter((img) => !img.complete);
|
|
726
996
|
if (images.length > 0) {
|
|
727
997
|
await Promise.all(images.map((img) => new Promise((resolve) => {
|
|
728
998
|
img.onload = img.onerror = resolve;
|
|
@@ -731,35 +1001,131 @@ class ViewportUnitsReplacer {
|
|
|
731
1001
|
}
|
|
732
1002
|
async run() {
|
|
733
1003
|
try {
|
|
1004
|
+
console.log('[IframeStyleReplacer] Starting viewport units replacement...');
|
|
734
1005
|
this.processInlineStyles();
|
|
735
1006
|
this.processStyleTags();
|
|
736
1007
|
this.processStylesheets();
|
|
737
1008
|
await this.processLinkedStylesheets();
|
|
738
1009
|
// await this.waitForResources();
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
1010
|
+
return await new Promise((resolve) => {
|
|
1011
|
+
requestAnimationFrame(() => {
|
|
1012
|
+
const height = this.getFinalHeight();
|
|
1013
|
+
const width = this.getFinalWidth();
|
|
1014
|
+
console.log('[IframeStyleReplacer] Calculated dimensions:', { height, width });
|
|
1015
|
+
resolve({ height, width });
|
|
1016
|
+
});
|
|
742
1017
|
});
|
|
743
1018
|
}
|
|
744
1019
|
catch (err) {
|
|
745
|
-
console.error('[
|
|
746
|
-
|
|
1020
|
+
console.error('[IframeStyleReplacer] Critical error:', err);
|
|
1021
|
+
return {
|
|
1022
|
+
height: this.doc.body.scrollHeight || 1000,
|
|
1023
|
+
width: this.doc.body.scrollWidth || 1000,
|
|
1024
|
+
};
|
|
747
1025
|
}
|
|
748
1026
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
1027
|
+
updateConfig(config) {
|
|
1028
|
+
this.config = { ...this.config, ...config };
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
class IframeHelperFixer {
|
|
1033
|
+
iframe;
|
|
1034
|
+
config;
|
|
1035
|
+
replacer = null;
|
|
1036
|
+
navigationBlocker = null;
|
|
1037
|
+
constructor(config) {
|
|
1038
|
+
this.config = config;
|
|
1039
|
+
this.iframe = config.iframe;
|
|
1040
|
+
this.init();
|
|
1041
|
+
}
|
|
1042
|
+
async init() {
|
|
1043
|
+
if (!this.iframe) {
|
|
1044
|
+
console.error('[IframeHelper] iframe not found');
|
|
1045
|
+
this.config.onError?.(new Error('iframe not found'));
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
// Wait for iframe to load completely
|
|
1049
|
+
if (this.iframe.contentDocument?.readyState === 'complete') {
|
|
1050
|
+
await this.process();
|
|
752
1051
|
}
|
|
753
1052
|
else {
|
|
754
|
-
this.
|
|
1053
|
+
this.iframe.addEventListener('load', () => this.process());
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
async process() {
|
|
1057
|
+
if (!this.iframe.contentDocument || !this.iframe.contentWindow) {
|
|
1058
|
+
console.error('[IframeHelper] Cannot access iframe document');
|
|
1059
|
+
this.config.onError?.(new Error('Cannot access iframe document'));
|
|
1060
|
+
return;
|
|
755
1061
|
}
|
|
1062
|
+
try {
|
|
1063
|
+
console.log('[IframeHelper] Processing viewport units...');
|
|
1064
|
+
// Create replacer instance
|
|
1065
|
+
this.replacer = new IframeStyleReplacer(this.iframe, this.config);
|
|
1066
|
+
// Create navigation blocker
|
|
1067
|
+
this.navigationBlocker = new IframeNavigationBlockerV2(this.iframe);
|
|
1068
|
+
// Run replacement
|
|
1069
|
+
const result = await this.replacer.run();
|
|
1070
|
+
console.log('[IframeHelper] Process completed:', result);
|
|
1071
|
+
// Trigger success callback
|
|
1072
|
+
this.config.onSuccess?.(result);
|
|
1073
|
+
// Dispatch custom event
|
|
1074
|
+
window.dispatchEvent(new CustomEvent('iframe-dimensions-applied', {
|
|
1075
|
+
detail: result,
|
|
1076
|
+
}));
|
|
1077
|
+
}
|
|
1078
|
+
catch (error) {
|
|
1079
|
+
console.error('[IframeHelper] Failed to process:', error);
|
|
1080
|
+
this.config.onError?.(error);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
async recalculate() {
|
|
1084
|
+
console.log('[IframeHelper] Recalculating...');
|
|
1085
|
+
await this.process();
|
|
1086
|
+
}
|
|
1087
|
+
updateConfig(config) {
|
|
1088
|
+
this.config = { ...this.config, ...config };
|
|
1089
|
+
if (this.replacer) {
|
|
1090
|
+
this.replacer.updateConfig(config);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
enableNavigationBlocking() {
|
|
1094
|
+
this.navigationBlocker?.enable();
|
|
1095
|
+
}
|
|
1096
|
+
enableNavigationBlockingMessage() {
|
|
1097
|
+
this.navigationBlocker?.enableMessage();
|
|
1098
|
+
}
|
|
1099
|
+
disableNavigationBlocking() {
|
|
1100
|
+
this.navigationBlocker?.disable();
|
|
1101
|
+
}
|
|
1102
|
+
disableNavigationBlockingMessage() {
|
|
1103
|
+
this.navigationBlocker?.disableMessage();
|
|
1104
|
+
}
|
|
1105
|
+
destroy() {
|
|
1106
|
+
this.replacer = null;
|
|
1107
|
+
this.navigationBlocker?.destroy();
|
|
1108
|
+
this.navigationBlocker = null;
|
|
1109
|
+
console.log('[IframeHelper] Destroyed');
|
|
756
1110
|
}
|
|
757
1111
|
}
|
|
758
1112
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
1113
|
+
function initIframeHelperFixer(config) {
|
|
1114
|
+
const fixer = new IframeHelperFixer(config);
|
|
1115
|
+
window.addEventListener('iframe-dimensions-applied', ((e) => {
|
|
1116
|
+
const ev = e;
|
|
1117
|
+
console.log('[IframeHelper] Iframe dimensions finalized:', ev.detail);
|
|
1118
|
+
}));
|
|
1119
|
+
window.addEventListener('iframe-navigation-blocked', ((e) => {
|
|
1120
|
+
const ev = e;
|
|
1121
|
+
console.warn('[IframeHelper] Iframe tried to navigate to:', ev.detail.url);
|
|
1122
|
+
}));
|
|
1123
|
+
window.addEventListener('iframe-form-submit', ((e) => {
|
|
1124
|
+
const ev = e;
|
|
1125
|
+
console.log('[IframeHelper] Iframe form submitted:', ev.detail.data);
|
|
1126
|
+
}));
|
|
1127
|
+
return fixer;
|
|
1128
|
+
}
|
|
763
1129
|
|
|
764
1130
|
const scrollToElementIfNeeded = (visualRef, rect, scale) => {
|
|
765
1131
|
if (!visualRef.current)
|
|
@@ -873,7 +1239,7 @@ const useHeatmapEffects = ({ isVisible, isElementSidebarOpen, setShouldShowCallo
|
|
|
873
1239
|
|
|
874
1240
|
const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
|
|
875
1241
|
const widthScale = useHeatmapVizStore((state) => state.scale);
|
|
876
|
-
const iframeHeight =
|
|
1242
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
877
1243
|
const heatmapWidth = useHeatmapConfigStore((state) => state.width);
|
|
878
1244
|
return useCallback((element) => {
|
|
879
1245
|
const hash = element?.hash;
|
|
@@ -921,6 +1287,109 @@ const debounce = (fn, delay) => {
|
|
|
921
1287
|
};
|
|
922
1288
|
};
|
|
923
1289
|
|
|
1290
|
+
// ===================== UTILITY FUNCTIONS =====================
|
|
1291
|
+
/**
|
|
1292
|
+
* Lấy bounding box tuyệt đối của element (relative to document)
|
|
1293
|
+
*/
|
|
1294
|
+
function getBoundingBox(element) {
|
|
1295
|
+
if (typeof element.getBoundingClientRect !== 'function') {
|
|
1296
|
+
return null;
|
|
1297
|
+
}
|
|
1298
|
+
const rect = element.getBoundingClientRect();
|
|
1299
|
+
// Lấy scroll offset (hỗ trợ cả cách cũ và mới)
|
|
1300
|
+
const scrollLeft = 'pageXOffset' in window ? window.pageXOffset : document.documentElement.scrollLeft;
|
|
1301
|
+
const scrollTop = 'pageYOffset' in window ? window.pageYOffset : document.documentElement.scrollTop;
|
|
1302
|
+
// Kiểm tra element có kích thước hợp lệ
|
|
1303
|
+
if (!rect || (rect.height === 0 && rect.width === 0)) {
|
|
1304
|
+
return null;
|
|
1305
|
+
}
|
|
1306
|
+
// Trả về vị trí tuyệt đối
|
|
1307
|
+
return {
|
|
1308
|
+
left: Math.floor(rect.left + scrollLeft),
|
|
1309
|
+
top: Math.floor(rect.top + scrollTop),
|
|
1310
|
+
width: Math.floor(rect.width),
|
|
1311
|
+
height: Math.floor(rect.height),
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
/**
|
|
1315
|
+
* Lấy tất cả elements tại tọa độ (x, y), hỗ trợ Shadow DOM
|
|
1316
|
+
*/
|
|
1317
|
+
function getElementsAtPoint(documentOrShadowRoot, x, y, filterFunction, visitedShadowRoots = new Set()) {
|
|
1318
|
+
// Lấy tất cả elements tại vị trí
|
|
1319
|
+
const elementsAtPoint = documentOrShadowRoot.elementsFromPoint(x, y);
|
|
1320
|
+
if (!filterFunction) {
|
|
1321
|
+
return elementsAtPoint;
|
|
1322
|
+
}
|
|
1323
|
+
// Tìm element đầu tiên match với filter
|
|
1324
|
+
const matchedElement = elementsAtPoint.find(filterFunction);
|
|
1325
|
+
// Nếu element có Shadow DOM và chưa visit -> đệ quy vào
|
|
1326
|
+
if (matchedElement?.shadowRoot && !visitedShadowRoots.has(matchedElement.shadowRoot)) {
|
|
1327
|
+
visitedShadowRoots.add(matchedElement.shadowRoot);
|
|
1328
|
+
return getElementsAtPoint(matchedElement.shadowRoot, x, y, filterFunction, visitedShadowRoots);
|
|
1329
|
+
}
|
|
1330
|
+
return elementsAtPoint;
|
|
1331
|
+
}
|
|
1332
|
+
// ===================== EXAMPLE USAGE =====================
|
|
1333
|
+
/*
|
|
1334
|
+
import { useRef, useState } from 'react';
|
|
1335
|
+
|
|
1336
|
+
function HeatmapComponent() {
|
|
1337
|
+
const heatmapWrapperRef = useRef<HTMLDivElement>(null);
|
|
1338
|
+
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
1339
|
+
const parentRef = useRef<HTMLDivElement>(null);
|
|
1340
|
+
|
|
1341
|
+
const [hoveredElement, setHoveredElement] = useState<HoveredElementInfo | null>(null);
|
|
1342
|
+
|
|
1343
|
+
const heatmapInfo = {
|
|
1344
|
+
width: 1920,
|
|
1345
|
+
elementMapInfo: {
|
|
1346
|
+
'hash123': {
|
|
1347
|
+
totalclicks: 45,
|
|
1348
|
+
selector: 'button.submit'
|
|
1349
|
+
}
|
|
1350
|
+
},
|
|
1351
|
+
sortedElements: [...]
|
|
1352
|
+
};
|
|
1353
|
+
|
|
1354
|
+
const { handleMouseMove } = useHeatmapMouseHandler({
|
|
1355
|
+
heatmapWrapperRef,
|
|
1356
|
+
iframeRef,
|
|
1357
|
+
parentRef,
|
|
1358
|
+
heatmapInfo,
|
|
1359
|
+
scaleRatio: 0.8, // 80% zoom
|
|
1360
|
+
onElementHover: (info) => {
|
|
1361
|
+
setHoveredElement(info);
|
|
1362
|
+
console.log('Hovered element:', info);
|
|
1363
|
+
}
|
|
1364
|
+
});
|
|
1365
|
+
|
|
1366
|
+
return (
|
|
1367
|
+
<div ref={parentRef}>
|
|
1368
|
+
<div
|
|
1369
|
+
ref={heatmapWrapperRef}
|
|
1370
|
+
onMouseMove={handleMouseMove}
|
|
1371
|
+
>
|
|
1372
|
+
<iframe ref={iframeRef} />
|
|
1373
|
+
|
|
1374
|
+
{hoveredElement && (
|
|
1375
|
+
<div className="tooltip" style={{
|
|
1376
|
+
position: 'absolute',
|
|
1377
|
+
left: hoveredElement.left,
|
|
1378
|
+
top: hoveredElement.top
|
|
1379
|
+
}}>
|
|
1380
|
+
Clicks: {hoveredElement.clicks}
|
|
1381
|
+
<br />
|
|
1382
|
+
Rank: #{hoveredElement.rank}
|
|
1383
|
+
<br />
|
|
1384
|
+
Selector: {hoveredElement.selector}
|
|
1385
|
+
</div>
|
|
1386
|
+
)}
|
|
1387
|
+
</div>
|
|
1388
|
+
</div>
|
|
1389
|
+
);
|
|
1390
|
+
}
|
|
1391
|
+
*/
|
|
1392
|
+
|
|
924
1393
|
const useHoveredElement = ({ iframeRef, getRect }) => {
|
|
925
1394
|
const hoveredElement = useHeatmapInteractionStore((state) => state.hoveredElement);
|
|
926
1395
|
const setHoveredElement = useHeatmapInteractionStore((state) => state.setHoveredElement);
|
|
@@ -942,7 +1411,7 @@ const useHoveredElement = ({ iframeRef, getRect }) => {
|
|
|
942
1411
|
const doc = iframe.contentDocument;
|
|
943
1412
|
const iframeRect = iframe.getBoundingClientRect();
|
|
944
1413
|
const { x, y } = convertViewportToIframeCoords(event.clientX, event.clientY, iframeRect, widthScale);
|
|
945
|
-
const targetElement = findTargetElement(doc, x, y);
|
|
1414
|
+
const targetElement = findTargetElement(doc, x, y, heatmapInfo);
|
|
946
1415
|
if (!targetElement || !isValidElement(targetElement, heatmapInfo)) {
|
|
947
1416
|
reset();
|
|
948
1417
|
return;
|
|
@@ -993,7 +1462,25 @@ const convertViewportToIframeCoords = (clientX, clientY, iframeRect, scale) => {
|
|
|
993
1462
|
}
|
|
994
1463
|
return { x, y };
|
|
995
1464
|
};
|
|
996
|
-
const findTargetElement = (doc, x, y) => {
|
|
1465
|
+
const findTargetElement = (doc, x, y, heatmapInfo) => {
|
|
1466
|
+
const HEATMAP_ELEMENT_ATTRIBUTE = 'data-clarity-hashalpha';
|
|
1467
|
+
const elementsAtPoint = getElementsAtPoint(doc, Math.round(x), Math.round(y), (element) => element.hasAttribute(HEATMAP_ELEMENT_ATTRIBUTE));
|
|
1468
|
+
let dataElement = null;
|
|
1469
|
+
for (let i = 0; i < elementsAtPoint.length; i++) {
|
|
1470
|
+
const element = elementsAtPoint[i];
|
|
1471
|
+
const elementHash = element.getAttribute(HEATMAP_ELEMENT_ATTRIBUTE);
|
|
1472
|
+
if (elementHash && heatmapInfo.elementMapInfo?.[elementHash]) {
|
|
1473
|
+
heatmapInfo.elementMapInfo[elementHash];
|
|
1474
|
+
const boundingBox = getBoundingBox(element);
|
|
1475
|
+
if (boundingBox) {
|
|
1476
|
+
dataElement = element;
|
|
1477
|
+
break;
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
if (!!dataElement) {
|
|
1482
|
+
return dataElement;
|
|
1483
|
+
}
|
|
997
1484
|
let targetElement = getElementAtPoint(doc, x, y);
|
|
998
1485
|
if (!targetElement) {
|
|
999
1486
|
targetElement = doc.elementFromPoint(x, y);
|
|
@@ -1017,9 +1504,9 @@ var MessageType;
|
|
|
1017
1504
|
MessageType["GX_DOM_TRACKING_PAYLOAD"] = "GX_DOM_TRACKING_PAYLOAD";
|
|
1018
1505
|
MessageType["CLARITY_READY"] = "CLARITY_READY";
|
|
1019
1506
|
})(MessageType || (MessageType = {}));
|
|
1020
|
-
function
|
|
1507
|
+
function useVizLiveIframeMsg(options = {}) {
|
|
1021
1508
|
const { trustedOrigins = [], onMessage } = options;
|
|
1022
|
-
const
|
|
1509
|
+
const addPayload = useHeatmapLiveStore((state) => state.addPayload);
|
|
1023
1510
|
const [isReady, setIsReady] = useState(false);
|
|
1024
1511
|
const iframeRef = useRef(null);
|
|
1025
1512
|
const isValidOrigin = useCallback((origin) => {
|
|
@@ -1045,9 +1532,9 @@ function useIframeMessage(options = {}) {
|
|
|
1045
1532
|
switch (message.type) {
|
|
1046
1533
|
case MessageType.GX_DOM_TRACKING_PAYLOAD:
|
|
1047
1534
|
if (message.payload) {
|
|
1048
|
-
const
|
|
1049
|
-
if (
|
|
1050
|
-
|
|
1535
|
+
const data = decodePayloads(message.payload);
|
|
1536
|
+
if (data) {
|
|
1537
|
+
addPayload(data);
|
|
1051
1538
|
}
|
|
1052
1539
|
}
|
|
1053
1540
|
break;
|
|
@@ -1062,27 +1549,19 @@ function useIframeMessage(options = {}) {
|
|
|
1062
1549
|
window.removeEventListener('message', handleMessage);
|
|
1063
1550
|
};
|
|
1064
1551
|
}, [handleMessage]);
|
|
1065
|
-
const clearPayloads = useCallback(() => {
|
|
1066
|
-
setPayloads([]);
|
|
1067
|
-
}, []);
|
|
1068
|
-
const reset = useCallback(() => {
|
|
1069
|
-
setPayloads([]);
|
|
1070
|
-
setIsReady(false);
|
|
1071
|
-
}, []);
|
|
1072
1552
|
return {
|
|
1073
1553
|
iframeRef,
|
|
1074
|
-
payloads,
|
|
1075
1554
|
isReady,
|
|
1076
|
-
clearPayloads,
|
|
1077
|
-
reset,
|
|
1078
1555
|
};
|
|
1079
1556
|
}
|
|
1080
|
-
|
|
1557
|
+
|
|
1558
|
+
function useVizLiveRender() {
|
|
1081
1559
|
const wrapperHeight = useHeatmapLiveStore((state) => state.wrapperHeight);
|
|
1560
|
+
const setIframeHeight = useHeatmapLiveStore((state) => state.setIframeHeight);
|
|
1082
1561
|
const contentWidth = useHeatmapConfigStore((state) => state.width);
|
|
1083
|
-
const setIframeHeight = useHeatmapVizStore((state) => state.setIframeHeight);
|
|
1084
1562
|
const htmlContent = useHeatmapLiveStore((state) => state.htmlContent);
|
|
1085
|
-
const
|
|
1563
|
+
const setIsRenderViz = useHeatmapVizStore((state) => state.setIsRenderViz);
|
|
1564
|
+
const { iframeRef, isReady } = useVizLiveIframeMsg();
|
|
1086
1565
|
useEffect(() => {
|
|
1087
1566
|
if (!htmlContent || !iframeRef.current)
|
|
1088
1567
|
return;
|
|
@@ -1102,50 +1581,50 @@ function useIframeRender() {
|
|
|
1102
1581
|
const iframe = iframeRef.current;
|
|
1103
1582
|
if (!iframe || !htmlContent)
|
|
1104
1583
|
return;
|
|
1105
|
-
|
|
1106
|
-
|
|
1584
|
+
setIsRenderViz(false);
|
|
1585
|
+
reset(iframe, { width: contentWidth, height: wrapperHeight }, (height) => {
|
|
1586
|
+
height && setIframeHeight(height);
|
|
1587
|
+
setIsRenderViz(true);
|
|
1107
1588
|
});
|
|
1108
1589
|
}, [isReady, contentWidth, wrapperHeight]);
|
|
1109
1590
|
return {
|
|
1110
1591
|
iframeRef,
|
|
1111
|
-
payloads,
|
|
1112
|
-
isReady,
|
|
1113
1592
|
};
|
|
1114
1593
|
}
|
|
1115
|
-
function reset
|
|
1116
|
-
const
|
|
1117
|
-
targetWidth:
|
|
1118
|
-
targetHeight:
|
|
1594
|
+
function reset(iframe, rect, onSuccess) {
|
|
1595
|
+
const fixer = initIframeHelperFixer({
|
|
1596
|
+
targetWidth: rect.width,
|
|
1597
|
+
targetHeight: rect.height,
|
|
1119
1598
|
iframe: iframe,
|
|
1120
1599
|
onSuccess: (data) => {
|
|
1121
|
-
onSuccess(data.height);
|
|
1122
1600
|
iframe.height = `${data.height}px`;
|
|
1601
|
+
onSuccess(data.height);
|
|
1123
1602
|
},
|
|
1124
1603
|
});
|
|
1125
|
-
|
|
1126
|
-
|
|
1604
|
+
// fixer.recalculate();
|
|
1605
|
+
fixer.enableNavigationBlocking();
|
|
1127
1606
|
}
|
|
1128
1607
|
|
|
1608
|
+
let visualizer = new Visualizer();
|
|
1129
1609
|
const useHeatmapRender = () => {
|
|
1130
1610
|
const data = useHeatmapDataStore((state) => state.data);
|
|
1131
|
-
const setVizRef =
|
|
1611
|
+
const setVizRef = useHeatmapSingleStore((state) => state.setVizRef);
|
|
1132
1612
|
const setIsRenderViz = useHeatmapVizStore((state) => state.setIsRenderViz);
|
|
1133
|
-
const setIframeHeight =
|
|
1613
|
+
const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
|
|
1134
1614
|
const iframeRef = useRef(null);
|
|
1135
1615
|
const renderHeatmap = useCallback(async (payloads) => {
|
|
1136
1616
|
if (!payloads || payloads.length === 0)
|
|
1137
1617
|
return;
|
|
1138
1618
|
setIsRenderViz(false);
|
|
1139
|
-
const visualizer = new Visualizer();
|
|
1140
1619
|
const iframe = iframeRef.current;
|
|
1141
1620
|
if (!iframe?.contentWindow)
|
|
1142
1621
|
return;
|
|
1143
1622
|
await visualizer.html(payloads, iframe.contentWindow);
|
|
1144
|
-
|
|
1623
|
+
initIframe(iframe, payloads, (height) => {
|
|
1145
1624
|
height && setIframeHeight(height);
|
|
1146
1625
|
setIsRenderViz(true);
|
|
1626
|
+
setVizRef(visualizer);
|
|
1147
1627
|
});
|
|
1148
|
-
setVizRef(visualizer);
|
|
1149
1628
|
}, []);
|
|
1150
1629
|
useEffect(() => {
|
|
1151
1630
|
if (!data || data.length === 0)
|
|
@@ -1159,21 +1638,20 @@ const useHeatmapRender = () => {
|
|
|
1159
1638
|
iframeRef,
|
|
1160
1639
|
};
|
|
1161
1640
|
};
|
|
1162
|
-
function
|
|
1641
|
+
function initIframe(iframe, payloads, onSuccess) {
|
|
1163
1642
|
const { size } = findLastSizeOfDom(payloads);
|
|
1164
1643
|
const docWidth = size.width ?? 0;
|
|
1165
1644
|
const docHeight = size.height ?? 0;
|
|
1166
|
-
|
|
1645
|
+
initIframeHelperFixer({
|
|
1167
1646
|
targetWidth: docWidth,
|
|
1168
1647
|
targetHeight: docHeight,
|
|
1169
1648
|
iframe: iframe,
|
|
1170
1649
|
onSuccess: (data) => {
|
|
1171
|
-
onSuccess(data.height);
|
|
1172
1650
|
iframe.height = `${data.height}px`;
|
|
1651
|
+
onSuccess(data.height);
|
|
1173
1652
|
},
|
|
1174
1653
|
});
|
|
1175
|
-
|
|
1176
|
-
return iframe;
|
|
1654
|
+
// fixer.recalculate();
|
|
1177
1655
|
}
|
|
1178
1656
|
|
|
1179
1657
|
function isMobileDevice(userAgent) {
|
|
@@ -1358,30 +1836,64 @@ const useContentDimensions = ({ iframeRef, }) => {
|
|
|
1358
1836
|
return { contentWidth };
|
|
1359
1837
|
};
|
|
1360
1838
|
|
|
1361
|
-
const
|
|
1839
|
+
const useObserveIframeHeight = (props) => {
|
|
1362
1840
|
const { iframeRef, setIframeHeight } = props;
|
|
1363
1841
|
const isRenderViz = useHeatmapVizStore((state) => state.isRenderViz);
|
|
1364
1842
|
const resizeObserverRef = useRef(null);
|
|
1365
1843
|
const mutationObserverRef = useRef(null);
|
|
1844
|
+
const debounceTimerRef = useRef(null);
|
|
1845
|
+
const lastHeightRef = useRef(0);
|
|
1846
|
+
const animationFrameRef = useRef(null);
|
|
1366
1847
|
const updateIframeHeight = useCallback(() => {
|
|
1367
1848
|
const iframe = iframeRef.current;
|
|
1368
|
-
if (!iframe)
|
|
1849
|
+
if (!iframe || !setIframeHeight)
|
|
1369
1850
|
return;
|
|
1370
1851
|
try {
|
|
1371
1852
|
const iframeDocument = iframe.contentDocument;
|
|
1372
1853
|
const iframeBody = iframeDocument?.body;
|
|
1373
|
-
|
|
1854
|
+
const iframeDocumentElement = iframeDocument?.documentElement;
|
|
1855
|
+
if (!iframeBody || !iframeDocumentElement)
|
|
1374
1856
|
return;
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1857
|
+
iframe.style.height = 'auto';
|
|
1858
|
+
requestAnimationFrame(() => {
|
|
1859
|
+
const bodyHeight = Math.max(iframeBody.scrollHeight, iframeBody.offsetHeight, iframeBody.clientHeight);
|
|
1860
|
+
const documentHeight = Math.max(iframeDocumentElement.scrollHeight, iframeDocumentElement.offsetHeight, iframeDocumentElement.clientHeight);
|
|
1861
|
+
const actualHeight = Math.max(bodyHeight, documentHeight);
|
|
1862
|
+
if (actualHeight > 0) {
|
|
1863
|
+
lastHeightRef.current = actualHeight;
|
|
1864
|
+
iframe.height = `${actualHeight}px`;
|
|
1865
|
+
iframe.style.height = `${actualHeight}px`;
|
|
1866
|
+
setIframeHeight(actualHeight);
|
|
1867
|
+
}
|
|
1868
|
+
});
|
|
1380
1869
|
}
|
|
1381
1870
|
catch (error) {
|
|
1382
1871
|
console.warn('Cannot measure iframe content:', error);
|
|
1383
1872
|
}
|
|
1384
1873
|
}, [iframeRef, setIframeHeight]);
|
|
1874
|
+
const debouncedUpdate = useCallback(() => {
|
|
1875
|
+
// Cancel pending updates
|
|
1876
|
+
if (debounceTimerRef.current) {
|
|
1877
|
+
clearTimeout(debounceTimerRef.current);
|
|
1878
|
+
}
|
|
1879
|
+
if (animationFrameRef.current) {
|
|
1880
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
1881
|
+
}
|
|
1882
|
+
debounceTimerRef.current = setTimeout(() => {
|
|
1883
|
+
animationFrameRef.current = requestAnimationFrame(() => {
|
|
1884
|
+
updateIframeHeight();
|
|
1885
|
+
});
|
|
1886
|
+
}, 50);
|
|
1887
|
+
}, [updateIframeHeight]);
|
|
1888
|
+
// Immediate update không debounce (cho ResizeObserver)
|
|
1889
|
+
const immediateUpdate = useCallback(() => {
|
|
1890
|
+
if (animationFrameRef.current) {
|
|
1891
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
1892
|
+
}
|
|
1893
|
+
animationFrameRef.current = requestAnimationFrame(() => {
|
|
1894
|
+
updateIframeHeight();
|
|
1895
|
+
});
|
|
1896
|
+
}, [updateIframeHeight]);
|
|
1385
1897
|
useEffect(() => {
|
|
1386
1898
|
const iframe = iframeRef.current;
|
|
1387
1899
|
if (!iframe || !isRenderViz)
|
|
@@ -1399,22 +1911,24 @@ const useIframeHeight = (props) => {
|
|
|
1399
1911
|
if (mutationObserverRef.current) {
|
|
1400
1912
|
mutationObserverRef.current.disconnect();
|
|
1401
1913
|
}
|
|
1402
|
-
// ResizeObserver for size changes
|
|
1403
1914
|
if (typeof window.ResizeObserver !== 'undefined') {
|
|
1404
|
-
resizeObserverRef.current = new ResizeObserver(
|
|
1915
|
+
resizeObserverRef.current = new ResizeObserver(immediateUpdate);
|
|
1405
1916
|
resizeObserverRef.current.observe(iframeBody);
|
|
1917
|
+
const iframeDocumentElement = iframeDocument?.documentElement;
|
|
1918
|
+
if (iframeDocumentElement) {
|
|
1919
|
+
resizeObserverRef.current.observe(iframeDocumentElement);
|
|
1920
|
+
}
|
|
1406
1921
|
}
|
|
1407
|
-
// MutationObserver for DOM changes
|
|
1408
1922
|
if (typeof window.MutationObserver !== 'undefined') {
|
|
1409
|
-
mutationObserverRef.current = new MutationObserver(
|
|
1923
|
+
mutationObserverRef.current = new MutationObserver(immediateUpdate);
|
|
1410
1924
|
mutationObserverRef.current.observe(iframeBody, {
|
|
1411
1925
|
childList: true,
|
|
1412
1926
|
subtree: true,
|
|
1413
1927
|
attributes: true,
|
|
1414
|
-
|
|
1928
|
+
attributeFilter: ['style', 'class'],
|
|
1929
|
+
characterData: false,
|
|
1415
1930
|
});
|
|
1416
1931
|
}
|
|
1417
|
-
// Initial measurement
|
|
1418
1932
|
updateIframeHeight();
|
|
1419
1933
|
}
|
|
1420
1934
|
catch (error) {
|
|
@@ -1428,15 +1942,23 @@ const useIframeHeight = (props) => {
|
|
|
1428
1942
|
iframe.addEventListener('load', setupObservers, { once: true });
|
|
1429
1943
|
}
|
|
1430
1944
|
return () => {
|
|
1945
|
+
// Cleanup observers
|
|
1431
1946
|
if (resizeObserverRef.current) {
|
|
1432
1947
|
resizeObserverRef.current.disconnect();
|
|
1433
1948
|
}
|
|
1434
1949
|
if (mutationObserverRef.current) {
|
|
1435
1950
|
mutationObserverRef.current.disconnect();
|
|
1436
1951
|
}
|
|
1952
|
+
// Cleanup timers
|
|
1953
|
+
if (debounceTimerRef.current) {
|
|
1954
|
+
clearTimeout(debounceTimerRef.current);
|
|
1955
|
+
}
|
|
1956
|
+
if (animationFrameRef.current) {
|
|
1957
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
1958
|
+
}
|
|
1437
1959
|
iframe.removeEventListener('load', setupObservers);
|
|
1438
1960
|
};
|
|
1439
|
-
}, [iframeRef, isRenderViz, updateIframeHeight]);
|
|
1961
|
+
}, [iframeRef, isRenderViz, updateIframeHeight, debouncedUpdate, immediateUpdate]);
|
|
1440
1962
|
return {};
|
|
1441
1963
|
};
|
|
1442
1964
|
|
|
@@ -1482,16 +2004,18 @@ const useHeatmapScale = (props) => {
|
|
|
1482
2004
|
// 2. Get content dimensions from config
|
|
1483
2005
|
const { contentWidth } = useContentDimensions({ iframeRef });
|
|
1484
2006
|
// 3. Observe iframe height (now reacts to width changes)
|
|
1485
|
-
|
|
2007
|
+
useObserveIframeHeight({ iframeRef, setIframeHeight });
|
|
1486
2008
|
// 4. Calculate scale
|
|
1487
2009
|
const { scale } = useScaleCalculation({ containerWidth, contentWidth });
|
|
1488
2010
|
// 5. Setup scroll sync
|
|
1489
2011
|
const { handleScroll } = useScrollSync({ iframeRef });
|
|
2012
|
+
const scaledHeight = iframeHeight * scale;
|
|
2013
|
+
const scaledWidth = contentWidth * scale;
|
|
1490
2014
|
return {
|
|
1491
2015
|
containerWidth,
|
|
1492
2016
|
containerHeight,
|
|
1493
|
-
scaledWidth
|
|
1494
|
-
scaledHeight
|
|
2017
|
+
scaledWidth,
|
|
2018
|
+
scaledHeight,
|
|
1495
2019
|
handleScroll,
|
|
1496
2020
|
};
|
|
1497
2021
|
};
|
|
@@ -1565,6 +2089,135 @@ const useWrapperRefHeight = (props) => {
|
|
|
1565
2089
|
return {};
|
|
1566
2090
|
};
|
|
1567
2091
|
|
|
2092
|
+
const useZonePositions = (options) => {
|
|
2093
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
2094
|
+
const getZonePosition = useCallback((zone) => {
|
|
2095
|
+
if (!iframeHeight) {
|
|
2096
|
+
return null;
|
|
2097
|
+
}
|
|
2098
|
+
const startYPx = (zone.startY / 100) * iframeHeight;
|
|
2099
|
+
const heightPx = ((zone.endY - zone.startY) / 100) * iframeHeight;
|
|
2100
|
+
return {
|
|
2101
|
+
top: startYPx,
|
|
2102
|
+
height: heightPx,
|
|
2103
|
+
};
|
|
2104
|
+
}, [iframeHeight]);
|
|
2105
|
+
return {
|
|
2106
|
+
getZonePosition,
|
|
2107
|
+
};
|
|
2108
|
+
};
|
|
2109
|
+
|
|
2110
|
+
const SCROLL_GRADIENT_COLORS = [
|
|
2111
|
+
[255, 0, 0], // Red
|
|
2112
|
+
[255, 255, 0], // Yellow
|
|
2113
|
+
[0, 255, 0], // Green
|
|
2114
|
+
];
|
|
2115
|
+
const useScrollmapZones = (options) => {
|
|
2116
|
+
const { mode = 'basic', enabled = true, iframeRef, wrapperRef } = options;
|
|
2117
|
+
const [isReady, setIsReady] = useState(false);
|
|
2118
|
+
const [zones, setZones] = useState([]);
|
|
2119
|
+
const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
|
|
2120
|
+
const scrollMapInfo = useHeatmapDataStore((state) => state.dataInfo?.scrollMapInfo);
|
|
2121
|
+
const { getZonePosition } = useZonePositions();
|
|
2122
|
+
const maxUsers = useMemo(() => {
|
|
2123
|
+
if (!scrollmap || scrollmap.length === 0)
|
|
2124
|
+
return 100;
|
|
2125
|
+
return Math.max(...scrollmap.map((d) => d.percUsers));
|
|
2126
|
+
}, [scrollmap]);
|
|
2127
|
+
const createZones = useCallback((data) => {
|
|
2128
|
+
if (mode === 'basic') {
|
|
2129
|
+
const breakpoints = [0, 25, 50, 75, 100];
|
|
2130
|
+
const zones = [];
|
|
2131
|
+
for (let i = 0; i < breakpoints.length - 1; i++) {
|
|
2132
|
+
const startY = breakpoints[i];
|
|
2133
|
+
const endY = breakpoints[i + 1];
|
|
2134
|
+
const pointsInRange = data.filter((d) => d.scrollReachY >= startY && d.scrollReachY < endY);
|
|
2135
|
+
const avgUsers = pointsInRange.length > 0
|
|
2136
|
+
? pointsInRange.reduce((sum, p) => sum + p.percUsers, 0) / pointsInRange.length
|
|
2137
|
+
: 0;
|
|
2138
|
+
zones.push({
|
|
2139
|
+
id: `zone_${startY}_${endY}`,
|
|
2140
|
+
startY,
|
|
2141
|
+
endY,
|
|
2142
|
+
percUsers: avgUsers,
|
|
2143
|
+
label: `${startY}% - ${endY}%`,
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2146
|
+
return zones;
|
|
2147
|
+
}
|
|
2148
|
+
else {
|
|
2149
|
+
// Metrics mode: 20 zones (5% intervals)
|
|
2150
|
+
const zones = [];
|
|
2151
|
+
const interval = 5;
|
|
2152
|
+
// Prepare metrics map
|
|
2153
|
+
let metricsMap;
|
|
2154
|
+
if (scrollMapInfo && Object.keys(scrollMapInfo).length > 0) {
|
|
2155
|
+
metricsMap = new Map();
|
|
2156
|
+
Object.entries(scrollMapInfo).forEach(([key, value]) => {
|
|
2157
|
+
metricsMap.set(Number(key), value);
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2160
|
+
for (let i = 0; i < 100; i += interval) {
|
|
2161
|
+
const startY = i;
|
|
2162
|
+
const endY = i + interval;
|
|
2163
|
+
const point = data.find((d) => d.scrollReachY === startY) || {
|
|
2164
|
+
scrollReachY: startY,
|
|
2165
|
+
cumulativeSum: 0,
|
|
2166
|
+
percUsers: 0,
|
|
2167
|
+
};
|
|
2168
|
+
const metrics = metricsMap?.get(startY);
|
|
2169
|
+
zones.push({
|
|
2170
|
+
id: `zone_${startY}_${endY}`,
|
|
2171
|
+
startY,
|
|
2172
|
+
endY,
|
|
2173
|
+
percUsers: point.percUsers,
|
|
2174
|
+
metrics,
|
|
2175
|
+
label: `${startY}% - ${endY}%`,
|
|
2176
|
+
});
|
|
2177
|
+
}
|
|
2178
|
+
return zones;
|
|
2179
|
+
}
|
|
2180
|
+
}, [mode, scrollMapInfo]);
|
|
2181
|
+
/**
|
|
2182
|
+
* Initialize zones
|
|
2183
|
+
*/
|
|
2184
|
+
useEffect(() => {
|
|
2185
|
+
if (!enabled || !scrollmap || scrollmap.length === 0) {
|
|
2186
|
+
setIsReady(false);
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
try {
|
|
2190
|
+
const newZones = createZones(scrollmap);
|
|
2191
|
+
setZones(newZones);
|
|
2192
|
+
setIsReady(true);
|
|
2193
|
+
console.log(`[useScrollmap] Created ${newZones.length} zones in ${mode} mode`);
|
|
2194
|
+
}
|
|
2195
|
+
catch (error) {
|
|
2196
|
+
console.error('[useScrollmap] Error:', error);
|
|
2197
|
+
setIsReady(false);
|
|
2198
|
+
}
|
|
2199
|
+
}, [enabled, scrollmap, mode, createZones]);
|
|
2200
|
+
return {
|
|
2201
|
+
zones,
|
|
2202
|
+
isReady,
|
|
2203
|
+
maxUsers,
|
|
2204
|
+
getZonePosition,
|
|
2205
|
+
};
|
|
2206
|
+
};
|
|
2207
|
+
/**
|
|
2208
|
+
* Get scroll gradient color for minimap
|
|
2209
|
+
*/
|
|
2210
|
+
const getScrollGradientColor = (normalized) => {
|
|
2211
|
+
const idx = Math.min(Math.floor(normalized * 2), 1);
|
|
2212
|
+
const [r1, g1, b1] = SCROLL_GRADIENT_COLORS[idx];
|
|
2213
|
+
const [r2, g2, b2] = SCROLL_GRADIENT_COLORS[idx + 1];
|
|
2214
|
+
const localPercent = (normalized * 2) % 1;
|
|
2215
|
+
const r = Math.round(r1 + (r2 - r1) * localPercent);
|
|
2216
|
+
const g = Math.round(g1 + (g2 - g1) * localPercent);
|
|
2217
|
+
const b = Math.round(b1 + (b2 - b1) * localPercent);
|
|
2218
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
2219
|
+
};
|
|
2220
|
+
|
|
1568
2221
|
const BoxStack = forwardRef(({ children, ...props }, ref) => {
|
|
1569
2222
|
const id = props.id;
|
|
1570
2223
|
const flexDirection = props.flexDirection;
|
|
@@ -1651,35 +2304,57 @@ const VizContainer = ({ children, setWrapperHeight }) => {
|
|
|
1651
2304
|
const useClickmap = () => {
|
|
1652
2305
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
1653
2306
|
const clickmap = useHeatmapDataStore((state) => state.clickmap);
|
|
1654
|
-
const vizRef =
|
|
1655
|
-
|
|
2307
|
+
const vizRef = useHeatmapSingleStore((state) => state.vizRef);
|
|
2308
|
+
const start = useCallback(() => {
|
|
1656
2309
|
if (isInitialized)
|
|
1657
2310
|
return;
|
|
1658
2311
|
if (!vizRef || !clickmap || clickmap.length === 0)
|
|
1659
2312
|
return;
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
2313
|
+
try {
|
|
2314
|
+
vizRef?.clearmap?.();
|
|
2315
|
+
vizRef?.clickmap?.(clickmap);
|
|
2316
|
+
setIsInitialized(true);
|
|
2317
|
+
}
|
|
2318
|
+
catch (error) {
|
|
2319
|
+
console.error(`🚀 🐥 ~ useClickmap ~ error:`, error);
|
|
2320
|
+
}
|
|
1663
2321
|
}, [vizRef, clickmap]);
|
|
1664
|
-
return {};
|
|
2322
|
+
return { start };
|
|
1665
2323
|
};
|
|
1666
2324
|
|
|
1667
2325
|
const useScrollmap = () => {
|
|
1668
|
-
|
|
1669
|
-
|
|
2326
|
+
const vizRef = useHeatmapSingleStore((state) => state.vizRef);
|
|
2327
|
+
const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
|
|
2328
|
+
const start = useCallback(() => {
|
|
2329
|
+
// if (isInitialized) return;
|
|
2330
|
+
if (!vizRef || !scrollmap || scrollmap.length === 0)
|
|
2331
|
+
return;
|
|
2332
|
+
try {
|
|
2333
|
+
vizRef?.clearmap?.();
|
|
2334
|
+
vizRef?.scrollmap?.(scrollmap);
|
|
2335
|
+
// setIsInitialized(true);
|
|
2336
|
+
}
|
|
2337
|
+
catch (error) {
|
|
2338
|
+
console.error(`🚀 🐥 ~ useScrollmap ~ error:`, error);
|
|
2339
|
+
}
|
|
2340
|
+
}, [vizRef, scrollmap]);
|
|
2341
|
+
return { start };
|
|
1670
2342
|
};
|
|
1671
2343
|
|
|
1672
|
-
const
|
|
2344
|
+
const useHeatmapCanvas = ({ iframeRef, }) => {
|
|
1673
2345
|
const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
|
|
1674
|
-
const
|
|
2346
|
+
const { start: startClickmap } = useClickmap();
|
|
2347
|
+
const { start: startScrollmap } = useScrollmap();
|
|
2348
|
+
useEffect(() => {
|
|
1675
2349
|
switch (heatmapType) {
|
|
1676
2350
|
case IHeatmapType.Click:
|
|
1677
|
-
|
|
2351
|
+
startClickmap();
|
|
2352
|
+
break;
|
|
1678
2353
|
case IHeatmapType.Scroll:
|
|
1679
|
-
|
|
2354
|
+
startScrollmap();
|
|
2355
|
+
break;
|
|
1680
2356
|
}
|
|
1681
|
-
}, [heatmapType]);
|
|
1682
|
-
return heatmapRender?.();
|
|
2357
|
+
}, [heatmapType, startClickmap, startScrollmap]);
|
|
1683
2358
|
};
|
|
1684
2359
|
|
|
1685
2360
|
const CLICKED_ELEMENT_ID = 'gx-hm-clicked-element';
|
|
@@ -1742,7 +2417,7 @@ const ElementCallout = (props) => {
|
|
|
1742
2417
|
window.removeEventListener('resize', handleUpdate);
|
|
1743
2418
|
visualRef?.current?.removeEventListener('scroll', handleUpdate);
|
|
1744
2419
|
};
|
|
1745
|
-
}, [target, visualRef, hozOffset, alignment]);
|
|
2420
|
+
}, [element, target, visualRef, hozOffset, alignment]);
|
|
1746
2421
|
const calloutContent = (jsx("div", { ref: calloutRef, className: `clarity-callout clarity-callout--${position.placement} clarity-callout--align-${position.horizontalAlign}`, style: {
|
|
1747
2422
|
position: 'fixed',
|
|
1748
2423
|
top: position.top,
|
|
@@ -1807,8 +2482,8 @@ const ELEMENT_CALLOUT = {
|
|
|
1807
2482
|
alignment: 'left',
|
|
1808
2483
|
};
|
|
1809
2484
|
const HeatmapElements = (props) => {
|
|
1810
|
-
const
|
|
1811
|
-
const { iframeRef, wrapperRef, visualRef, visualizer, iframeDimensions, isElementSidebarOpen, isVisible = true, areDefaultRanksHidden, isSecondary,
|
|
2485
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
2486
|
+
const { iframeRef, wrapperRef, visualRef, visualizer, iframeDimensions, isElementSidebarOpen, isVisible = true, areDefaultRanksHidden, isSecondary, } = props;
|
|
1812
2487
|
const getRect = useHeatmapElementPosition({
|
|
1813
2488
|
iframeRef,
|
|
1814
2489
|
wrapperRef,
|
|
@@ -1837,14 +2512,21 @@ const HeatmapElements = (props) => {
|
|
|
1837
2512
|
});
|
|
1838
2513
|
if (!isVisible)
|
|
1839
2514
|
return null;
|
|
1840
|
-
return (jsxs("div", { onMouseMove:
|
|
2515
|
+
return (jsxs("div", { onMouseMove: (event) => {
|
|
2516
|
+
handleMouseMove(event);
|
|
2517
|
+
// handleMouseMove2(event as any);
|
|
2518
|
+
}, onMouseLeave: handleMouseLeave, className: "gx-hm-elements", style: { ...iframeDimensions, height: `${iframeHeight}px` }, children: [jsx(ElementMissing, { show: showMissingElement }), jsx(DefaultRankBadges, { getRect: getRect, hidden: areDefaultRanksHidden }), jsx(ElementOverlay, { type: "clicked", element: clickedElement, isSecondary: isSecondary }), jsx(ElementOverlay, { type: "hovered", element: hoveredElement, isSecondary: isSecondary, onClick: handleClick }), hoveredElement?.hash !== clickedElement?.hash && hoveredElement && (jsx(ElementCallout, { element: hoveredElement, target: `#${HOVERED_ELEMENT_ID}`, visualRef: visualRef, ...ELEMENT_CALLOUT })), shouldShowCallout && clickedElement && (jsx(ElementCallout, { element: clickedElement, target: `#${CLICKED_ELEMENT_ID}`, visualRef: visualRef, ...ELEMENT_CALLOUT }))] }));
|
|
1841
2519
|
};
|
|
1842
2520
|
|
|
1843
2521
|
const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
|
|
1844
2522
|
const heatmapInfo = useHeatmapDataStore((state) => state.dataInfo);
|
|
1845
|
-
const contentWidth =
|
|
2523
|
+
const contentWidth = useHeatmapConfigStore((state) => state.width);
|
|
2524
|
+
const vizRef = useHeatmapSingleStore((state) => state.vizRef);
|
|
1846
2525
|
const visualizer = {
|
|
1847
2526
|
get: (hash) => {
|
|
2527
|
+
if (vizRef) {
|
|
2528
|
+
return vizRef.get(hash);
|
|
2529
|
+
}
|
|
1848
2530
|
const doc = iframeRef.current?.contentDocument;
|
|
1849
2531
|
if (!doc)
|
|
1850
2532
|
return null;
|
|
@@ -1870,6 +2552,293 @@ const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
|
|
|
1870
2552
|
} }));
|
|
1871
2553
|
};
|
|
1872
2554
|
|
|
2555
|
+
const AverageFoldLine = ({ iframeRef, wrapperRef }) => {
|
|
2556
|
+
const averageFold = useHeatmapDataStore((state) => state.dataInfo?.averageFold || 50);
|
|
2557
|
+
const { getZonePosition } = useZonePositions();
|
|
2558
|
+
const position = getZonePosition({
|
|
2559
|
+
startY: averageFold,
|
|
2560
|
+
endY: averageFold,
|
|
2561
|
+
});
|
|
2562
|
+
if (!position)
|
|
2563
|
+
return null;
|
|
2564
|
+
return (jsx("div", { style: {
|
|
2565
|
+
position: 'absolute',
|
|
2566
|
+
top: `${position.top}px`,
|
|
2567
|
+
left: 0,
|
|
2568
|
+
width: '100%',
|
|
2569
|
+
height: '2px',
|
|
2570
|
+
backgroundColor: '#0078D4',
|
|
2571
|
+
pointerEvents: 'none',
|
|
2572
|
+
zIndex: 2,
|
|
2573
|
+
boxShadow: '0 0 4px rgba(0,120,212,0.5)',
|
|
2574
|
+
display: 'flex',
|
|
2575
|
+
alignItems: 'center',
|
|
2576
|
+
}, children: jsxs("div", { style: {
|
|
2577
|
+
position: 'absolute',
|
|
2578
|
+
padding: '8px',
|
|
2579
|
+
backgroundColor: 'rgba(0, 120, 212, 0.9)',
|
|
2580
|
+
color: 'white',
|
|
2581
|
+
fontSize: '16px',
|
|
2582
|
+
fontWeight: 600,
|
|
2583
|
+
borderRadius: '4px',
|
|
2584
|
+
whiteSpace: 'nowrap',
|
|
2585
|
+
left: '12px',
|
|
2586
|
+
minWidth: '120px',
|
|
2587
|
+
textAlign: 'center',
|
|
2588
|
+
}, children: ["Average fold - ", averageFold.toFixed(0), "%"] }) }));
|
|
2589
|
+
};
|
|
2590
|
+
|
|
2591
|
+
const ScrollmapMarker = ({ iframeRef, wrapperRef }) => {
|
|
2592
|
+
const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
|
|
2593
|
+
const scrollType = useHeatmapConfigStore((state) => state.scrollType);
|
|
2594
|
+
const { getZonePosition } = useZonePositions();
|
|
2595
|
+
if (!scrollmap || scrollmap.length === 0)
|
|
2596
|
+
return null;
|
|
2597
|
+
const findScrollPositionForUserPercent = (targetPercent) => {
|
|
2598
|
+
for (let i = 0; i < scrollmap.length; i++) {
|
|
2599
|
+
if (scrollmap[i].percUsers <= targetPercent) {
|
|
2600
|
+
if (i > 0) {
|
|
2601
|
+
return scrollmap[i - 1].scrollReachY;
|
|
2602
|
+
}
|
|
2603
|
+
return scrollmap[i].scrollReachY;
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
return scrollmap[scrollmap.length - 1]?.scrollReachY || null;
|
|
2607
|
+
};
|
|
2608
|
+
const boundaries = [
|
|
2609
|
+
{ percent: 75, label: '75%', color: '#10B981' },
|
|
2610
|
+
{ percent: 50, label: '50%', color: '#F59E0B' },
|
|
2611
|
+
{ percent: 25, label: '25%', color: '#EF4444' },
|
|
2612
|
+
{ percent: 5, label: '5%', color: '#8B5CF6' },
|
|
2613
|
+
];
|
|
2614
|
+
const isScrollDepth = scrollType === IScrollType.Depth;
|
|
2615
|
+
if (!isScrollDepth)
|
|
2616
|
+
return null;
|
|
2617
|
+
return (jsx(Fragment, { children: boundaries.map((boundary) => {
|
|
2618
|
+
const scrollY = findScrollPositionForUserPercent(boundary.percent);
|
|
2619
|
+
if (scrollY === null)
|
|
2620
|
+
return null;
|
|
2621
|
+
const position = getZonePosition({
|
|
2622
|
+
startY: scrollY,
|
|
2623
|
+
endY: scrollY,
|
|
2624
|
+
});
|
|
2625
|
+
if (!position)
|
|
2626
|
+
return null;
|
|
2627
|
+
return (jsx("div", { className: `marker-boundary-line-${boundary.percent}`, style: {
|
|
2628
|
+
position: 'absolute',
|
|
2629
|
+
top: `${position.top}px`,
|
|
2630
|
+
left: 0,
|
|
2631
|
+
transformOrigin: 'left center',
|
|
2632
|
+
width: '100%',
|
|
2633
|
+
height: '0px',
|
|
2634
|
+
// borderBottom: `2px dashed #323130`,
|
|
2635
|
+
borderBottom: `2px solid ${boundary.color}`,
|
|
2636
|
+
// background: 'repeating-linear-gradient(90deg, #323130, transparent 2px 3px)',
|
|
2637
|
+
zIndex: 1,
|
|
2638
|
+
display: 'flex',
|
|
2639
|
+
alignItems: 'center',
|
|
2640
|
+
}, children: jsx("div", { style: {
|
|
2641
|
+
position: 'absolute',
|
|
2642
|
+
padding: '8px',
|
|
2643
|
+
backgroundColor: boundary.color,
|
|
2644
|
+
color: 'white',
|
|
2645
|
+
fontSize: '16px',
|
|
2646
|
+
fontWeight: 600,
|
|
2647
|
+
borderRadius: '4px',
|
|
2648
|
+
whiteSpace: 'nowrap',
|
|
2649
|
+
left: '12px',
|
|
2650
|
+
minWidth: '120px',
|
|
2651
|
+
textAlign: 'center',
|
|
2652
|
+
// textAlign: 'center',
|
|
2653
|
+
// padding: '8px',
|
|
2654
|
+
// paddingInline: '8px',
|
|
2655
|
+
// fontSize: '16px',
|
|
2656
|
+
// background: '#fff',
|
|
2657
|
+
// width: 'auto',
|
|
2658
|
+
// borderRadius: '4px',
|
|
2659
|
+
// position: 'absolute',
|
|
2660
|
+
// left: '12px',
|
|
2661
|
+
// minWidth: '120px',
|
|
2662
|
+
}, children: boundary.label }) }, boundary.label));
|
|
2663
|
+
}) }));
|
|
2664
|
+
};
|
|
2665
|
+
|
|
2666
|
+
const ScrollMapMinimap = ({ zones, maxUsers }) => {
|
|
2667
|
+
const showMinimap = useHeatmapVizScrollmapStore((state) => state.showMinimap);
|
|
2668
|
+
const scrollType = useHeatmapConfigStore((state) => state.scrollType);
|
|
2669
|
+
const isScrollType = [IScrollType.Attention].includes(scrollType);
|
|
2670
|
+
if (!showMinimap || !isScrollType)
|
|
2671
|
+
return null;
|
|
2672
|
+
return (jsx("div", { style: {
|
|
2673
|
+
position: 'fixed',
|
|
2674
|
+
left: '20px',
|
|
2675
|
+
top: '50%',
|
|
2676
|
+
transform: 'translateY(-50%)',
|
|
2677
|
+
width: '60px',
|
|
2678
|
+
height: '400px',
|
|
2679
|
+
backgroundColor: 'white',
|
|
2680
|
+
borderRadius: '8px',
|
|
2681
|
+
boxShadow: '0 4px 16px rgba(0,0,0,0.15)',
|
|
2682
|
+
zIndex: 10002,
|
|
2683
|
+
padding: '8px',
|
|
2684
|
+
boxSizing: 'border-box',
|
|
2685
|
+
}, children: jsx("div", { style: {
|
|
2686
|
+
width: '100%',
|
|
2687
|
+
height: '100%',
|
|
2688
|
+
borderRadius: '4px',
|
|
2689
|
+
overflow: 'hidden',
|
|
2690
|
+
display: 'flex',
|
|
2691
|
+
flexDirection: 'column',
|
|
2692
|
+
}, children: zones.map((zone) => {
|
|
2693
|
+
const normalized = maxUsers > 0 ? zone.percUsers / maxUsers : 0;
|
|
2694
|
+
const color = getScrollGradientColor(normalized);
|
|
2695
|
+
return (jsx("div", { title: `${zone.label}: ${zone.percUsers.toFixed(2)}%`, style: {
|
|
2696
|
+
width: '100%',
|
|
2697
|
+
flex: `${zone.endY - zone.startY}`,
|
|
2698
|
+
backgroundColor: color,
|
|
2699
|
+
borderBottom: '1px solid rgba(255,255,255,0.2)',
|
|
2700
|
+
} }, zone.id));
|
|
2701
|
+
}) }) }));
|
|
2702
|
+
};
|
|
2703
|
+
|
|
2704
|
+
const ScrollZoneTooltip = ({ zone, position, currentScrollPercent, scrollmap, }) => {
|
|
2705
|
+
const tooltipRef = useRef(null);
|
|
2706
|
+
const currentData = useMemo(() => {
|
|
2707
|
+
if (!scrollmap || scrollmap.length === 0)
|
|
2708
|
+
return null;
|
|
2709
|
+
const roundedPercent = Math.floor(currentScrollPercent);
|
|
2710
|
+
return scrollmap.find((d) => d.scrollReachY === roundedPercent) || null;
|
|
2711
|
+
}, [scrollmap, currentScrollPercent]);
|
|
2712
|
+
return (jsxs("div", { id: "gx-hm-scrollmap-tooltip", ref: tooltipRef, style: {
|
|
2713
|
+
position: 'fixed',
|
|
2714
|
+
top: `${position.y}px`,
|
|
2715
|
+
backgroundColor: 'black',
|
|
2716
|
+
zIndex: 10001,
|
|
2717
|
+
pointerEvents: 'none',
|
|
2718
|
+
width: '100%',
|
|
2719
|
+
height: '2px',
|
|
2720
|
+
}, children: [jsxs("div", { style: {
|
|
2721
|
+
position: 'absolute',
|
|
2722
|
+
left: '50%',
|
|
2723
|
+
top: '-50%',
|
|
2724
|
+
transform: 'translate(-50%, -50%)',
|
|
2725
|
+
padding: '16px',
|
|
2726
|
+
borderRadius: '8px',
|
|
2727
|
+
boxShadow: '0 4px 16px rgba(0,0,0,0.15)',
|
|
2728
|
+
fontSize: '14px',
|
|
2729
|
+
width: 'fit-content',
|
|
2730
|
+
backgroundColor: 'white',
|
|
2731
|
+
minWidth: '230px',
|
|
2732
|
+
display: 'flex',
|
|
2733
|
+
gap: '8px',
|
|
2734
|
+
alignItems: 'center',
|
|
2735
|
+
}, children: [jsxs("p", { style: {
|
|
2736
|
+
fontWeight: 650,
|
|
2737
|
+
fontSize: '20px',
|
|
2738
|
+
lineHeight: '24px',
|
|
2739
|
+
letterSpacing: '-0.2px',
|
|
2740
|
+
verticalAlign: 'middle',
|
|
2741
|
+
fontVariantNumeric: 'tabular-nums',
|
|
2742
|
+
}, children: [currentData?.percUsers?.toFixed(2), "%", ' '] }), jsx("p", { style: { fontWeight: 450 }, children: "user scrolled this far" })] }), jsx(TooltipByZone, { zone: zone })] }));
|
|
2743
|
+
};
|
|
2744
|
+
const TooltipByZone = ({ zone }) => {
|
|
2745
|
+
const scrollType = useHeatmapConfigStore((state) => state.scrollType);
|
|
2746
|
+
if (!zone)
|
|
2747
|
+
return null;
|
|
2748
|
+
const contentMarkup = () => {
|
|
2749
|
+
switch (scrollType) {
|
|
2750
|
+
case IScrollType.Depth:
|
|
2751
|
+
return jsx(BasicTooltipContent, { zone: zone });
|
|
2752
|
+
case IScrollType.Attention:
|
|
2753
|
+
return jsx(MetricsTooltipContent, { zone: zone });
|
|
2754
|
+
default:
|
|
2755
|
+
return jsx(BasicTooltipContent, { zone: zone });
|
|
2756
|
+
}
|
|
2757
|
+
};
|
|
2758
|
+
return (jsx("div", { style: { paddingTop: '12px', borderTop: '1px solid #E5E7EB' }, children: contentMarkup() }));
|
|
2759
|
+
};
|
|
2760
|
+
const BasicTooltipContent = ({ zone }) => {
|
|
2761
|
+
if (!zone)
|
|
2762
|
+
return null;
|
|
2763
|
+
return (jsxs(Fragment, { children: [jsx("div", { style: { fontWeight: 600, marginBottom: '8px' }, children: zone.label }), jsxs("div", { style: { fontSize: '24px', fontWeight: 700, color: '#0078D4' }, children: [zone.percUsers.toFixed(2), "%"] }), jsx("div", { style: { fontSize: '12px', color: '#605E5C', marginTop: '4px' }, children: "of users reached this point" })] }));
|
|
2764
|
+
};
|
|
2765
|
+
const MetricsTooltipContent = ({ zone }) => {
|
|
2766
|
+
if (!zone)
|
|
2767
|
+
return null;
|
|
2768
|
+
return (jsxs(Fragment, { children: [jsx("div", { style: { fontWeight: 600, marginBottom: '8px' }, children: zone.label }), jsxs("div", { style: { fontSize: '20px', fontWeight: 700, marginBottom: '8px' }, children: [zone.percUsers.toFixed(2), "% users"] }), zone.metrics && (jsxs("div", { style: { display: 'grid', gap: '6px', fontSize: '13px' }, children: [zone.metrics.revenue !== undefined && (jsx(MetricRow, { label: "Revenue", value: `$${zone.metrics.revenue.toFixed(2)}` })), zone.metrics.conversionRate !== undefined && (jsx(MetricRow, { label: "Conversion", value: `${zone.metrics.conversionRate.toFixed(2)}%` })), zone.metrics.orders !== undefined && (jsx(MetricRow, { label: "Orders", value: zone.metrics.orders.toString() }))] }))] }));
|
|
2769
|
+
};
|
|
2770
|
+
const MetricRow = ({ label, value }) => (jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [jsxs("span", { style: { color: '#605E5C' }, children: [label, ":"] }), jsx("span", { style: { fontWeight: 600 }, children: value })] }));
|
|
2771
|
+
|
|
2772
|
+
const HoverZones = ({ iframeRef, wrapperRef, position, currentScrollPercent, }) => {
|
|
2773
|
+
const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
|
|
2774
|
+
// const hoveredZone = useHeatmapVizScrollmapStore((state) => state.hoveredZone);
|
|
2775
|
+
// const setHoveredZone = useHeatmapVizScrollmapStore((state) => state.setHoveredZone);
|
|
2776
|
+
const { zones, isReady, maxUsers } = useScrollmapZones({
|
|
2777
|
+
iframeRef,
|
|
2778
|
+
wrapperRef,
|
|
2779
|
+
});
|
|
2780
|
+
if (!isReady || !zones.length)
|
|
2781
|
+
return null;
|
|
2782
|
+
if (!position)
|
|
2783
|
+
return null;
|
|
2784
|
+
return (jsxs(Fragment, { children: [jsx(ScrollZoneTooltip, { position: position, currentScrollPercent: currentScrollPercent, scrollmap: scrollmap || [] }), jsx(ScrollMapMinimap, { zones: zones, maxUsers: maxUsers })] }));
|
|
2785
|
+
};
|
|
2786
|
+
|
|
2787
|
+
const ScrollMapOverlay = ({ wrapperRef, iframeRef }) => {
|
|
2788
|
+
const overlayRef = useRef(null);
|
|
2789
|
+
const [position, setPosition] = useState();
|
|
2790
|
+
const [currentScrollPercent, setCurrentScrollPercent] = useState(0);
|
|
2791
|
+
const widthScale = useHeatmapVizStore((state) => state.scale);
|
|
2792
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
2793
|
+
const handleMouseMove = (event) => {
|
|
2794
|
+
if (!iframeRef.current || !wrapperRef.current)
|
|
2795
|
+
return;
|
|
2796
|
+
const iframe = iframeRef.current;
|
|
2797
|
+
const iframeRect = iframe.getBoundingClientRect();
|
|
2798
|
+
const { x, y } = convertViewportToIframeCoords(event.clientX, event.clientY, iframeRect, widthScale);
|
|
2799
|
+
const wrapperEl = wrapperRef.current;
|
|
2800
|
+
const scrollOffset = (wrapperEl?.scrollTop || 0) / widthScale;
|
|
2801
|
+
const actualY = y + scrollOffset;
|
|
2802
|
+
const scrollPercent = Math.min(100, Math.max(0, (actualY / iframeHeight) * 100));
|
|
2803
|
+
setCurrentScrollPercent(scrollPercent);
|
|
2804
|
+
setPosition({ x, y });
|
|
2805
|
+
};
|
|
2806
|
+
const onMouseMove = useCallback((event) => {
|
|
2807
|
+
requestAnimationFrame(() => handleMouseMove(event));
|
|
2808
|
+
}, [handleMouseMove]);
|
|
2809
|
+
const onMouseLeave = () => {
|
|
2810
|
+
requestAnimationFrame(() => {
|
|
2811
|
+
setCurrentScrollPercent(0);
|
|
2812
|
+
setPosition(undefined);
|
|
2813
|
+
});
|
|
2814
|
+
};
|
|
2815
|
+
return (jsx("div", { ref: overlayRef, id: "gx-hm-scrollmap-overlay", onMouseMove: onMouseMove, onMouseLeave: onMouseLeave, style: {
|
|
2816
|
+
position: 'absolute',
|
|
2817
|
+
top: 0,
|
|
2818
|
+
left: 0,
|
|
2819
|
+
width: '100%',
|
|
2820
|
+
height: `${iframeHeight}px`,
|
|
2821
|
+
zIndex: 3,
|
|
2822
|
+
}, children: jsx(HoverZones, { position: position, currentScrollPercent: currentScrollPercent, iframeRef: iframeRef, wrapperRef: wrapperRef }) }));
|
|
2823
|
+
};
|
|
2824
|
+
|
|
2825
|
+
const SCROLL_TYPES = [IHeatmapType.Scroll];
|
|
2826
|
+
const VizScrollMap = ({ iframeRef, wrapperRef }) => {
|
|
2827
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
2828
|
+
const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
|
|
2829
|
+
const isHeatmapScroll = SCROLL_TYPES.includes(heatmapType);
|
|
2830
|
+
if (!iframeHeight || !isHeatmapScroll)
|
|
2831
|
+
return null;
|
|
2832
|
+
return (jsxs("div", { style: {
|
|
2833
|
+
position: 'absolute',
|
|
2834
|
+
top: 0,
|
|
2835
|
+
left: '2px',
|
|
2836
|
+
width: `calc(100% - 4px)`,
|
|
2837
|
+
height: '100%',
|
|
2838
|
+
transform: 'translateZ(0)',
|
|
2839
|
+
}, children: [jsx(ScrollmapMarker, { iframeRef: iframeRef, wrapperRef: wrapperRef }), jsx(AverageFoldLine, { iframeRef: iframeRef, wrapperRef: wrapperRef }), jsx(ScrollMapOverlay, { wrapperRef: wrapperRef, iframeRef: iframeRef })] }));
|
|
2840
|
+
};
|
|
2841
|
+
|
|
1873
2842
|
const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHeight, onScroll, }) => {
|
|
1874
2843
|
const contentWidth = useHeatmapConfigStore((state) => state.width);
|
|
1875
2844
|
const widthScale = useHeatmapVizStore((state) => state.scale);
|
|
@@ -1904,8 +2873,9 @@ const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHe
|
|
|
1904
2873
|
|
|
1905
2874
|
const VizDomRenderer = ({ mode = 'heatmap' }) => {
|
|
1906
2875
|
const width = useHeatmapConfigStore((state) => state.width);
|
|
1907
|
-
const
|
|
1908
|
-
const
|
|
2876
|
+
const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
|
|
2877
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
2878
|
+
const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
|
|
1909
2879
|
const setSelectedElement = useHeatmapInteractionStore((state) => state.setSelectedElement);
|
|
1910
2880
|
const wrapperRef = useRef(null);
|
|
1911
2881
|
const visualRef = useRef(null);
|
|
@@ -1915,14 +2885,13 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
|
|
|
1915
2885
|
iframeRef,
|
|
1916
2886
|
visualRef,
|
|
1917
2887
|
iframeHeight,
|
|
1918
|
-
setIframeHeight,
|
|
1919
2888
|
});
|
|
1920
2889
|
const contentWidth = width ?? 0;
|
|
1921
2890
|
const onScroll = (e) => {
|
|
1922
2891
|
const scrollTop = e.currentTarget.scrollTop;
|
|
1923
2892
|
handleScroll(scrollTop);
|
|
1924
2893
|
};
|
|
1925
|
-
|
|
2894
|
+
useHeatmapCanvas({ iframeRef: iframeRef });
|
|
1926
2895
|
const cleanUp = () => {
|
|
1927
2896
|
setIframeHeight(0);
|
|
1928
2897
|
setSelectedElement(null);
|
|
@@ -1930,7 +2899,7 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
|
|
|
1930
2899
|
useEffect(() => {
|
|
1931
2900
|
return cleanUp;
|
|
1932
2901
|
}, []);
|
|
1933
|
-
return (jsxs(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, onScroll: onScroll, iframeHeight: iframeHeight, children: [jsx(VizElements, { iframeRef: iframeRef, visualRef: visualRef, wrapperRef: wrapperRef }), jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: contentWidth,
|
|
2902
|
+
return (jsxs(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, onScroll: onScroll, iframeHeight: iframeHeight, children: [heatmapType === IHeatmapType.Click && (jsx(VizElements, { iframeRef: iframeRef, visualRef: visualRef, wrapperRef: wrapperRef })), jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: contentWidth, scrolling: "no" }), jsx(VizScrollMap, { iframeRef: iframeRef, wrapperRef: visualRef })] }));
|
|
1934
2903
|
};
|
|
1935
2904
|
|
|
1936
2905
|
const VizLoading = () => {
|
|
@@ -1940,12 +2909,12 @@ const VizLoading = () => {
|
|
|
1940
2909
|
const VizDomHeatmap = () => {
|
|
1941
2910
|
const controls = useHeatmapControlStore((state) => state.controls);
|
|
1942
2911
|
const isRendering = useHeatmapDataStore((state) => state.isRendering);
|
|
1943
|
-
const iframeHeight =
|
|
1944
|
-
const setIframeHeight =
|
|
1945
|
-
const setVizRef =
|
|
2912
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
2913
|
+
const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
|
|
2914
|
+
const setVizRef = useHeatmapSingleStore((state) => state.setVizRef);
|
|
1946
2915
|
useEffect(() => {
|
|
1947
2916
|
return () => {
|
|
1948
|
-
setVizRef(
|
|
2917
|
+
setVizRef(null);
|
|
1949
2918
|
setIframeHeight(0);
|
|
1950
2919
|
};
|
|
1951
2920
|
}, []);
|
|
@@ -1960,7 +2929,7 @@ const VizLiveRenderer = () => {
|
|
|
1960
2929
|
const setIframeHeight = useHeatmapLiveStore((state) => state.setIframeHeight);
|
|
1961
2930
|
const visualRef = useRef(null);
|
|
1962
2931
|
const wrapperRef = useRef(null);
|
|
1963
|
-
const { iframeRef } =
|
|
2932
|
+
const { iframeRef } = useVizLiveRender();
|
|
1964
2933
|
const { scaledHeight, handleScroll } = useHeatmapScale({
|
|
1965
2934
|
wrapperRef,
|
|
1966
2935
|
iframeRef,
|
|
@@ -1972,13 +2941,15 @@ const VizLiveRenderer = () => {
|
|
|
1972
2941
|
const scrollTop = e.currentTarget.scrollTop;
|
|
1973
2942
|
handleScroll(scrollTop);
|
|
1974
2943
|
};
|
|
1975
|
-
return (jsx(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, iframeHeight: iframeHeight, onScroll: onScroll, children: jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: contentWidth,
|
|
2944
|
+
return (jsx(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, iframeHeight: iframeHeight, onScroll: onScroll, children: jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: contentWidth,
|
|
2945
|
+
// height={iframeHeight}
|
|
2946
|
+
scrolling: "no", sandbox: "allow-scripts allow-same-origin" }) }));
|
|
1976
2947
|
};
|
|
1977
2948
|
|
|
1978
2949
|
const VizLiveHeatmap = () => {
|
|
1979
2950
|
const controls = useHeatmapControlStore((state) => state.controls);
|
|
1980
2951
|
const isRendering = useHeatmapDataStore((state) => state.isRendering);
|
|
1981
|
-
const iframeHeight =
|
|
2952
|
+
const iframeHeight = useHeatmapLiveStore((state) => state.iframeHeight);
|
|
1982
2953
|
const wrapperHeight = useHeatmapLiveStore((state) => state.wrapperHeight);
|
|
1983
2954
|
const setWrapperHeight = useHeatmapLiveStore((state) => state.setWrapperHeight);
|
|
1984
2955
|
const reset = useHeatmapLiveStore((state) => state.reset);
|
|
@@ -2035,10 +3006,10 @@ const WrapperLayout = () => {
|
|
|
2035
3006
|
return (jsxs(BoxStack, { id: "gx-hm-layout", flexDirection: "column", flex: "1", children: [jsx(ContentTopBar, {}), jsx(WrapperPreview, {})] }));
|
|
2036
3007
|
};
|
|
2037
3008
|
|
|
2038
|
-
const HeatmapLayout = ({ data, clickmap, controls, dataInfo, }) => {
|
|
3009
|
+
const HeatmapLayout = ({ data, clickmap, scrollmap, controls, dataInfo, }) => {
|
|
2039
3010
|
useRegisterControl(controls);
|
|
2040
3011
|
useRegisterData(data, dataInfo);
|
|
2041
|
-
useRegisterHeatmap(clickmap);
|
|
3012
|
+
useRegisterHeatmap({ clickmap, scrollmap });
|
|
2042
3013
|
useRegisterConfig();
|
|
2043
3014
|
return (jsx(BoxStack, { id: "gx-hm-project", flexDirection: "column", flex: "1", height: "100%", style: getVariableStyle(), children: jsx(BoxStack, { id: "gx-hm-project-content", flexDirection: "column", flex: "1", children: jsx("div", { style: {
|
|
2044
3015
|
minHeight: '100%',
|
|
@@ -2053,4 +3024,4 @@ const HeatmapLayout = ({ data, clickmap, controls, dataInfo, }) => {
|
|
|
2053
3024
|
}
|
|
2054
3025
|
};
|
|
2055
3026
|
|
|
2056
|
-
export { GraphView, HeatmapLayout, IHeatmapType, useHeatmapConfigStore, useHeatmapDataStore, useHeatmapInteractionStore, useHeatmapLiveStore };
|
|
3027
|
+
export { GraphView, HeatmapLayout, IClickType, IHeatmapType, IScrollType, useHeatmapConfigStore, useHeatmapDataStore, useHeatmapInteractionStore, useHeatmapLiveStore, useHeatmapVizStore };
|