@gemx-dev/heatmap-react 3.5.46 → 3.5.47

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