@gemx-dev/heatmap-react 3.5.44 → 3.5.46
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/ContentHeader.d.ts +4 -0
- package/dist/esm/components/Layout/ContentHeader.d.ts.map +1 -0
- package/dist/esm/components/Layout/VizMode.d.ts +2 -0
- package/dist/esm/components/Layout/VizMode.d.ts.map +1 -0
- package/dist/esm/components/Test.d.ts +121 -0
- package/dist/esm/components/Test.d.ts.map +1 -0
- package/dist/esm/components/VizDom/VizDomContainer.d.ts +6 -0
- package/dist/esm/components/VizDom/VizDomContainer.d.ts.map +1 -0
- package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/esm/components/VizElement/ClickedElementOverlay.d.ts +17 -0
- package/dist/esm/components/VizElement/ClickedElementOverlay.d.ts.map +1 -0
- package/dist/esm/components/VizElement/HeatmapElements.d.ts.map +1 -1
- package/dist/esm/components/VizElement/HoveredElementOverlay.d.ts +12 -0
- package/dist/esm/components/VizElement/HoveredElementOverlay.d.ts.map +1 -0
- package/dist/esm/components/VizElement/MissingElementMessage.d.ts +7 -0
- package/dist/esm/components/VizElement/MissingElementMessage.d.ts.map +1 -0
- package/dist/esm/components/VizElement/VizElements.d.ts.map +1 -1
- package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts +150 -0
- package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts.map +1 -0
- package/dist/esm/components/VizElement/temp/VizElementRank.d.ts +74 -0
- package/dist/esm/components/VizElement/temp/VizElementRank.d.ts.map +1 -0
- package/dist/esm/components/VizLive/VizLive.d.ts +2 -0
- package/dist/esm/components/VizLive/VizLive.d.ts.map +1 -0
- 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/configs/style.d.ts +0 -2
- package/dist/esm/configs/style.d.ts.map +1 -1
- package/dist/esm/helpers/index.d.ts +2 -1
- package/dist/esm/helpers/index.d.ts.map +1 -1
- package/dist/esm/helpers/viewport-fixer.d.ts +13 -0
- package/dist/esm/helpers/viewport-fixer.d.ts.map +1 -0
- package/dist/esm/helpers/viewport-replacer.d.ts +26 -0
- package/dist/esm/helpers/viewport-replacer.d.ts.map +1 -0
- package/dist/esm/hooks/vix-elements/useHoveredElement.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useClickmap.d.ts +1 -3
- package/dist/esm/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -1
- package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
- package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts +1 -3
- package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/esm/hooks/viz-live/index.d.ts +1 -1
- package/dist/esm/hooks/viz-live/{useVizLiveIframeMsg.d.ts → useIframeMessage.d.ts} +10 -2
- package/dist/esm/hooks/viz-live/useIframeMessage.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/useIframeHeight.d.ts +10 -0
- package/dist/esm/hooks/viz-scale/useIframeHeight.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 +203 -910
- package/dist/esm/index.mjs +203 -910
- package/dist/esm/stores/index.d.ts +0 -1
- 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 +0 -4
- package/dist/esm/stores/mode-live.d.ts.map +1 -1
- package/dist/esm/stores/viz.d.ts +4 -0
- package/dist/esm/stores/viz.d.ts.map +1 -1
- package/dist/esm/types/index.d.ts +1 -1
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/types/viewport-fixer.d.ts +31 -0
- package/dist/esm/types/viewport-fixer.d.ts.map +1 -0
- package/dist/umd/components/Layout/ContentHeader.d.ts +4 -0
- package/dist/umd/components/Layout/ContentHeader.d.ts.map +1 -0
- package/dist/umd/components/Test.d.ts +121 -0
- package/dist/umd/components/Test.d.ts.map +1 -0
- package/dist/umd/components/VizDom/VizDomContainer.d.ts +2 -0
- package/dist/umd/components/VizDom/VizDomContainer.d.ts.map +1 -0
- package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -1
- package/dist/umd/components/VizElement/ClickedElementOverlay.d.ts +17 -0
- package/dist/umd/components/VizElement/ClickedElementOverlay.d.ts.map +1 -0
- package/dist/umd/components/VizElement/HeatmapElements.d.ts.map +1 -1
- package/dist/umd/components/VizElement/HoveredElementOverlay.d.ts +12 -0
- package/dist/umd/components/VizElement/HoveredElementOverlay.d.ts.map +1 -0
- package/dist/umd/components/VizElement/MissingElementMessage.d.ts +7 -0
- package/dist/umd/components/VizElement/MissingElementMessage.d.ts.map +1 -0
- package/dist/umd/components/VizElement/VizElements.d.ts.map +1 -1
- package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts +150 -0
- package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts.map +1 -0
- package/dist/umd/components/VizElement/temp/VizElementRank.d.ts +74 -0
- package/dist/umd/components/VizElement/temp/VizElementRank.d.ts.map +1 -0
- 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/configs/style.d.ts +0 -2
- package/dist/umd/configs/style.d.ts.map +1 -1
- package/dist/umd/helpers/index.d.ts +2 -1
- package/dist/umd/helpers/index.d.ts.map +1 -1
- package/dist/umd/helpers/viewport-fixer.d.ts +13 -0
- package/dist/umd/helpers/viewport-fixer.d.ts.map +1 -0
- package/dist/umd/helpers/viewport-replacer.d.ts +26 -0
- package/dist/umd/helpers/viewport-replacer.d.ts.map +1 -0
- package/dist/umd/hooks/vix-elements/useHoveredElement.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useClickmap.d.ts +1 -3
- package/dist/umd/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +1 -1
- package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +1 -1
- package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts +1 -3
- package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
- package/dist/umd/hooks/viz-live/index.d.ts +1 -1
- package/dist/umd/hooks/viz-live/{useVizLiveIframeMsg.d.ts → useIframeMessage.d.ts} +10 -2
- package/dist/umd/hooks/viz-live/useIframeMessage.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/useIframeHeight.d.ts +10 -0
- package/dist/umd/hooks/viz-scale/useIframeHeight.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/index.d.ts +0 -1
- 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 +0 -4
- package/dist/umd/stores/mode-live.d.ts.map +1 -1
- package/dist/umd/stores/viz.d.ts +4 -0
- package/dist/umd/stores/viz.d.ts.map +1 -1
- package/dist/umd/types/index.d.ts +1 -1
- package/dist/umd/types/index.d.ts.map +1 -1
- package/dist/umd/types/viewport-fixer.d.ts +31 -0
- package/dist/umd/types/viewport-fixer.d.ts.map +1 -0
- package/package.json +13 -15
- package/src/components/GraphView.tsx +58 -0
- package/src/components/Layout/ContentMetricBar.tsx +23 -0
- package/src/components/Layout/ContentToolbar.tsx +22 -0
- package/src/components/Layout/ContentTopBar.tsx +24 -0
- package/src/components/Layout/ContentVizByMode.tsx +14 -0
- package/src/components/Layout/HeatmapLayout.tsx +60 -0
- package/src/components/Layout/LeftSidebar.tsx +44 -0
- package/src/components/Layout/WrapperLayout.tsx +12 -0
- package/src/components/Layout/WrapperPreview.tsx +24 -0
- package/src/components/Layout/index.ts +1 -0
- package/src/components/VizDom/ReplayControls.tsx +48 -0
- package/src/components/VizDom/VizContainer.tsx +40 -0
- package/src/components/VizDom/VizDomHeatmap.tsx +28 -0
- package/src/components/VizDom/VizDomRenderer.tsx +82 -0
- package/src/components/VizDom/VizLoading.tsx +8 -0
- package/src/components/VizDom/WrapperVisual.tsx +73 -0
- package/src/components/VizDom/index.ts +5 -0
- package/src/components/VizElement/DefaultRankBadges.tsx +36 -0
- package/src/components/VizElement/ElementCallout.tsx +82 -0
- package/src/components/VizElement/ElementMissing.tsx +35 -0
- package/src/components/VizElement/ElementOverlay.tsx +66 -0
- package/src/components/VizElement/HeatmapElements.tsx +127 -0
- package/src/components/VizElement/HeatmapExample.tsx +70 -0
- package/src/components/VizElement/RankBadge.tsx +25 -0
- package/src/components/VizElement/VizElements.tsx +57 -0
- package/src/components/VizElement/index.ts +1 -0
- package/src/components/VizLive/VizLiveHeatmap.tsx +27 -0
- package/src/components/VizLive/VizLiveRenderer.tsx +47 -0
- package/src/components/VizLive/index.ts +1 -0
- package/src/components/VizScrollmap/AverageFoldLine.tsx +57 -0
- package/src/components/VizScrollmap/HoverZones.tsx +58 -0
- package/src/components/VizScrollmap/MetricRow.tsx +0 -0
- package/src/components/VizScrollmap/ScrollMapMinimap.tsx +64 -0
- package/src/components/VizScrollmap/ScrollMapOverlay.tsx +79 -0
- package/src/components/VizScrollmap/ScrollZoneHoverArea.tsx +35 -0
- package/src/components/VizScrollmap/ScrollZoneTooltip.tsx +146 -0
- package/src/components/VizScrollmap/ScrollmapMarker.tsx +106 -0
- package/src/components/VizScrollmap/VizScrollMap.tsx +36 -0
- package/src/components/VizScrollmap/index.ts +1 -0
- package/src/components/VizScrollmapV2/ScrollmapOverlay.css +94 -0
- package/src/components/VizScrollmapV2/ScrollmapOverlayV2.tsx +130 -0
- package/src/components/VizScrollmapV2/index.ts +1 -0
- package/src/components/VizScrollmapV2/scrollmap.types.ts +21 -0
- package/src/components/VizScrollmapV2/useScrollmapOverlay.ts +187 -0
- package/src/components/index.tsx +2 -0
- package/src/configs/iframe.ts +15 -0
- package/src/configs/index.ts +2 -0
- package/src/configs/style.ts +21 -0
- package/src/constants/index.ts +4 -0
- package/src/global.d.ts +5 -0
- package/src/helpers/elm-callout.ts +347 -0
- package/src/helpers/elm-getter.ts +70 -0
- package/src/helpers/iframe-helper/fixer.ts +100 -0
- package/src/helpers/iframe-helper/index.ts +1 -0
- package/src/helpers/iframe-helper/init.ts +56 -0
- package/src/helpers/iframe-helper/navigation-blocker-v2.ts +371 -0
- package/src/helpers/iframe-helper/navigation-blocker.ts +367 -0
- package/src/helpers/iframe-helper/style-replacer.ts +231 -0
- package/src/helpers/iframe.ts +42 -0
- package/src/helpers/index.ts +8 -0
- package/src/helpers/viz-canvas/area-clustering.ts +234 -0
- package/src/helpers/viz-canvas/area-overlay-manager-v2.ts +176 -0
- package/src/helpers/viz-canvas/area-overlay-manager.ts +273 -0
- package/src/helpers/viz-canvas/hierarchical-area-clustering.ts +420 -0
- package/src/helpers/viz-canvas/index.ts +2 -0
- package/src/helpers/viz-elements.ts +43 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/register/index.ts +4 -0
- package/src/hooks/register/useRegisterConfig.ts +17 -0
- package/src/hooks/register/useRegisterControl.ts +13 -0
- package/src/hooks/register/useRegisterData.ts +36 -0
- package/src/hooks/register/useRegisterHeatmap.ts +38 -0
- package/src/hooks/viz-area/useAreaHeatmap.ts +336 -0
- package/src/hooks/viz-area/useAreaHeatmapManager.ts +692 -0
- package/src/hooks/viz-canvas/index.ts +1 -0
- package/src/hooks/viz-canvas/useAreamap.ts +162 -0
- package/src/hooks/viz-canvas/useClickmap.ts +24 -0
- package/src/hooks/viz-canvas/useHeatmapCanvas.ts +27 -0
- package/src/hooks/viz-canvas/useScrollmap.ts +22 -0
- package/src/hooks/viz-elements/index.ts +5 -0
- package/src/hooks/viz-elements/useClickedElement.ts +86 -0
- package/src/hooks/viz-elements/useElementCalloutVisible.ts +45 -0
- package/src/hooks/viz-elements/useHeatmapEffects.ts +30 -0
- package/src/hooks/viz-elements/useHeatmapElementPosition.ts +60 -0
- package/src/hooks/viz-elements/useHeatmapMouseHandler.ts +255 -0
- package/src/hooks/viz-elements/useHoveredElement.ts +170 -0
- package/src/hooks/viz-live/index.ts +1 -0
- package/src/hooks/viz-live/useVizLiveIframeMsg.ts +88 -0
- package/src/hooks/viz-live/useVizLiveRender.ts +67 -0
- package/src/hooks/viz-render/index.ts +1 -0
- package/src/hooks/viz-render/useHeatmapRender.ts +71 -0
- package/src/hooks/viz-render/useHeatmapVizRender.ts +20 -0
- package/src/hooks/viz-render/useReplayRender.ts +160 -0
- package/src/hooks/viz-scale/index.ts +2 -0
- package/src/hooks/viz-scale/useContainerDimensions.ts +48 -0
- package/src/hooks/viz-scale/useContentDimensions.ts +25 -0
- package/src/hooks/viz-scale/useHeatmapScale.ts +52 -0
- package/src/hooks/viz-scale/useObserveIframeHeight.ts +162 -0
- package/src/hooks/viz-scale/useScaleCalculation.ts +31 -0
- package/src/hooks/viz-scale/useScrollSync.ts +36 -0
- package/src/hooks/viz-scale/useWrapperRefHeight.ts +91 -0
- package/src/hooks/viz-scrollmap/index.ts +2 -0
- package/src/hooks/viz-scrollmap/useScrollmapZones.ts +165 -0
- package/src/hooks/viz-scrollmap/useZonePositions.ts +38 -0
- package/src/index.ts +10 -0
- package/src/stores/comp.ts +31 -0
- package/src/stores/config.ts +37 -0
- package/src/stores/data.ts +30 -0
- package/src/stores/index.ts +10 -0
- package/src/stores/interaction.ts +32 -0
- package/src/stores/mode-live.ts +38 -0
- package/src/stores/mode-single.ts +18 -0
- package/src/stores/viz-scrollmap.ts +22 -0
- package/src/stores/viz.ts +17 -0
- package/src/styles/base.css +1 -0
- package/src/styles/style.css +137 -0
- package/src/types/clarity.ts +45 -0
- package/src/types/control.ts +10 -0
- package/src/types/elm-callout.ts +9 -0
- package/src/types/heatmap-info.ts +11 -0
- package/src/types/heatmap.ts +25 -0
- package/src/types/iframe-helper.ts +18 -0
- package/src/types/index.ts +12 -0
- package/src/types/viz-canvas.ts +20 -0
- package/src/types/viz-element.ts +34 -0
- package/src/types/viz-scrollmap.ts +28 -0
- package/src/ui/BoxStack/BoxStack.tsx +136 -0
- package/src/ui/BoxStack/index.ts +1 -0
- package/src/ui/index.ts +1 -0
- package/src/utils/debounce.ts +10 -0
- package/src/utils/device.ts +7 -0
- package/src/utils/retry.ts +20 -0
- package/src/utils/sort.ts +5 -0
- package/dist/esm/helpers/iframe-helper/fixer.d.ts +0 -18
- package/dist/esm/helpers/iframe-helper/fixer.d.ts.map +0 -1
- package/dist/esm/helpers/iframe-helper/index.d.ts +0 -2
- package/dist/esm/helpers/iframe-helper/index.d.ts.map +0 -1
- package/dist/esm/helpers/iframe-helper/init.d.ts +0 -5
- package/dist/esm/helpers/iframe-helper/init.d.ts.map +0 -1
- package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts +0 -28
- package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +0 -1
- package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts +0 -20
- package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts.map +0 -1
- package/dist/esm/helpers/iframe-helper/style-replacer.d.ts +0 -25
- package/dist/esm/helpers/iframe-helper/style-replacer.d.ts.map +0 -1
- package/dist/esm/hooks/vix-elements/useHeatmapMouseHandler.d.ts +0 -34
- package/dist/esm/hooks/vix-elements/useHeatmapMouseHandler.d.ts.map +0 -1
- package/dist/esm/hooks/viz-live/useVizLiveIframeMsg.d.ts.map +0 -1
- package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts +0 -4
- package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts.map +0 -1
- package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts +0 -10
- package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts.map +0 -1
- package/dist/esm/stores/mode-single.d.ts +0 -9
- package/dist/esm/stores/mode-single.d.ts.map +0 -1
- package/dist/esm/types/iframe-helper.d.ts +0 -20
- package/dist/esm/types/iframe-helper.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/fixer.d.ts +0 -18
- package/dist/umd/helpers/iframe-helper/fixer.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/index.d.ts +0 -2
- package/dist/umd/helpers/iframe-helper/index.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/init.d.ts +0 -5
- package/dist/umd/helpers/iframe-helper/init.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts +0 -28
- package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts +0 -20
- package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts.map +0 -1
- package/dist/umd/helpers/iframe-helper/style-replacer.d.ts +0 -25
- package/dist/umd/helpers/iframe-helper/style-replacer.d.ts.map +0 -1
- package/dist/umd/hooks/vix-elements/useHeatmapMouseHandler.d.ts +0 -34
- package/dist/umd/hooks/vix-elements/useHeatmapMouseHandler.d.ts.map +0 -1
- package/dist/umd/hooks/viz-live/useVizLiveIframeMsg.d.ts.map +0 -1
- package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts +0 -4
- package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts.map +0 -1
- package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts +0 -10
- package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts.map +0 -1
- package/dist/umd/stores/mode-single.d.ts +0 -9
- package/dist/umd/stores/mode-single.d.ts.map +0 -1
- package/dist/umd/types/iframe-helper.d.ts +0 -20
- package/dist/umd/types/iframe-helper.d.ts.map +0 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useZonePositions } from '../../hooks';
|
|
3
|
+
import { useHeatmapDataStore } from '../../stores';
|
|
4
|
+
|
|
5
|
+
interface AverageFoldLineProps {
|
|
6
|
+
iframeRef: React.RefObject<HTMLIFrameElement>;
|
|
7
|
+
wrapperRef: React.RefObject<HTMLElement>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const AverageFoldLine: React.FC<AverageFoldLineProps> = ({ iframeRef, wrapperRef }) => {
|
|
11
|
+
const averageFold = useHeatmapDataStore((state) => state.dataInfo?.averageFold || 50);
|
|
12
|
+
|
|
13
|
+
const { getZonePosition } = useZonePositions({ iframeRef, wrapperRef });
|
|
14
|
+
|
|
15
|
+
const position = getZonePosition({
|
|
16
|
+
startY: averageFold,
|
|
17
|
+
endY: averageFold,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (!position) return null;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div
|
|
24
|
+
style={{
|
|
25
|
+
position: 'absolute',
|
|
26
|
+
top: `${position.top}px`,
|
|
27
|
+
left: 0,
|
|
28
|
+
width: '100%',
|
|
29
|
+
height: '2px',
|
|
30
|
+
backgroundColor: '#0078D4',
|
|
31
|
+
pointerEvents: 'none',
|
|
32
|
+
zIndex: 2,
|
|
33
|
+
boxShadow: '0 0 4px rgba(0,120,212,0.5)',
|
|
34
|
+
display: 'flex',
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
}}
|
|
37
|
+
>
|
|
38
|
+
<div
|
|
39
|
+
style={{
|
|
40
|
+
position: 'absolute',
|
|
41
|
+
padding: '8px',
|
|
42
|
+
backgroundColor: 'rgba(0, 120, 212, 0.9)',
|
|
43
|
+
color: 'white',
|
|
44
|
+
fontSize: '16px',
|
|
45
|
+
fontWeight: 600,
|
|
46
|
+
borderRadius: '4px',
|
|
47
|
+
whiteSpace: 'nowrap',
|
|
48
|
+
left: '12px',
|
|
49
|
+
minWidth: '120px',
|
|
50
|
+
textAlign: 'center',
|
|
51
|
+
}}
|
|
52
|
+
>
|
|
53
|
+
Average fold - {averageFold.toFixed(0)}%
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useScrollmapZones } from '../../hooks';
|
|
2
|
+
import { useHeatmapDataStore } from '../../stores';
|
|
3
|
+
import { IScrollMapPosition } from '../../types';
|
|
4
|
+
import { ScrollMapMinimap } from './ScrollMapMinimap';
|
|
5
|
+
import { ScrollZoneTooltip } from './ScrollZoneTooltip';
|
|
6
|
+
|
|
7
|
+
interface HoverZonesProps {
|
|
8
|
+
wrapperRef: React.RefObject<HTMLElement>;
|
|
9
|
+
iframeRef: React.RefObject<HTMLIFrameElement>;
|
|
10
|
+
position?: IScrollMapPosition;
|
|
11
|
+
currentScrollPercent: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const HoverZones: React.FC<HoverZonesProps> = ({
|
|
15
|
+
iframeRef,
|
|
16
|
+
wrapperRef,
|
|
17
|
+
position,
|
|
18
|
+
currentScrollPercent,
|
|
19
|
+
}) => {
|
|
20
|
+
const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
|
|
21
|
+
// const hoveredZone = useHeatmapVizScrollmapStore((state) => state.hoveredZone);
|
|
22
|
+
// const setHoveredZone = useHeatmapVizScrollmapStore((state) => state.setHoveredZone);
|
|
23
|
+
|
|
24
|
+
const { zones, isReady, maxUsers } = useScrollmapZones({
|
|
25
|
+
iframeRef,
|
|
26
|
+
wrapperRef,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
if (!isReady || !zones.length) return null;
|
|
30
|
+
if (!position) return null;
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<>
|
|
34
|
+
{/* {zones.map((zone) => {
|
|
35
|
+
const position = getZonePosition(zone);
|
|
36
|
+
if (!position) return null;
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<ScrollZoneHoverArea
|
|
40
|
+
key={zone.id}
|
|
41
|
+
zone={zone}
|
|
42
|
+
position={position}
|
|
43
|
+
isHovered={hoveredZone?.id === zone.id}
|
|
44
|
+
onHoverChange={setHoveredZone}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
})} */}
|
|
48
|
+
|
|
49
|
+
<ScrollZoneTooltip
|
|
50
|
+
position={position}
|
|
51
|
+
currentScrollPercent={currentScrollPercent}
|
|
52
|
+
scrollmap={scrollmap || []}
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<ScrollMapMinimap zones={zones} maxUsers={maxUsers} />
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getScrollGradientColor } from '../../hooks';
|
|
2
|
+
import { useHeatmapConfigStore, useHeatmapVizScrollmapStore } from '../../stores';
|
|
3
|
+
import { IScrollType, IScrollZone } from '../../types';
|
|
4
|
+
|
|
5
|
+
interface ScrollMapMinimapProps {
|
|
6
|
+
zones: IScrollZone[];
|
|
7
|
+
maxUsers: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const ScrollMapMinimap: React.FC<ScrollMapMinimapProps> = ({ zones, maxUsers }) => {
|
|
11
|
+
const showMinimap = useHeatmapVizScrollmapStore((state) => state.showMinimap);
|
|
12
|
+
const scrollType = useHeatmapConfigStore((state) => state.scrollType);
|
|
13
|
+
const isScrollType = [IScrollType.Attention].includes(scrollType);
|
|
14
|
+
|
|
15
|
+
if (!showMinimap || !isScrollType) return null;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div
|
|
19
|
+
style={{
|
|
20
|
+
position: 'fixed',
|
|
21
|
+
left: '20px',
|
|
22
|
+
top: '50%',
|
|
23
|
+
transform: 'translateY(-50%)',
|
|
24
|
+
width: '60px',
|
|
25
|
+
height: '400px',
|
|
26
|
+
backgroundColor: 'white',
|
|
27
|
+
borderRadius: '8px',
|
|
28
|
+
boxShadow: '0 4px 16px rgba(0,0,0,0.15)',
|
|
29
|
+
zIndex: 10002,
|
|
30
|
+
padding: '8px',
|
|
31
|
+
boxSizing: 'border-box',
|
|
32
|
+
}}
|
|
33
|
+
>
|
|
34
|
+
<div
|
|
35
|
+
style={{
|
|
36
|
+
width: '100%',
|
|
37
|
+
height: '100%',
|
|
38
|
+
borderRadius: '4px',
|
|
39
|
+
overflow: 'hidden',
|
|
40
|
+
display: 'flex',
|
|
41
|
+
flexDirection: 'column',
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
{zones.map((zone) => {
|
|
45
|
+
const normalized = maxUsers > 0 ? zone.percUsers / maxUsers : 0;
|
|
46
|
+
const color = getScrollGradientColor(normalized);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
key={zone.id}
|
|
51
|
+
title={`${zone.label}: ${zone.percUsers.toFixed(2)}%`}
|
|
52
|
+
style={{
|
|
53
|
+
width: '100%',
|
|
54
|
+
flex: `${zone.endY - zone.startY}`,
|
|
55
|
+
backgroundColor: color,
|
|
56
|
+
borderBottom: '1px solid rgba(255,255,255,0.2)',
|
|
57
|
+
}}
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
})}
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from 'react';
|
|
2
|
+
import { convertViewportToIframeCoords } from '../../hooks';
|
|
3
|
+
import { useHeatmapSingleStore, useHeatmapVizStore } from '../../stores';
|
|
4
|
+
import { IScrollMapPosition } from '../../types';
|
|
5
|
+
import { HoverZones } from './HoverZones';
|
|
6
|
+
|
|
7
|
+
interface ScrollMapOverlayProps {
|
|
8
|
+
wrapperRef: React.RefObject<HTMLElement>;
|
|
9
|
+
iframeRef: React.RefObject<HTMLIFrameElement>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const ScrollMapOverlay: React.FC<ScrollMapOverlayProps> = ({ wrapperRef, iframeRef }) => {
|
|
13
|
+
const overlayRef = useRef<HTMLDivElement>(null);
|
|
14
|
+
|
|
15
|
+
const [position, setPosition] = useState<IScrollMapPosition>();
|
|
16
|
+
const [currentScrollPercent, setCurrentScrollPercent] = useState<number>(0);
|
|
17
|
+
|
|
18
|
+
const widthScale = useHeatmapVizStore((state) => state.scale);
|
|
19
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
20
|
+
|
|
21
|
+
const handleMouseMove = (event: React.MouseEvent<HTMLDivElement>) => {
|
|
22
|
+
if (!iframeRef.current || !wrapperRef.current) return;
|
|
23
|
+
|
|
24
|
+
const iframe = iframeRef.current;
|
|
25
|
+
const iframeRect = iframe.getBoundingClientRect();
|
|
26
|
+
const { x, y } = convertViewportToIframeCoords(
|
|
27
|
+
event.clientX,
|
|
28
|
+
event.clientY,
|
|
29
|
+
iframeRect,
|
|
30
|
+
widthScale,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const wrapperEl = wrapperRef.current as HTMLElement;
|
|
34
|
+
const scrollOffset = (wrapperEl?.scrollTop || 0) / widthScale;
|
|
35
|
+
const actualY = y + scrollOffset;
|
|
36
|
+
const scrollPercent = Math.min(100, Math.max(0, (actualY / iframeHeight) * 100));
|
|
37
|
+
|
|
38
|
+
setCurrentScrollPercent(scrollPercent);
|
|
39
|
+
setPosition({ x, y });
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const onMouseMove = useCallback(
|
|
43
|
+
(event: React.MouseEvent<HTMLDivElement>) => {
|
|
44
|
+
requestAnimationFrame(() => handleMouseMove(event));
|
|
45
|
+
},
|
|
46
|
+
[handleMouseMove],
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const onMouseLeave = () => {
|
|
50
|
+
requestAnimationFrame(() => {
|
|
51
|
+
setCurrentScrollPercent(0);
|
|
52
|
+
setPosition(undefined);
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<div
|
|
58
|
+
ref={overlayRef}
|
|
59
|
+
id="gx-hm-scrollmap-overlay"
|
|
60
|
+
onMouseMove={onMouseMove}
|
|
61
|
+
onMouseLeave={onMouseLeave}
|
|
62
|
+
style={{
|
|
63
|
+
position: 'absolute',
|
|
64
|
+
top: 0,
|
|
65
|
+
left: 0,
|
|
66
|
+
width: '100%',
|
|
67
|
+
height: `${iframeHeight}px`,
|
|
68
|
+
zIndex: 3,
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
<HoverZones
|
|
72
|
+
position={position}
|
|
73
|
+
currentScrollPercent={currentScrollPercent}
|
|
74
|
+
iframeRef={iframeRef}
|
|
75
|
+
wrapperRef={wrapperRef}
|
|
76
|
+
/>
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IScrollZone } from '../../types';
|
|
3
|
+
|
|
4
|
+
interface ScrollZoneHoverAreaProps {
|
|
5
|
+
zone: IScrollZone;
|
|
6
|
+
position: { top: number; height: number };
|
|
7
|
+
isHovered: boolean;
|
|
8
|
+
onHoverChange: (zone: IScrollZone | null) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const ScrollZoneHoverArea: React.FC<ScrollZoneHoverAreaProps> = ({
|
|
12
|
+
zone,
|
|
13
|
+
position,
|
|
14
|
+
isHovered,
|
|
15
|
+
onHoverChange,
|
|
16
|
+
}) => {
|
|
17
|
+
return (
|
|
18
|
+
<div
|
|
19
|
+
style={{
|
|
20
|
+
position: 'absolute',
|
|
21
|
+
top: `${position.top}px`,
|
|
22
|
+
left: 0,
|
|
23
|
+
width: '100%',
|
|
24
|
+
height: `${position.height}px`,
|
|
25
|
+
pointerEvents: 'auto',
|
|
26
|
+
cursor: 'pointer',
|
|
27
|
+
backgroundColor: isHovered ? 'rgba(0, 120, 212, 0.1)' : 'transparent',
|
|
28
|
+
transition: 'background-color 0.2s ease',
|
|
29
|
+
borderBottom: '1px dashed rgba(0, 120, 212, 0.2)',
|
|
30
|
+
}}
|
|
31
|
+
onMouseEnter={() => onHoverChange(zone)}
|
|
32
|
+
onMouseLeave={() => onHoverChange(null)}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { useMemo, useRef } from 'react';
|
|
2
|
+
import { useHeatmapConfigStore } from '../../stores';
|
|
3
|
+
import { IScrollMapPosition, IScrollType, IScrollZone, ScrollMapPoint } from '../../types';
|
|
4
|
+
|
|
5
|
+
interface ScrollZoneTooltipProps {
|
|
6
|
+
zone?: IScrollZone;
|
|
7
|
+
position: IScrollMapPosition;
|
|
8
|
+
currentScrollPercent: number;
|
|
9
|
+
scrollmap: ScrollMapPoint[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const ScrollZoneTooltip: React.FC<ScrollZoneTooltipProps> = ({
|
|
13
|
+
zone,
|
|
14
|
+
position,
|
|
15
|
+
currentScrollPercent,
|
|
16
|
+
scrollmap,
|
|
17
|
+
}) => {
|
|
18
|
+
const tooltipRef = useRef<HTMLDivElement>(null);
|
|
19
|
+
|
|
20
|
+
const currentData = useMemo(() => {
|
|
21
|
+
if (!scrollmap || scrollmap.length === 0) return null;
|
|
22
|
+
|
|
23
|
+
const roundedPercent = Math.floor(currentScrollPercent);
|
|
24
|
+
return scrollmap.find((d) => d.scrollReachY === roundedPercent) || null;
|
|
25
|
+
}, [scrollmap, currentScrollPercent]);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
id="gx-hm-scrollmap-tooltip"
|
|
30
|
+
ref={tooltipRef}
|
|
31
|
+
style={{
|
|
32
|
+
position: 'fixed',
|
|
33
|
+
top: `${position.y}px`,
|
|
34
|
+
backgroundColor: 'black',
|
|
35
|
+
zIndex: 10001,
|
|
36
|
+
pointerEvents: 'none',
|
|
37
|
+
width: '100%',
|
|
38
|
+
height: '2px',
|
|
39
|
+
}}
|
|
40
|
+
>
|
|
41
|
+
<div
|
|
42
|
+
style={{
|
|
43
|
+
position: 'absolute',
|
|
44
|
+
left: '50%',
|
|
45
|
+
top: '-50%',
|
|
46
|
+
transform: 'translate(-50%, -50%)',
|
|
47
|
+
padding: '16px',
|
|
48
|
+
borderRadius: '8px',
|
|
49
|
+
boxShadow: '0 4px 16px rgba(0,0,0,0.15)',
|
|
50
|
+
fontSize: '14px',
|
|
51
|
+
width: 'fit-content',
|
|
52
|
+
backgroundColor: 'white',
|
|
53
|
+
minWidth: '230px',
|
|
54
|
+
display: 'flex',
|
|
55
|
+
gap: '8px',
|
|
56
|
+
alignItems: 'center',
|
|
57
|
+
}}
|
|
58
|
+
>
|
|
59
|
+
<p
|
|
60
|
+
style={{
|
|
61
|
+
fontWeight: 650,
|
|
62
|
+
fontSize: '20px',
|
|
63
|
+
lineHeight: '24px',
|
|
64
|
+
letterSpacing: '-0.2px',
|
|
65
|
+
verticalAlign: 'middle',
|
|
66
|
+
fontVariantNumeric: 'tabular-nums',
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
{currentData?.percUsers?.toFixed(2)}%{' '}
|
|
70
|
+
</p>
|
|
71
|
+
<p style={{ fontWeight: 450 }}>user scrolled this far</p>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<TooltipByZone zone={zone} />
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const TooltipByZone: React.FC<{ zone?: IScrollZone }> = ({ zone }) => {
|
|
80
|
+
const scrollType = useHeatmapConfigStore((state) => state.scrollType);
|
|
81
|
+
if (!zone) return null;
|
|
82
|
+
|
|
83
|
+
const contentMarkup = () => {
|
|
84
|
+
switch (scrollType) {
|
|
85
|
+
case IScrollType.Depth:
|
|
86
|
+
return <BasicTooltipContent zone={zone} />;
|
|
87
|
+
case IScrollType.Attention:
|
|
88
|
+
return <MetricsTooltipContent zone={zone} />;
|
|
89
|
+
default:
|
|
90
|
+
return <BasicTooltipContent zone={zone} />;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
return (
|
|
94
|
+
<div style={{ paddingTop: '12px', borderTop: '1px solid #E5E7EB' }}>{contentMarkup()}</div>
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const BasicTooltipContent: React.FC<{ zone?: IScrollZone }> = ({ zone }) => {
|
|
99
|
+
if (!zone) return null;
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<>
|
|
103
|
+
<div style={{ fontWeight: 600, marginBottom: '8px' }}>{zone.label}</div>
|
|
104
|
+
<div style={{ fontSize: '24px', fontWeight: 700, color: '#0078D4' }}>
|
|
105
|
+
{zone.percUsers.toFixed(2)}%
|
|
106
|
+
</div>
|
|
107
|
+
<div style={{ fontSize: '12px', color: '#605E5C', marginTop: '4px' }}>
|
|
108
|
+
of users reached this point
|
|
109
|
+
</div>
|
|
110
|
+
</>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const MetricsTooltipContent: React.FC<{ zone?: IScrollZone }> = ({ zone }) => {
|
|
115
|
+
if (!zone) return null;
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<>
|
|
119
|
+
<div style={{ fontWeight: 600, marginBottom: '8px' }}>{zone.label}</div>
|
|
120
|
+
<div style={{ fontSize: '20px', fontWeight: 700, marginBottom: '8px' }}>
|
|
121
|
+
{zone.percUsers.toFixed(2)}% users
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
{zone.metrics && (
|
|
125
|
+
<div style={{ display: 'grid', gap: '6px', fontSize: '13px' }}>
|
|
126
|
+
{zone.metrics.revenue !== undefined && (
|
|
127
|
+
<MetricRow label="Revenue" value={`$${zone.metrics.revenue.toFixed(2)}`} />
|
|
128
|
+
)}
|
|
129
|
+
{zone.metrics.conversionRate !== undefined && (
|
|
130
|
+
<MetricRow label="Conversion" value={`${zone.metrics.conversionRate.toFixed(2)}%`} />
|
|
131
|
+
)}
|
|
132
|
+
{zone.metrics.orders !== undefined && (
|
|
133
|
+
<MetricRow label="Orders" value={zone.metrics.orders.toString()} />
|
|
134
|
+
)}
|
|
135
|
+
</div>
|
|
136
|
+
)}
|
|
137
|
+
</>
|
|
138
|
+
);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const MetricRow: React.FC<{ label: string; value: string }> = ({ label, value }) => (
|
|
142
|
+
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
143
|
+
<span style={{ color: '#605E5C' }}>{label}:</span>
|
|
144
|
+
<span style={{ fontWeight: 600 }}>{value}</span>
|
|
145
|
+
</div>
|
|
146
|
+
);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useZonePositions } from '../../hooks';
|
|
2
|
+
import { useHeatmapConfigStore, useHeatmapDataStore } from '../../stores';
|
|
3
|
+
import { IScrollType } from '../../types';
|
|
4
|
+
|
|
5
|
+
interface ScrollmapMarkerProps {
|
|
6
|
+
iframeRef: React.RefObject<HTMLIFrameElement>;
|
|
7
|
+
wrapperRef: React.RefObject<HTMLElement>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const ScrollmapMarker: React.FC<ScrollmapMarkerProps> = ({ iframeRef, wrapperRef }) => {
|
|
11
|
+
const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
|
|
12
|
+
const scrollType = useHeatmapConfigStore((state) => state.scrollType);
|
|
13
|
+
|
|
14
|
+
const { getZonePosition } = useZonePositions({ iframeRef, wrapperRef });
|
|
15
|
+
|
|
16
|
+
if (!scrollmap || scrollmap.length === 0) return null;
|
|
17
|
+
|
|
18
|
+
const findScrollPositionForUserPercent = (targetPercent: number): number | null => {
|
|
19
|
+
for (let i = 0; i < scrollmap.length; i++) {
|
|
20
|
+
if (scrollmap[i].percUsers <= targetPercent) {
|
|
21
|
+
if (i > 0) {
|
|
22
|
+
return scrollmap[i - 1].scrollReachY;
|
|
23
|
+
}
|
|
24
|
+
return scrollmap[i].scrollReachY;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return scrollmap[scrollmap.length - 1]?.scrollReachY || null;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const boundaries = [
|
|
32
|
+
{ percent: 75, label: '75%', color: '#10B981' },
|
|
33
|
+
{ percent: 50, label: '50%', color: '#F59E0B' },
|
|
34
|
+
{ percent: 25, label: '25%', color: '#EF4444' },
|
|
35
|
+
{ percent: 5, label: '5%', color: '#8B5CF6' },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const isScrollDepth = scrollType === IScrollType.Depth;
|
|
39
|
+
if (!isScrollDepth) return null;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<>
|
|
43
|
+
{boundaries.map((boundary) => {
|
|
44
|
+
const scrollY = findScrollPositionForUserPercent(boundary.percent);
|
|
45
|
+
if (scrollY === null) return null;
|
|
46
|
+
|
|
47
|
+
const position = getZonePosition({
|
|
48
|
+
startY: scrollY,
|
|
49
|
+
endY: scrollY,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (!position) return null;
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<div
|
|
56
|
+
className={`marker-boundary-line-${boundary.percent}`}
|
|
57
|
+
key={boundary.label}
|
|
58
|
+
style={{
|
|
59
|
+
position: 'absolute',
|
|
60
|
+
top: `${position.top}px`,
|
|
61
|
+
left: 0,
|
|
62
|
+
transformOrigin: 'left center',
|
|
63
|
+
width: '100%',
|
|
64
|
+
height: '0px',
|
|
65
|
+
// borderBottom: `2px dashed #323130`,
|
|
66
|
+
borderBottom: `2px solid ${boundary.color}`,
|
|
67
|
+
// background: 'repeating-linear-gradient(90deg, #323130, transparent 2px 3px)',
|
|
68
|
+
zIndex: 1,
|
|
69
|
+
display: 'flex',
|
|
70
|
+
alignItems: 'center',
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
73
|
+
<div
|
|
74
|
+
style={{
|
|
75
|
+
position: 'absolute',
|
|
76
|
+
padding: '8px',
|
|
77
|
+
backgroundColor: boundary.color,
|
|
78
|
+
color: 'white',
|
|
79
|
+
fontSize: '16px',
|
|
80
|
+
fontWeight: 600,
|
|
81
|
+
borderRadius: '4px',
|
|
82
|
+
whiteSpace: 'nowrap',
|
|
83
|
+
left: '12px',
|
|
84
|
+
minWidth: '120px',
|
|
85
|
+
textAlign: 'center',
|
|
86
|
+
|
|
87
|
+
// textAlign: 'center',
|
|
88
|
+
// padding: '8px',
|
|
89
|
+
// paddingInline: '8px',
|
|
90
|
+
// fontSize: '16px',
|
|
91
|
+
// background: '#fff',
|
|
92
|
+
// width: 'auto',
|
|
93
|
+
// borderRadius: '4px',
|
|
94
|
+
// position: 'absolute',
|
|
95
|
+
// left: '12px',
|
|
96
|
+
// minWidth: '120px',
|
|
97
|
+
}}
|
|
98
|
+
>
|
|
99
|
+
{boundary.label}
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
);
|
|
103
|
+
})}
|
|
104
|
+
</>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useHeatmapConfigStore, useHeatmapSingleStore } from '../../stores';
|
|
2
|
+
import { IHeatmapType } from '../../types';
|
|
3
|
+
import { AverageFoldLine } from './AverageFoldLine';
|
|
4
|
+
import { ScrollmapMarker } from './ScrollmapMarker';
|
|
5
|
+
import { ScrollMapOverlay } from './ScrollMapOverlay';
|
|
6
|
+
|
|
7
|
+
interface VizScrollMapProps {
|
|
8
|
+
iframeRef: React.RefObject<HTMLIFrameElement>;
|
|
9
|
+
wrapperRef: React.RefObject<HTMLElement>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const SCROLL_TYPES = [IHeatmapType.Scroll];
|
|
13
|
+
export const VizScrollMap: React.FC<VizScrollMapProps> = ({ iframeRef, wrapperRef }) => {
|
|
14
|
+
const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
|
|
15
|
+
const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
|
|
16
|
+
|
|
17
|
+
const isHeatmapScroll = SCROLL_TYPES.includes(heatmapType);
|
|
18
|
+
if (!iframeHeight || !isHeatmapScroll) return null;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div
|
|
22
|
+
style={{
|
|
23
|
+
position: 'absolute',
|
|
24
|
+
top: 0,
|
|
25
|
+
left: '2px',
|
|
26
|
+
width: `calc(100% - 4px)`,
|
|
27
|
+
height: '100%',
|
|
28
|
+
transform: 'translateZ(0)',
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
31
|
+
<ScrollmapMarker iframeRef={iframeRef} wrapperRef={wrapperRef} />
|
|
32
|
+
<AverageFoldLine iframeRef={iframeRef} wrapperRef={wrapperRef} />
|
|
33
|
+
<ScrollMapOverlay wrapperRef={wrapperRef} iframeRef={iframeRef} />
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ScrollMapOverlay';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/* ScrollmapOverlay.css */
|
|
2
|
+
|
|
3
|
+
.scrollmap-overlay {
|
|
4
|
+
position: absolute;
|
|
5
|
+
top: 0;
|
|
6
|
+
left: 0;
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 100%;
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
z-index: 10;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Marker wrapper */
|
|
14
|
+
.scrollmap-marker-wrapper {
|
|
15
|
+
position: absolute;
|
|
16
|
+
width: 100%;
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
gap: 8px;
|
|
20
|
+
pointer-events: none;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* Marker lines */
|
|
24
|
+
.scrollmap-marker-line {
|
|
25
|
+
flex: 1;
|
|
26
|
+
height: 2px;
|
|
27
|
+
background-color: rgba(0, 0, 0, 0.3);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Marker label base */
|
|
31
|
+
.scrollmap-marker {
|
|
32
|
+
padding: 4px 12px;
|
|
33
|
+
border-radius: 4px;
|
|
34
|
+
font-size: 12px;
|
|
35
|
+
font-weight: 600;
|
|
36
|
+
white-space: nowrap;
|
|
37
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* Average Fold marker - distinctive color */
|
|
41
|
+
.scrollmap-marker--avgfold {
|
|
42
|
+
background-color: #ff6b6b;
|
|
43
|
+
color: white;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Percentage markers - neutral color */
|
|
47
|
+
.scrollmap-marker--percentage {
|
|
48
|
+
background-color: #4a90e2;
|
|
49
|
+
color: white;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Hover tooltip */
|
|
53
|
+
.scrollmap-hover-tooltip {
|
|
54
|
+
position: absolute;
|
|
55
|
+
pointer-events: none;
|
|
56
|
+
z-index: 100;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.scrollmap-hover-tooltip-content {
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-direction: column;
|
|
62
|
+
align-items: center;
|
|
63
|
+
padding: 8px 12px;
|
|
64
|
+
background-color: rgba(0, 0, 0, 0.85);
|
|
65
|
+
color: white;
|
|
66
|
+
border-radius: 6px;
|
|
67
|
+
font-size: 12px;
|
|
68
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
69
|
+
max-height: 48px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.scrollmap-hover-tooltip-percentage {
|
|
73
|
+
font-size: 14px;
|
|
74
|
+
font-weight: 700;
|
|
75
|
+
line-height: 1.2;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.scrollmap-hover-tooltip-label {
|
|
79
|
+
font-size: 11px;
|
|
80
|
+
opacity: 0.8;
|
|
81
|
+
line-height: 1.2;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Responsive adjustments */
|
|
85
|
+
@media (max-width: 768px) {
|
|
86
|
+
.scrollmap-marker {
|
|
87
|
+
font-size: 10px;
|
|
88
|
+
padding: 3px 8px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.scrollmap-hover-tooltip-content {
|
|
92
|
+
padding: 6px 10px;
|
|
93
|
+
}
|
|
94
|
+
}
|