@gemx-dev/heatmap-react 3.5.43 → 3.5.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/dist/esm/components/Layout/HeatmapLayout.d.ts +3 -2
  2. package/dist/esm/components/Layout/HeatmapLayout.d.ts.map +1 -1
  3. package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -1
  4. package/dist/esm/components/VizElement/HeatmapElements.d.ts +2 -2
  5. package/dist/esm/components/VizElement/HeatmapElements.d.ts.map +1 -1
  6. package/dist/esm/components/VizElement/HeatmapExample.d.ts +2 -0
  7. package/dist/esm/components/VizElement/HeatmapExample.d.ts.map +1 -0
  8. package/dist/esm/components/VizScrollmap/AverageFoldLine.d.ts +8 -0
  9. package/dist/esm/components/VizScrollmap/AverageFoldLine.d.ts.map +1 -0
  10. package/dist/esm/components/VizScrollmap/HoverZones.d.ts +10 -0
  11. package/dist/esm/components/VizScrollmap/HoverZones.d.ts.map +1 -0
  12. package/dist/esm/components/VizScrollmap/MetricRow.d.ts +1 -0
  13. package/dist/esm/components/VizScrollmap/MetricRow.d.ts.map +1 -0
  14. package/dist/esm/components/VizScrollmap/ScrollMapMinimap.d.ts +8 -0
  15. package/dist/esm/components/VizScrollmap/ScrollMapMinimap.d.ts.map +1 -0
  16. package/dist/esm/components/VizScrollmap/ScrollMapOverlay.d.ts +7 -0
  17. package/dist/esm/components/VizScrollmap/ScrollMapOverlay.d.ts.map +1 -0
  18. package/dist/esm/components/VizScrollmap/ScrollZoneHoverArea.d.ts +14 -0
  19. package/dist/esm/components/VizScrollmap/ScrollZoneHoverArea.d.ts.map +1 -0
  20. package/dist/esm/components/VizScrollmap/ScrollZoneTooltip.d.ts +10 -0
  21. package/dist/esm/components/VizScrollmap/ScrollZoneTooltip.d.ts.map +1 -0
  22. package/dist/esm/components/VizScrollmap/ScrollmapMarker.d.ts +7 -0
  23. package/dist/esm/components/VizScrollmap/ScrollmapMarker.d.ts.map +1 -0
  24. package/dist/esm/components/VizScrollmap/VizScrollMap.d.ts +7 -0
  25. package/dist/esm/components/VizScrollmap/VizScrollMap.d.ts.map +1 -0
  26. package/dist/esm/components/VizScrollmap/index.d.ts +2 -0
  27. package/dist/esm/components/VizScrollmap/index.d.ts.map +1 -0
  28. package/dist/esm/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts +5 -0
  29. package/dist/esm/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts.map +1 -0
  30. package/dist/esm/components/VizScrollmapV2/index.d.ts +2 -0
  31. package/dist/esm/components/VizScrollmapV2/index.d.ts.map +1 -0
  32. package/dist/esm/components/VizScrollmapV2/scrollmap.types.d.ts +18 -0
  33. package/dist/esm/components/VizScrollmapV2/scrollmap.types.d.ts.map +1 -0
  34. package/dist/esm/components/VizScrollmapV2/useScrollmapOverlay.d.ts +16 -0
  35. package/dist/esm/components/VizScrollmapV2/useScrollmapOverlay.d.ts.map +1 -0
  36. package/dist/esm/helpers/elm-getter.d.ts +2 -2
  37. package/dist/esm/helpers/elm-getter.d.ts.map +1 -1
  38. package/dist/esm/helpers/iframe-helper/fixer.d.ts +18 -0
  39. package/dist/esm/helpers/iframe-helper/fixer.d.ts.map +1 -0
  40. package/dist/esm/helpers/iframe-helper/index.d.ts +2 -0
  41. package/dist/esm/helpers/iframe-helper/index.d.ts.map +1 -0
  42. package/dist/esm/helpers/iframe-helper/init.d.ts +5 -0
  43. package/dist/esm/helpers/iframe-helper/init.d.ts.map +1 -0
  44. package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts +28 -0
  45. package/dist/esm/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +1 -0
  46. package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts +20 -0
  47. package/dist/esm/helpers/iframe-helper/navigation-blocker.d.ts.map +1 -0
  48. package/dist/{umd/helpers/viewport-replacer.d.ts → esm/helpers/iframe-helper/style-replacer.d.ts} +5 -5
  49. package/dist/esm/helpers/iframe-helper/style-replacer.d.ts.map +1 -0
  50. package/dist/esm/helpers/index.d.ts +2 -2
  51. package/dist/esm/helpers/index.d.ts.map +1 -1
  52. package/dist/esm/helpers/viz-canvas/area-clustering.d.ts +44 -0
  53. package/dist/esm/helpers/viz-canvas/area-clustering.d.ts.map +1 -0
  54. package/dist/esm/helpers/viz-canvas/area-overlay-manager-v2.d.ts +17 -0
  55. package/dist/esm/helpers/viz-canvas/area-overlay-manager-v2.d.ts.map +1 -0
  56. package/dist/esm/helpers/viz-canvas/area-overlay-manager.d.ts +51 -0
  57. package/dist/esm/helpers/viz-canvas/area-overlay-manager.d.ts.map +1 -0
  58. package/dist/esm/helpers/viz-canvas/hierarchical-area-clustering.d.ts +73 -0
  59. package/dist/esm/helpers/viz-canvas/hierarchical-area-clustering.d.ts.map +1 -0
  60. package/dist/esm/helpers/viz-canvas/index.d.ts +3 -0
  61. package/dist/esm/helpers/viz-canvas/index.d.ts.map +1 -0
  62. package/dist/esm/hooks/index.d.ts +2 -1
  63. package/dist/esm/hooks/index.d.ts.map +1 -1
  64. package/dist/esm/hooks/register/useRegisterData.d.ts +2 -2
  65. package/dist/esm/hooks/register/useRegisterData.d.ts.map +1 -1
  66. package/dist/esm/hooks/register/useRegisterHeatmap.d.ts +7 -2
  67. package/dist/esm/hooks/register/useRegisterHeatmap.d.ts.map +1 -1
  68. package/dist/esm/hooks/viz-area/useAreaHeatmap.d.ts +59 -0
  69. package/dist/esm/hooks/viz-area/useAreaHeatmap.d.ts.map +1 -0
  70. package/dist/esm/hooks/viz-area/useAreaHeatmapManager.d.ts +77 -0
  71. package/dist/esm/hooks/viz-area/useAreaHeatmapManager.d.ts.map +1 -0
  72. package/dist/esm/hooks/viz-canvas/index.d.ts +1 -1
  73. package/dist/esm/hooks/viz-canvas/index.d.ts.map +1 -1
  74. package/dist/esm/hooks/viz-canvas/useAreamap.d.ts +14 -0
  75. package/dist/esm/hooks/viz-canvas/useAreamap.d.ts.map +1 -0
  76. package/dist/esm/hooks/viz-canvas/useHeatmapCanvas.d.ts +4 -0
  77. package/dist/esm/hooks/viz-canvas/useHeatmapCanvas.d.ts.map +1 -0
  78. package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
  79. package/dist/esm/hooks/{vix-elements → viz-elements}/index.d.ts.map +1 -1
  80. package/dist/esm/hooks/{vix-elements → viz-elements}/useClickedElement.d.ts.map +1 -1
  81. package/dist/esm/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts.map +1 -1
  82. package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts.map +1 -1
  83. package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts.map +1 -1
  84. package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapMouseHandler.d.ts +2 -2
  85. package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapMouseHandler.d.ts.map +1 -1
  86. package/dist/esm/hooks/{vix-elements → viz-elements}/useHoveredElement.d.ts +4 -0
  87. package/dist/esm/hooks/{vix-elements → viz-elements}/useHoveredElement.d.ts.map +1 -1
  88. package/dist/esm/hooks/viz-scrollmap/index.d.ts +3 -0
  89. package/dist/esm/hooks/viz-scrollmap/index.d.ts.map +1 -0
  90. package/dist/esm/hooks/viz-scrollmap/useScrollmapZones.d.ts +29 -0
  91. package/dist/esm/hooks/viz-scrollmap/useScrollmapZones.d.ts.map +1 -0
  92. package/dist/esm/hooks/viz-scrollmap/useZonePositions.d.ts +12 -0
  93. package/dist/esm/hooks/viz-scrollmap/useZonePositions.d.ts.map +1 -0
  94. package/dist/esm/index.js +825 -242
  95. package/dist/esm/index.mjs +825 -242
  96. package/dist/esm/stores/config.d.ts +5 -1
  97. package/dist/esm/stores/config.d.ts.map +1 -1
  98. package/dist/esm/stores/data.d.ts +5 -3
  99. package/dist/esm/stores/data.d.ts.map +1 -1
  100. package/dist/esm/stores/index.d.ts +1 -0
  101. package/dist/esm/stores/index.d.ts.map +1 -1
  102. package/dist/esm/stores/viz-scrollmap.d.ts +11 -0
  103. package/dist/esm/stores/viz-scrollmap.d.ts.map +1 -0
  104. package/dist/esm/types/clarity.d.ts +5 -0
  105. package/dist/esm/types/clarity.d.ts.map +1 -1
  106. package/dist/esm/types/heatmap-info.d.ts +11 -0
  107. package/dist/esm/types/heatmap-info.d.ts.map +1 -0
  108. package/dist/esm/types/heatmap.d.ts +13 -0
  109. package/dist/esm/types/heatmap.d.ts.map +1 -1
  110. package/dist/esm/types/iframe-helper.d.ts +20 -0
  111. package/dist/esm/types/iframe-helper.d.ts.map +1 -0
  112. package/dist/esm/types/index.d.ts +4 -1
  113. package/dist/esm/types/index.d.ts.map +1 -1
  114. package/dist/esm/types/viz-canvas.d.ts +23 -0
  115. package/dist/esm/types/viz-canvas.d.ts.map +1 -0
  116. package/dist/esm/types/viz-element.d.ts +0 -6
  117. package/dist/esm/types/viz-element.d.ts.map +1 -1
  118. package/dist/esm/types/viz-scrollmap.d.ts +27 -0
  119. package/dist/esm/types/viz-scrollmap.d.ts.map +1 -0
  120. package/dist/umd/components/Layout/HeatmapLayout.d.ts +3 -2
  121. package/dist/umd/components/Layout/HeatmapLayout.d.ts.map +1 -1
  122. package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -1
  123. package/dist/umd/components/VizElement/HeatmapElements.d.ts +2 -2
  124. package/dist/umd/components/VizElement/HeatmapElements.d.ts.map +1 -1
  125. package/dist/umd/components/VizElement/HeatmapExample.d.ts +2 -0
  126. package/dist/umd/components/VizElement/HeatmapExample.d.ts.map +1 -0
  127. package/dist/umd/components/VizScrollmap/AverageFoldLine.d.ts +8 -0
  128. package/dist/umd/components/VizScrollmap/AverageFoldLine.d.ts.map +1 -0
  129. package/dist/umd/components/VizScrollmap/HoverZones.d.ts +10 -0
  130. package/dist/umd/components/VizScrollmap/HoverZones.d.ts.map +1 -0
  131. package/dist/umd/components/VizScrollmap/MetricRow.d.ts +1 -0
  132. package/dist/umd/components/VizScrollmap/MetricRow.d.ts.map +1 -0
  133. package/dist/umd/components/VizScrollmap/ScrollMapMinimap.d.ts +8 -0
  134. package/dist/umd/components/VizScrollmap/ScrollMapMinimap.d.ts.map +1 -0
  135. package/dist/umd/components/VizScrollmap/ScrollMapOverlay.d.ts +7 -0
  136. package/dist/umd/components/VizScrollmap/ScrollMapOverlay.d.ts.map +1 -0
  137. package/dist/umd/components/VizScrollmap/ScrollZoneHoverArea.d.ts +14 -0
  138. package/dist/umd/components/VizScrollmap/ScrollZoneHoverArea.d.ts.map +1 -0
  139. package/dist/umd/components/VizScrollmap/ScrollZoneTooltip.d.ts +10 -0
  140. package/dist/umd/components/VizScrollmap/ScrollZoneTooltip.d.ts.map +1 -0
  141. package/dist/umd/components/VizScrollmap/ScrollmapMarker.d.ts +7 -0
  142. package/dist/umd/components/VizScrollmap/ScrollmapMarker.d.ts.map +1 -0
  143. package/dist/umd/components/VizScrollmap/VizScrollMap.d.ts +7 -0
  144. package/dist/umd/components/VizScrollmap/VizScrollMap.d.ts.map +1 -0
  145. package/dist/umd/components/VizScrollmap/index.d.ts +2 -0
  146. package/dist/umd/components/VizScrollmap/index.d.ts.map +1 -0
  147. package/dist/umd/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts +5 -0
  148. package/dist/umd/components/VizScrollmapV2/ScrollmapOverlayV2.d.ts.map +1 -0
  149. package/dist/umd/components/VizScrollmapV2/index.d.ts +2 -0
  150. package/dist/umd/components/VizScrollmapV2/index.d.ts.map +1 -0
  151. package/dist/umd/components/VizScrollmapV2/scrollmap.types.d.ts +18 -0
  152. package/dist/umd/components/VizScrollmapV2/scrollmap.types.d.ts.map +1 -0
  153. package/dist/umd/components/VizScrollmapV2/useScrollmapOverlay.d.ts +16 -0
  154. package/dist/umd/components/VizScrollmapV2/useScrollmapOverlay.d.ts.map +1 -0
  155. package/dist/umd/helpers/elm-getter.d.ts +2 -2
  156. package/dist/umd/helpers/elm-getter.d.ts.map +1 -1
  157. package/dist/umd/helpers/iframe-helper/fixer.d.ts +18 -0
  158. package/dist/umd/helpers/iframe-helper/fixer.d.ts.map +1 -0
  159. package/dist/umd/helpers/iframe-helper/index.d.ts +2 -0
  160. package/dist/umd/helpers/iframe-helper/index.d.ts.map +1 -0
  161. package/dist/umd/helpers/iframe-helper/init.d.ts +5 -0
  162. package/dist/umd/helpers/iframe-helper/init.d.ts.map +1 -0
  163. package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts +28 -0
  164. package/dist/umd/helpers/iframe-helper/navigation-blocker-v2.d.ts.map +1 -0
  165. package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts +20 -0
  166. package/dist/umd/helpers/iframe-helper/navigation-blocker.d.ts.map +1 -0
  167. package/dist/{esm/helpers/viewport-replacer.d.ts → umd/helpers/iframe-helper/style-replacer.d.ts} +5 -5
  168. package/dist/umd/helpers/iframe-helper/style-replacer.d.ts.map +1 -0
  169. package/dist/umd/helpers/index.d.ts +2 -2
  170. package/dist/umd/helpers/index.d.ts.map +1 -1
  171. package/dist/umd/helpers/viz-canvas/area-clustering.d.ts +44 -0
  172. package/dist/umd/helpers/viz-canvas/area-clustering.d.ts.map +1 -0
  173. package/dist/umd/helpers/viz-canvas/area-overlay-manager-v2.d.ts +17 -0
  174. package/dist/umd/helpers/viz-canvas/area-overlay-manager-v2.d.ts.map +1 -0
  175. package/dist/umd/helpers/viz-canvas/area-overlay-manager.d.ts +51 -0
  176. package/dist/umd/helpers/viz-canvas/area-overlay-manager.d.ts.map +1 -0
  177. package/dist/umd/helpers/viz-canvas/hierarchical-area-clustering.d.ts +73 -0
  178. package/dist/umd/helpers/viz-canvas/hierarchical-area-clustering.d.ts.map +1 -0
  179. package/dist/umd/helpers/viz-canvas/index.d.ts +3 -0
  180. package/dist/umd/helpers/viz-canvas/index.d.ts.map +1 -0
  181. package/dist/umd/hooks/index.d.ts +2 -1
  182. package/dist/umd/hooks/index.d.ts.map +1 -1
  183. package/dist/umd/hooks/register/useRegisterData.d.ts +2 -2
  184. package/dist/umd/hooks/register/useRegisterData.d.ts.map +1 -1
  185. package/dist/umd/hooks/register/useRegisterHeatmap.d.ts +7 -2
  186. package/dist/umd/hooks/register/useRegisterHeatmap.d.ts.map +1 -1
  187. package/dist/umd/hooks/viz-area/useAreaHeatmap.d.ts +59 -0
  188. package/dist/umd/hooks/viz-area/useAreaHeatmap.d.ts.map +1 -0
  189. package/dist/umd/hooks/viz-area/useAreaHeatmapManager.d.ts +77 -0
  190. package/dist/umd/hooks/viz-area/useAreaHeatmapManager.d.ts.map +1 -0
  191. package/dist/umd/hooks/viz-canvas/index.d.ts +1 -1
  192. package/dist/umd/hooks/viz-canvas/index.d.ts.map +1 -1
  193. package/dist/umd/hooks/viz-canvas/useAreamap.d.ts +14 -0
  194. package/dist/umd/hooks/viz-canvas/useAreamap.d.ts.map +1 -0
  195. package/dist/umd/hooks/viz-canvas/useHeatmapCanvas.d.ts +4 -0
  196. package/dist/umd/hooks/viz-canvas/useHeatmapCanvas.d.ts.map +1 -0
  197. package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
  198. package/dist/umd/hooks/{vix-elements → viz-elements}/index.d.ts.map +1 -1
  199. package/dist/umd/hooks/{vix-elements → viz-elements}/useClickedElement.d.ts.map +1 -1
  200. package/dist/umd/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts.map +1 -1
  201. package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts.map +1 -1
  202. package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts.map +1 -1
  203. package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapMouseHandler.d.ts +2 -2
  204. package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapMouseHandler.d.ts.map +1 -1
  205. package/dist/umd/hooks/{vix-elements → viz-elements}/useHoveredElement.d.ts +4 -0
  206. package/dist/umd/hooks/{vix-elements → viz-elements}/useHoveredElement.d.ts.map +1 -1
  207. package/dist/umd/hooks/viz-scrollmap/index.d.ts +3 -0
  208. package/dist/umd/hooks/viz-scrollmap/index.d.ts.map +1 -0
  209. package/dist/umd/hooks/viz-scrollmap/useScrollmapZones.d.ts +29 -0
  210. package/dist/umd/hooks/viz-scrollmap/useScrollmapZones.d.ts.map +1 -0
  211. package/dist/umd/hooks/viz-scrollmap/useZonePositions.d.ts +12 -0
  212. package/dist/umd/hooks/viz-scrollmap/useZonePositions.d.ts.map +1 -0
  213. package/dist/umd/index.js +2 -2
  214. package/dist/umd/stores/config.d.ts +5 -1
  215. package/dist/umd/stores/config.d.ts.map +1 -1
  216. package/dist/umd/stores/data.d.ts +5 -3
  217. package/dist/umd/stores/data.d.ts.map +1 -1
  218. package/dist/umd/stores/index.d.ts +1 -0
  219. package/dist/umd/stores/index.d.ts.map +1 -1
  220. package/dist/umd/stores/viz-scrollmap.d.ts +11 -0
  221. package/dist/umd/stores/viz-scrollmap.d.ts.map +1 -0
  222. package/dist/umd/types/clarity.d.ts +5 -0
  223. package/dist/umd/types/clarity.d.ts.map +1 -1
  224. package/dist/umd/types/heatmap-info.d.ts +11 -0
  225. package/dist/umd/types/heatmap-info.d.ts.map +1 -0
  226. package/dist/umd/types/heatmap.d.ts +13 -0
  227. package/dist/umd/types/heatmap.d.ts.map +1 -1
  228. package/dist/umd/types/iframe-helper.d.ts +20 -0
  229. package/dist/umd/types/iframe-helper.d.ts.map +1 -0
  230. package/dist/umd/types/index.d.ts +4 -1
  231. package/dist/umd/types/index.d.ts.map +1 -1
  232. package/dist/umd/types/viz-canvas.d.ts +23 -0
  233. package/dist/umd/types/viz-canvas.d.ts.map +1 -0
  234. package/dist/umd/types/viz-element.d.ts +0 -6
  235. package/dist/umd/types/viz-element.d.ts.map +1 -1
  236. package/dist/umd/types/viz-scrollmap.d.ts +27 -0
  237. package/dist/umd/types/viz-scrollmap.d.ts.map +1 -0
  238. package/package.json +1 -1
  239. package/dist/esm/helpers/viewport-fixer.d.ts +0 -15
  240. package/dist/esm/helpers/viewport-fixer.d.ts.map +0 -1
  241. package/dist/esm/helpers/viewport-replacer.d.ts.map +0 -1
  242. package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +0 -2
  243. package/dist/esm/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +0 -1
  244. package/dist/esm/types/viewport-fixer.d.ts +0 -31
  245. package/dist/esm/types/viewport-fixer.d.ts.map +0 -1
  246. package/dist/umd/helpers/viewport-fixer.d.ts +0 -15
  247. package/dist/umd/helpers/viewport-fixer.d.ts.map +0 -1
  248. package/dist/umd/helpers/viewport-replacer.d.ts.map +0 -1
  249. package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts +0 -2
  250. package/dist/umd/hooks/viz-canvas/useHeatmapVizCanvas.d.ts.map +0 -1
  251. package/dist/umd/types/viewport-fixer.d.ts +0 -31
  252. package/dist/umd/types/viewport-fixer.d.ts.map +0 -1
  253. /package/dist/esm/hooks/{vix-elements → viz-elements}/index.d.ts +0 -0
  254. /package/dist/esm/hooks/{vix-elements → viz-elements}/useClickedElement.d.ts +0 -0
  255. /package/dist/esm/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts +0 -0
  256. /package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts +0 -0
  257. /package/dist/esm/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts +0 -0
  258. /package/dist/umd/hooks/{vix-elements → viz-elements}/index.d.ts +0 -0
  259. /package/dist/umd/hooks/{vix-elements → viz-elements}/useClickedElement.d.ts +0 -0
  260. /package/dist/umd/hooks/{vix-elements → viz-elements}/useElementCalloutVisible.d.ts +0 -0
  261. /package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapEffects.d.ts +0 -0
  262. /package/dist/umd/hooks/{vix-elements → viz-elements}/useHeatmapElementPosition.d.ts +0 -0
@@ -93,18 +93,37 @@ var IHeatmapType;
93
93
  IHeatmapType["Click"] = "click";
94
94
  IHeatmapType["Scroll"] = "scroll";
95
95
  })(IHeatmapType || (IHeatmapType = {}));
96
+ var IClickType;
97
+ (function (IClickType) {
98
+ IClickType["Total"] = "total-clicks";
99
+ IClickType["Rage"] = "rage-clicks";
100
+ IClickType["Dead"] = "dead-clicks";
101
+ IClickType["Error"] = "error-clicks";
102
+ IClickType["First"] = "first-clicks";
103
+ IClickType["Last"] = "last-clicks";
104
+ })(IClickType || (IClickType = {}));
105
+ var IScrollType;
106
+ (function (IScrollType) {
107
+ IScrollType["Depth"] = "scroll-depth";
108
+ IScrollType["Attention"] = "attention-scroll";
109
+ IScrollType["Revenue"] = "revenue-scroll";
110
+ })(IScrollType || (IScrollType = {}));
96
111
 
97
112
  const useHeatmapConfigStore = create()((set, get) => {
98
113
  return {
99
114
  mode: 'single',
100
115
  width: 1440,
101
116
  sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
102
- heatmapType: IHeatmapType.Click,
117
+ heatmapType: IHeatmapType.Scroll,
118
+ clickType: IClickType.Total,
119
+ scrollType: IScrollType.Depth,
103
120
  setMode: (mode) => set({ mode }),
104
121
  resetMode: () => set({ mode: 'single' }),
105
122
  setWidth: (width) => set({ width }),
106
123
  setSidebarWidth: (sidebarWidth) => set({ sidebarWidth }),
107
124
  setHeatmapType: (heatmapType) => set({ heatmapType }),
125
+ setClickType: (clickType) => set({ clickType }),
126
+ setScrollType: (scrollType) => set({ scrollType }),
108
127
  };
109
128
  });
110
129
 
@@ -113,11 +132,13 @@ const useHeatmapDataStore = create()((set, get) => {
113
132
  data: undefined,
114
133
  clickmap: undefined,
115
134
  dataInfo: undefined,
135
+ scrollmap: undefined,
116
136
  isRendering: true,
117
137
  setIsRendering: (isRendering) => set({ isRendering }),
118
138
  setDataInfo: (dataInfo) => set({ dataInfo }),
119
139
  setData: (data) => set({ data }),
120
140
  setClickmap: (clickmap) => set({ clickmap }),
141
+ setScrollmap: (scrollmap) => set({ scrollmap }),
121
142
  };
122
143
  });
123
144
 
@@ -145,6 +166,17 @@ const useHeatmapVizStore = create()((set, get) => {
145
166
  };
146
167
  });
147
168
 
169
+ const useHeatmapVizScrollmapStore = create()((set, get) => {
170
+ return {
171
+ zones: [],
172
+ hoveredZone: null,
173
+ showMinimap: true,
174
+ setZones: (zones) => set({ zones }),
175
+ setHoveredZone: (hoveredZone) => set({ hoveredZone }),
176
+ setShowMinimap: (showMinimap) => set({ showMinimap }),
177
+ };
178
+ });
179
+
148
180
  const initialState = {
149
181
  payloads: [],
150
182
  htmlContent: '',
@@ -219,16 +251,25 @@ const useRegisterData = (data, dataInfo) => {
219
251
  }, [dataInfo]);
220
252
  };
221
253
 
222
- const useRegisterHeatmap = (clickmap) => {
254
+ const useRegisterHeatmap = ({ clickmap, scrollmap }) => {
223
255
  const setClickmap = useHeatmapDataStore((state) => state.setClickmap);
256
+ const setScrollmap = useHeatmapDataStore((state) => state.setScrollmap);
224
257
  const handleSetClickmap = useCallback((clickmap) => {
225
258
  if (!clickmap)
226
259
  return;
227
260
  setClickmap(clickmap);
228
261
  }, [clickmap]);
262
+ const handleSetScrollmap = useCallback((scrollmap) => {
263
+ if (!scrollmap)
264
+ return;
265
+ setScrollmap(scrollmap);
266
+ }, [scrollmap]);
229
267
  useEffect(() => {
230
268
  handleSetClickmap(clickmap);
231
269
  }, [clickmap]);
270
+ useEffect(() => {
271
+ handleSetScrollmap(scrollmap);
272
+ }, [scrollmap]);
232
273
  };
233
274
 
234
275
  const PADDING = 0;
@@ -511,7 +552,300 @@ function isElementInViewport(elementRect, visualRef, scale) {
511
552
  return elementBottom > viewportTop && elementTop < viewportBottom;
512
553
  }
513
554
 
514
- class ViewportUnitsReplacer {
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);
569
+ this.init();
570
+ }
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();
586
+ }
587
+ catch (error) {
588
+ console.error('[NavigationBlocker] Init error:', error);
589
+ }
590
+ }
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
+ });
738
+ });
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
+ }
761
+ }
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)
787
+ return;
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);
816
+ }
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');
845
+ }
846
+ }
847
+
848
+ class IframeStyleReplacer {
515
849
  doc;
516
850
  win;
517
851
  config;
@@ -556,7 +890,7 @@ class ViewportUnitsReplacer {
556
890
  count++;
557
891
  }
558
892
  });
559
- console.log(`[ViewportReplacer] Replaced ${count} inline style elements`);
893
+ console.log(`[IframeStyleReplacer] Replaced ${count} inline style elements`);
560
894
  return count;
561
895
  }
562
896
  processStyleTags() {
@@ -569,7 +903,7 @@ class ViewportUnitsReplacer {
569
903
  count++;
570
904
  }
571
905
  });
572
- console.log(`[ViewportReplacer] Replaced ${count} <style> tags`);
906
+ console.log(`[IframeStyleReplacer] Replaced ${count} <style> tags`);
573
907
  return count;
574
908
  }
575
909
  processRule(rule) {
@@ -600,7 +934,7 @@ class ViewportUnitsReplacer {
600
934
  try {
601
935
  // Bỏ qua external CSS (cross-origin)
602
936
  if (sheet.href && !sheet.href.startsWith(this.win.location.origin)) {
603
- console.log('[ViewportReplacer] Skipping external CSS:', sheet.href);
937
+ console.log('[IframeStyleReplacer] Skipping external CSS:', sheet.href);
604
938
  return;
605
939
  }
606
940
  const rules = sheet.cssRules || sheet.rules;
@@ -611,10 +945,10 @@ class ViewportUnitsReplacer {
611
945
  }
612
946
  }
613
947
  catch (e) {
614
- console.warn('[ViewportReplacer] Cannot read stylesheet (CORS?):', e.message);
948
+ console.warn('[IframeStyleReplacer] Cannot read stylesheet (CORS?):', e.message);
615
949
  }
616
950
  });
617
- console.log(`[ViewportReplacer] Replaced ${total} rules in stylesheets`);
951
+ console.log(`[IframeStyleReplacer] Replaced ${total} rules in stylesheets`);
618
952
  return total;
619
953
  }
620
954
  async processLinkedStylesheets() {
@@ -622,7 +956,7 @@ class ViewportUnitsReplacer {
622
956
  let count = 0;
623
957
  for (const link of Array.from(links)) {
624
958
  if (!link.href.startsWith(this.win.location.origin)) {
625
- console.log('[ViewportReplacer] Skipping external CSS:', link.href);
959
+ console.log('[IframeStyleReplacer] Skipping external CSS:', link.href);
626
960
  continue;
627
961
  }
628
962
  try {
@@ -640,10 +974,10 @@ class ViewportUnitsReplacer {
640
974
  }
641
975
  }
642
976
  catch (e) {
643
- console.warn('[ViewportReplacer] Cannot load CSS:', link.href, e);
977
+ console.warn('[IframeStyleReplacer] Cannot load CSS:', link.href, e);
644
978
  }
645
979
  }
646
- console.log(`[ViewportReplacer] Replaced ${count} linked CSS files`);
980
+ console.log(`[IframeStyleReplacer] Replaced ${count} linked CSS files`);
647
981
  return count;
648
982
  }
649
983
  getFinalHeight() {
@@ -667,7 +1001,7 @@ class ViewportUnitsReplacer {
667
1001
  }
668
1002
  async run() {
669
1003
  try {
670
- console.log('[ViewportReplacer] Starting viewport units replacement...');
1004
+ console.log('[IframeStyleReplacer] Starting viewport units replacement...');
671
1005
  this.processInlineStyles();
672
1006
  this.processStyleTags();
673
1007
  this.processStylesheets();
@@ -677,13 +1011,13 @@ class ViewportUnitsReplacer {
677
1011
  requestAnimationFrame(() => {
678
1012
  const height = this.getFinalHeight();
679
1013
  const width = this.getFinalWidth();
680
- console.log('[ViewportReplacer] Calculated dimensions:', { height, width });
1014
+ console.log('[IframeStyleReplacer] Calculated dimensions:', { height, width });
681
1015
  resolve({ height, width });
682
1016
  });
683
1017
  });
684
1018
  }
685
1019
  catch (err) {
686
- console.error('[ViewportReplacer] Critical error:', err);
1020
+ console.error('[IframeStyleReplacer] Critical error:', err);
687
1021
  return {
688
1022
  height: this.doc.body.scrollHeight || 1000,
689
1023
  width: this.doc.body.scrollWidth || 1000,
@@ -695,10 +1029,11 @@ class ViewportUnitsReplacer {
695
1029
  }
696
1030
  }
697
1031
 
698
- class ViewportUnitsFixer {
1032
+ class IframeHelperFixer {
699
1033
  iframe;
700
1034
  config;
701
1035
  replacer = null;
1036
+ navigationBlocker = null;
702
1037
  constructor(config) {
703
1038
  this.config = config;
704
1039
  this.iframe = config.iframe;
@@ -706,10 +1041,11 @@ class ViewportUnitsFixer {
706
1041
  }
707
1042
  async init() {
708
1043
  if (!this.iframe) {
709
- console.error('[ViewportFixer] iframe not found');
1044
+ console.error('[IframeHelper] iframe not found');
710
1045
  this.config.onError?.(new Error('iframe not found'));
711
1046
  return;
712
1047
  }
1048
+ // Wait for iframe to load completely
713
1049
  if (this.iframe.contentDocument?.readyState === 'complete') {
714
1050
  await this.process();
715
1051
  }
@@ -719,17 +1055,19 @@ class ViewportUnitsFixer {
719
1055
  }
720
1056
  async process() {
721
1057
  if (!this.iframe.contentDocument || !this.iframe.contentWindow) {
722
- console.error('[ViewportFixer] Cannot access iframe document');
1058
+ console.error('[IframeHelper] Cannot access iframe document');
723
1059
  this.config.onError?.(new Error('Cannot access iframe document'));
724
1060
  return;
725
1061
  }
726
1062
  try {
727
- console.log('[ViewportFixer] Processing viewport units...');
728
- // Tạo replacer instance với iframe và config
729
- this.replacer = new ViewportUnitsReplacer(this.iframe, this.config);
730
- // Chạy replacement
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
731
1069
  const result = await this.replacer.run();
732
- console.log('[ViewportFixer] Process completed:', result);
1070
+ console.log('[IframeHelper] Process completed:', result);
733
1071
  // Trigger success callback
734
1072
  this.config.onSuccess?.(result);
735
1073
  // Dispatch custom event
@@ -738,12 +1076,12 @@ class ViewportUnitsFixer {
738
1076
  }));
739
1077
  }
740
1078
  catch (error) {
741
- console.error('[ViewportFixer] Failed to process:', error);
1079
+ console.error('[IframeHelper] Failed to process:', error);
742
1080
  this.config.onError?.(error);
743
1081
  }
744
1082
  }
745
1083
  async recalculate() {
746
- console.log('[ViewportFixer] Recalculating...');
1084
+ console.log('[IframeHelper] Recalculating...');
747
1085
  await this.process();
748
1086
  }
749
1087
  updateConfig(config) {
@@ -752,16 +1090,39 @@ class ViewportUnitsFixer {
752
1090
  this.replacer.updateConfig(config);
753
1091
  }
754
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
+ }
755
1105
  destroy() {
756
1106
  this.replacer = null;
757
- console.log('[ViewportFixer] Destroyed');
1107
+ this.navigationBlocker?.destroy();
1108
+ this.navigationBlocker = null;
1109
+ console.log('[IframeHelper] Destroyed');
758
1110
  }
759
1111
  }
760
- function initViewportFixer(config) {
761
- const fixer = new ViewportUnitsFixer(config);
1112
+
1113
+ function initIframeHelperFixer(config) {
1114
+ const fixer = new IframeHelperFixer(config);
762
1115
  window.addEventListener('iframe-dimensions-applied', ((e) => {
763
1116
  const ev = e;
764
- console.log('[ViewportFixer] Iframe dimensions finalized:', ev.detail);
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);
765
1126
  }));
766
1127
  return fixer;
767
1128
  }
@@ -926,8 +1287,6 @@ const debounce = (fn, delay) => {
926
1287
  };
927
1288
  };
928
1289
 
929
- // ===================== CONSTANTS =====================
930
- const HEATMAP_ELEMENT_ATTRIBUTE = 'data-clarity-hashalpha'; // Hoặc attribute bạn đang dùng
931
1290
  // ===================== UTILITY FUNCTIONS =====================
932
1291
  /**
933
1292
  * Lấy bounding box tuyệt đối của element (relative to document)
@@ -970,74 +1329,6 @@ function getElementsAtPoint(documentOrShadowRoot, x, y, filterFunction, visitedS
970
1329
  }
971
1330
  return elementsAtPoint;
972
1331
  }
973
- // ===================== MAIN HOOK =====================
974
- function useHeatmapMouseHandler(props) {
975
- const { heatmapWrapperRef, iframeRef, parentRef, heatmapInfo, scaleRatio, onElementHover } = props;
976
- const handleMouseMove = useCallback((event) => {
977
- // Kiểm tra tất cả refs và data cần thiết
978
- if (!heatmapWrapperRef?.current ||
979
- !iframeRef?.current ||
980
- !iframeRef.current.contentDocument ||
981
- !heatmapInfo?.elementMapInfo ||
982
- !parentRef?.current) {
983
- return;
984
- }
985
- try {
986
- // Tính toán scroll position (đã scale)
987
- const scrollTop = parentRef.current.scrollTop / scaleRatio;
988
- console.log(`🚀 🐥 ~ useHeatmapMouseHandler ~ scrollTop:`, scrollTop);
989
- // Lấy vị trí của heatmap wrapper
990
- const wrapperRect = heatmapWrapperRef.current.getBoundingClientRect();
991
- // Tính toán tọa độ chuột trong iframe (đã scale)
992
- const mouseX = (event.clientX - wrapperRect.left) / scaleRatio;
993
- const mouseY = (event.clientY - wrapperRect.top) / scaleRatio - scrollTop;
994
- // Tìm elements tại vị trí chuột
995
- const elementsAtPoint = getElementsAtPoint(iframeRef.current.contentDocument, Math.round(mouseX), Math.round(mouseY),
996
- // Filter: chỉ lấy elements có heatmap attribute
997
- (element) => element.hasAttribute(HEATMAP_ELEMENT_ATTRIBUTE));
998
- if (!elementsAtPoint || elementsAtPoint.length === 0) {
999
- return;
1000
- }
1001
- // Duyệt qua các elements tìm được
1002
- for (let i = 0; i < elementsAtPoint.length; i++) {
1003
- const element = elementsAtPoint[i];
1004
- // Lấy hash/id của element
1005
- const elementHash = element.getAttribute(HEATMAP_ELEMENT_ATTRIBUTE);
1006
- // Kiểm tra element có data trong heatmapInfo không
1007
- if (elementHash && heatmapInfo.elementMapInfo[elementHash]) {
1008
- const elementData = heatmapInfo.elementMapInfo[elementHash];
1009
- // Lấy bounding box của element
1010
- const boundingBox = getBoundingBox(element);
1011
- if (boundingBox) {
1012
- // Tính rank của element
1013
- const rank = Array.isArray(heatmapInfo.sortedElements) && elementData
1014
- ? heatmapInfo.sortedElements.indexOf(elementData) + 1
1015
- : NaN;
1016
- // Callback với thông tin element
1017
- onElementHover({
1018
- ...boundingBox,
1019
- // Giới hạn width không vượt quá width của heatmap
1020
- width: Math.min(boundingBox.width, heatmapInfo.width || 0),
1021
- // Adjust top position với scroll
1022
- top: boundingBox.top + scrollTop,
1023
- // Metadata
1024
- hash: elementHash,
1025
- clicks: elementData.totalclicks,
1026
- rank: rank,
1027
- selector: elementData.selector || '',
1028
- });
1029
- // Dừng loop khi tìm thấy element hợp lệ đầu tiên
1030
- break;
1031
- }
1032
- }
1033
- }
1034
- }
1035
- catch (error) {
1036
- console.warn('Error handling mouse move on heatmap:', error);
1037
- }
1038
- }, [heatmapWrapperRef, iframeRef, parentRef, heatmapInfo, scaleRatio, onElementHover]);
1039
- return { handleMouseMove };
1040
- }
1041
1332
  // ===================== EXAMPLE USAGE =====================
1042
1333
  /*
1043
1334
  import { useRef, useState } from 'react';
@@ -1291,7 +1582,7 @@ function useVizLiveRender() {
1291
1582
  if (!iframe || !htmlContent)
1292
1583
  return;
1293
1584
  setIsRenderViz(false);
1294
- reset$1(iframe, { width: contentWidth, height: wrapperHeight }, (height) => {
1585
+ reset(iframe, { width: contentWidth, height: wrapperHeight }, (height) => {
1295
1586
  height && setIframeHeight(height);
1296
1587
  setIsRenderViz(true);
1297
1588
  });
@@ -1300,8 +1591,8 @@ function useVizLiveRender() {
1300
1591
  iframeRef,
1301
1592
  };
1302
1593
  }
1303
- function reset$1(iframe, rect, onSuccess) {
1304
- const viewportFixer = initViewportFixer({
1594
+ function reset(iframe, rect, onSuccess) {
1595
+ const fixer = initIframeHelperFixer({
1305
1596
  targetWidth: rect.width,
1306
1597
  targetHeight: rect.height,
1307
1598
  iframe: iframe,
@@ -1310,8 +1601,8 @@ function reset$1(iframe, rect, onSuccess) {
1310
1601
  onSuccess(data.height);
1311
1602
  },
1312
1603
  });
1313
- viewportFixer.recalculate();
1314
- return iframe;
1604
+ // fixer.recalculate();
1605
+ fixer.enableNavigationBlocking();
1315
1606
  }
1316
1607
 
1317
1608
  let visualizer = new Visualizer();
@@ -1329,7 +1620,7 @@ const useHeatmapRender = () => {
1329
1620
  if (!iframe?.contentWindow)
1330
1621
  return;
1331
1622
  await visualizer.html(payloads, iframe.contentWindow);
1332
- reset(iframe, payloads, (height) => {
1623
+ initIframe(iframe, payloads, (height) => {
1333
1624
  height && setIframeHeight(height);
1334
1625
  setIsRenderViz(true);
1335
1626
  setVizRef(visualizer);
@@ -1347,11 +1638,11 @@ const useHeatmapRender = () => {
1347
1638
  iframeRef,
1348
1639
  };
1349
1640
  };
1350
- function reset(iframe, payloads, onSuccess) {
1641
+ function initIframe(iframe, payloads, onSuccess) {
1351
1642
  const { size } = findLastSizeOfDom(payloads);
1352
1643
  const docWidth = size.width ?? 0;
1353
1644
  const docHeight = size.height ?? 0;
1354
- const viewportFixer = initViewportFixer({
1645
+ initIframeHelperFixer({
1355
1646
  targetWidth: docWidth,
1356
1647
  targetHeight: docHeight,
1357
1648
  iframe: iframe,
@@ -1360,8 +1651,7 @@ function reset(iframe, payloads, onSuccess) {
1360
1651
  onSuccess(data.height);
1361
1652
  },
1362
1653
  });
1363
- viewportFixer.recalculate();
1364
- return iframe;
1654
+ // fixer.recalculate();
1365
1655
  }
1366
1656
 
1367
1657
  function isMobileDevice(userAgent) {
@@ -1799,6 +2089,135 @@ const useWrapperRefHeight = (props) => {
1799
2089
  return {};
1800
2090
  };
1801
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
+
1802
2221
  const BoxStack = forwardRef(({ children, ...props }, ref) => {
1803
2222
  const id = props.id;
1804
2223
  const flexDirection = props.flexDirection;
@@ -1903,113 +2322,11 @@ const useClickmap = () => {
1903
2322
  return { start };
1904
2323
  };
1905
2324
 
1906
- const DATA_SCROLLMAP = [
1907
- {
1908
- scrollReachY: 5,
1909
- cumulativeSum: 0,
1910
- percUsers: 0,
1911
- },
1912
- {
1913
- scrollReachY: 10,
1914
- cumulativeSum: 0,
1915
- percUsers: 0,
1916
- },
1917
- {
1918
- scrollReachY: 15,
1919
- cumulativeSum: 0,
1920
- percUsers: 0,
1921
- },
1922
- {
1923
- scrollReachY: 20,
1924
- cumulativeSum: 0,
1925
- percUsers: 0,
1926
- },
1927
- {
1928
- scrollReachY: 25,
1929
- cumulativeSum: 0,
1930
- percUsers: 0,
1931
- },
1932
- {
1933
- scrollReachY: 30,
1934
- cumulativeSum: 0,
1935
- percUsers: 0,
1936
- },
1937
- {
1938
- scrollReachY: 35,
1939
- cumulativeSum: 0,
1940
- percUsers: 0,
1941
- },
1942
- {
1943
- scrollReachY: 40,
1944
- cumulativeSum: 0,
1945
- percUsers: 0,
1946
- },
1947
- {
1948
- scrollReachY: 45,
1949
- cumulativeSum: 0,
1950
- percUsers: 0,
1951
- },
1952
- {
1953
- scrollReachY: 50,
1954
- cumulativeSum: 0,
1955
- percUsers: 0,
1956
- },
1957
- {
1958
- scrollReachY: 55,
1959
- cumulativeSum: 0,
1960
- percUsers: 0,
1961
- },
1962
- {
1963
- scrollReachY: 60,
1964
- cumulativeSum: 0,
1965
- percUsers: 0,
1966
- },
1967
- {
1968
- scrollReachY: 65,
1969
- cumulativeSum: 0,
1970
- percUsers: 0,
1971
- },
1972
- {
1973
- scrollReachY: 70,
1974
- cumulativeSum: 0,
1975
- percUsers: 0,
1976
- },
1977
- {
1978
- scrollReachY: 75,
1979
- cumulativeSum: 0,
1980
- percUsers: 0,
1981
- },
1982
- {
1983
- scrollReachY: 80,
1984
- cumulativeSum: 0,
1985
- percUsers: 0,
1986
- },
1987
- {
1988
- scrollReachY: 85,
1989
- cumulativeSum: 0,
1990
- percUsers: 0,
1991
- },
1992
- {
1993
- scrollReachY: 90,
1994
- cumulativeSum: 0,
1995
- percUsers: 0,
1996
- },
1997
- {
1998
- scrollReachY: 95,
1999
- cumulativeSum: 0,
2000
- percUsers: 0,
2001
- },
2002
- {
2003
- scrollReachY: 100,
2004
- cumulativeSum: 0,
2005
- percUsers: 0,
2006
- },
2007
- ];
2008
2325
  const useScrollmap = () => {
2009
2326
  const vizRef = useHeatmapSingleStore((state) => state.vizRef);
2327
+ const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
2010
2328
  const start = useCallback(() => {
2011
2329
  // if (isInitialized) return;
2012
- const scrollmap = DATA_SCROLLMAP;
2013
2330
  if (!vizRef || !scrollmap || scrollmap.length === 0)
2014
2331
  return;
2015
2332
  try {
@@ -2020,11 +2337,11 @@ const useScrollmap = () => {
2020
2337
  catch (error) {
2021
2338
  console.error(`🚀 🐥 ~ useScrollmap ~ error:`, error);
2022
2339
  }
2023
- }, [vizRef]);
2340
+ }, [vizRef, scrollmap]);
2024
2341
  return { start };
2025
2342
  };
2026
2343
 
2027
- const useHeatmapVizCanvas = () => {
2344
+ const useHeatmapCanvas = ({ iframeRef, }) => {
2028
2345
  const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
2029
2346
  const { start: startClickmap } = useClickmap();
2030
2347
  const { start: startScrollmap } = useScrollmap();
@@ -2034,7 +2351,7 @@ const useHeatmapVizCanvas = () => {
2034
2351
  startClickmap();
2035
2352
  break;
2036
2353
  case IHeatmapType.Scroll:
2037
- startClickmap();
2354
+ startScrollmap();
2038
2355
  break;
2039
2356
  }
2040
2357
  }, [heatmapType, startClickmap, startScrollmap]);
@@ -2166,8 +2483,7 @@ const ELEMENT_CALLOUT = {
2166
2483
  };
2167
2484
  const HeatmapElements = (props) => {
2168
2485
  const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
2169
- const setHoveredElement = useHeatmapInteractionStore((state) => state.setHoveredElement);
2170
- const { iframeRef, wrapperRef, visualRef, visualizer, iframeDimensions, isElementSidebarOpen, isVisible = true, areDefaultRanksHidden, isSecondary, ...rest } = props;
2486
+ const { iframeRef, wrapperRef, visualRef, visualizer, iframeDimensions, isElementSidebarOpen, isVisible = true, areDefaultRanksHidden, isSecondary, } = props;
2171
2487
  const getRect = useHeatmapElementPosition({
2172
2488
  iframeRef,
2173
2489
  wrapperRef,
@@ -2181,27 +2497,6 @@ const HeatmapElements = (props) => {
2181
2497
  iframeRef,
2182
2498
  getRect,
2183
2499
  });
2184
- const heatmapInfo = useHeatmapDataStore((state) => state.dataInfo);
2185
- useHeatmapMouseHandler({
2186
- heatmapWrapperRef: wrapperRef,
2187
- iframeRef,
2188
- parentRef: visualRef,
2189
- heatmapInfo: heatmapInfo || {},
2190
- scaleRatio: 0.8, // 80% zoom
2191
- onElementHover: (info) => {
2192
- setHoveredElement({
2193
- hash: info.hash,
2194
- clicks: info.clicks,
2195
- rank: info.rank,
2196
- selector: info.selector,
2197
- top: info.top,
2198
- left: info.left,
2199
- width: info.width,
2200
- height: info.height,
2201
- });
2202
- console.log(`🚀 🐥 ~ HeatmapElements ~ info:`, info);
2203
- },
2204
- });
2205
2500
  useElementCalloutVisible({
2206
2501
  visualRef,
2207
2502
  getRect,
@@ -2257,6 +2552,293 @@ const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
2257
2552
  } }));
2258
2553
  };
2259
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
+
2260
2842
  const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHeight, onScroll, }) => {
2261
2843
  const contentWidth = useHeatmapConfigStore((state) => state.width);
2262
2844
  const widthScale = useHeatmapVizStore((state) => state.scale);
@@ -2291,6 +2873,7 @@ const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHe
2291
2873
 
2292
2874
  const VizDomRenderer = ({ mode = 'heatmap' }) => {
2293
2875
  const width = useHeatmapConfigStore((state) => state.width);
2876
+ const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
2294
2877
  const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
2295
2878
  const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
2296
2879
  const setSelectedElement = useHeatmapInteractionStore((state) => state.setSelectedElement);
@@ -2308,7 +2891,7 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
2308
2891
  const scrollTop = e.currentTarget.scrollTop;
2309
2892
  handleScroll(scrollTop);
2310
2893
  };
2311
- useHeatmapVizCanvas();
2894
+ useHeatmapCanvas({ iframeRef: iframeRef });
2312
2895
  const cleanUp = () => {
2313
2896
  setIframeHeight(0);
2314
2897
  setSelectedElement(null);
@@ -2316,7 +2899,7 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
2316
2899
  useEffect(() => {
2317
2900
  return cleanUp;
2318
2901
  }, []);
2319
- return (jsxs(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, onScroll: onScroll, iframeHeight: iframeHeight, children: [jsx(VizElements, { iframeRef: iframeRef, visualRef: visualRef, wrapperRef: wrapperRef }), jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: contentWidth, scrolling: "no" })] }));
2902
+ return (jsxs(WrapperVisual, { visualRef: visualRef, wrapperRef: wrapperRef, scaledHeight: scaledHeight, onScroll: onScroll, iframeHeight: iframeHeight, children: [heatmapType === IHeatmapType.Click && (jsx(VizElements, { iframeRef: iframeRef, visualRef: visualRef, wrapperRef: wrapperRef })), jsx("iframe", { ref: iframeRef, ...HEATMAP_IFRAME, width: contentWidth, scrolling: "no" }), jsx(VizScrollMap, { iframeRef: iframeRef, wrapperRef: visualRef })] }));
2320
2903
  };
2321
2904
 
2322
2905
  const VizLoading = () => {
@@ -2423,10 +3006,10 @@ const WrapperLayout = () => {
2423
3006
  return (jsxs(BoxStack, { id: "gx-hm-layout", flexDirection: "column", flex: "1", children: [jsx(ContentTopBar, {}), jsx(WrapperPreview, {})] }));
2424
3007
  };
2425
3008
 
2426
- const HeatmapLayout = ({ data, clickmap, controls, dataInfo, }) => {
3009
+ const HeatmapLayout = ({ data, clickmap, scrollmap, controls, dataInfo, }) => {
2427
3010
  useRegisterControl(controls);
2428
3011
  useRegisterData(data, dataInfo);
2429
- useRegisterHeatmap(clickmap);
3012
+ useRegisterHeatmap({ clickmap, scrollmap });
2430
3013
  useRegisterConfig();
2431
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: {
2432
3015
  minHeight: '100%',
@@ -2441,4 +3024,4 @@ const HeatmapLayout = ({ data, clickmap, controls, dataInfo, }) => {
2441
3024
  }
2442
3025
  };
2443
3026
 
2444
- export { GraphView, HeatmapLayout, IHeatmapType, useHeatmapConfigStore, useHeatmapDataStore, useHeatmapInteractionStore, useHeatmapLiveStore, useHeatmapVizStore };
3027
+ export { GraphView, HeatmapLayout, IClickType, IHeatmapType, IScrollType, useHeatmapConfigStore, useHeatmapDataStore, useHeatmapInteractionStore, useHeatmapLiveStore, useHeatmapVizStore };