@gemx-dev/heatmap-react 3.5.19 → 3.5.23

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 (456) hide show
  1. package/dist/base.css +3 -0
  2. package/dist/esm/components/GraphView.d.ts +9 -0
  3. package/dist/esm/components/GraphView.d.ts.map +1 -0
  4. package/dist/esm/components/HeatmapLayout/ContentHeader.d.ts +4 -0
  5. package/dist/esm/components/HeatmapLayout/ContentHeader.d.ts.map +1 -0
  6. package/dist/esm/components/HeatmapLayout/HeatmapLayout.d.ts +7 -0
  7. package/dist/esm/components/HeatmapLayout/HeatmapLayout.d.ts.map +1 -0
  8. package/dist/esm/components/HeatmapLayout/LeftSidebar.d.ts +4 -0
  9. package/dist/esm/components/HeatmapLayout/LeftSidebar.d.ts.map +1 -0
  10. package/dist/esm/components/HeatmapLayout/ReplayControls.d.ts +2 -0
  11. package/dist/esm/components/HeatmapLayout/ReplayControls.d.ts.map +1 -0
  12. package/dist/esm/components/HeatmapLayout/VizDomContainer.d.ts +2 -0
  13. package/dist/esm/components/HeatmapLayout/VizDomContainer.d.ts.map +1 -0
  14. package/dist/esm/components/HeatmapLayout/VizDomRenderer.d.ts +6 -0
  15. package/dist/esm/components/HeatmapLayout/VizDomRenderer.d.ts.map +1 -0
  16. package/dist/esm/components/HeatmapLayout/WrapperLayout.d.ts +7 -0
  17. package/dist/esm/components/HeatmapLayout/WrapperLayout.d.ts.map +1 -0
  18. package/dist/esm/components/HeatmapLayout/WrapperPreview.d.ts +4 -0
  19. package/dist/esm/components/HeatmapLayout/WrapperPreview.d.ts.map +1 -0
  20. package/dist/esm/components/HeatmapLayout/index.d.ts +2 -0
  21. package/dist/esm/components/HeatmapLayout/index.d.ts.map +1 -0
  22. package/dist/esm/components/Layout/ContentHeader.d.ts +4 -0
  23. package/dist/esm/components/Layout/ContentHeader.d.ts.map +1 -0
  24. package/dist/esm/components/Layout/HeatmapLayout.d.ts +11 -0
  25. package/dist/esm/components/Layout/HeatmapLayout.d.ts.map +1 -0
  26. package/dist/esm/components/Layout/LeftSidebar.d.ts +4 -0
  27. package/dist/esm/components/Layout/LeftSidebar.d.ts.map +1 -0
  28. package/dist/esm/components/Layout/WrapperLayout.d.ts +8 -0
  29. package/dist/esm/components/Layout/WrapperLayout.d.ts.map +1 -0
  30. package/dist/esm/components/Layout/WrapperPreview.d.ts +4 -0
  31. package/dist/esm/components/Layout/WrapperPreview.d.ts.map +1 -0
  32. package/dist/esm/components/Layout/index.d.ts +2 -0
  33. package/dist/esm/components/Layout/index.d.ts.map +1 -0
  34. package/dist/esm/components/Test.d.ts +121 -0
  35. package/dist/esm/components/Test.d.ts.map +1 -0
  36. package/dist/esm/components/VizDom/ReplayControls.d.ts +2 -0
  37. package/dist/esm/components/VizDom/ReplayControls.d.ts.map +1 -0
  38. package/dist/esm/components/VizDom/VizDomContainer.d.ts +2 -0
  39. package/dist/esm/components/VizDom/VizDomContainer.d.ts.map +1 -0
  40. package/dist/esm/components/VizDom/VizDomRenderer.d.ts +6 -0
  41. package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -0
  42. package/dist/esm/components/VizDom/index.d.ts +2 -0
  43. package/dist/esm/components/VizDom/index.d.ts.map +1 -0
  44. package/dist/esm/components/VizElement/ClarityVisualizer.d.ts +150 -0
  45. package/dist/esm/components/VizElement/ClarityVisualizer.d.ts.map +1 -0
  46. package/dist/esm/components/VizElement/ClickedElementOverlay.d.ts +17 -0
  47. package/dist/esm/components/VizElement/ClickedElementOverlay.d.ts.map +1 -0
  48. package/dist/esm/components/VizElement/DefaultRankBadges.d.ts +11 -0
  49. package/dist/esm/components/VizElement/DefaultRankBadges.d.ts.map +1 -0
  50. package/dist/esm/components/VizElement/ElementCallout.d.ts +17 -0
  51. package/dist/esm/components/VizElement/ElementCallout.d.ts.map +1 -0
  52. package/dist/esm/components/VizElement/HeatmapElementV2.d.ts +45 -0
  53. package/dist/esm/components/VizElement/HeatmapElementV2.d.ts.map +1 -0
  54. package/dist/esm/components/VizElement/HeatmapElements.d.ts +23 -0
  55. package/dist/esm/components/VizElement/HeatmapElements.d.ts.map +1 -0
  56. package/dist/esm/components/VizElement/HoveredElementOverlay.d.ts +12 -0
  57. package/dist/esm/components/VizElement/HoveredElementOverlay.d.ts.map +1 -0
  58. package/dist/esm/components/VizElement/MissingElementMessage.d.ts +7 -0
  59. package/dist/esm/components/VizElement/MissingElementMessage.d.ts.map +1 -0
  60. package/dist/esm/components/VizElement/PayloadProcessor.d.ts +65 -0
  61. package/dist/esm/components/VizElement/PayloadProcessor.d.ts.map +1 -0
  62. package/dist/esm/components/VizElement/RankBadge.d.ts +10 -0
  63. package/dist/esm/components/VizElement/RankBadge.d.ts.map +1 -0
  64. package/dist/esm/components/VizElement/VizElementRank.d.ts +74 -0
  65. package/dist/esm/components/VizElement/VizElementRank.d.ts.map +1 -0
  66. package/dist/esm/components/VizElement/VizElements.d.ts +10 -0
  67. package/dist/esm/components/VizElement/VizElements.d.ts.map +1 -0
  68. package/dist/esm/components/VizElement/constants.d.ts +5 -0
  69. package/dist/esm/components/VizElement/constants.d.ts.map +1 -0
  70. package/dist/esm/components/VizElement/helpers.d.ts +20 -0
  71. package/dist/esm/components/VizElement/helpers.d.ts.map +1 -0
  72. package/dist/esm/components/VizElement/index.d.ts +2 -0
  73. package/dist/esm/components/VizElement/index.d.ts.map +1 -0
  74. package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts +150 -0
  75. package/dist/esm/components/VizElement/temp/ClarityVisualizer.d.ts.map +1 -0
  76. package/dist/esm/components/VizElement/temp/VizElementRank.d.ts +74 -0
  77. package/dist/esm/components/VizElement/temp/VizElementRank.d.ts.map +1 -0
  78. package/dist/esm/components/VizElement/types.d.ts +13 -0
  79. package/dist/esm/components/VizElement/types.d.ts.map +1 -0
  80. package/dist/esm/components/index.d.ts +4 -0
  81. package/dist/esm/components/index.d.ts.map +1 -0
  82. package/dist/esm/configs/iframe.d.ts +10 -0
  83. package/dist/esm/configs/iframe.d.ts.map +1 -0
  84. package/dist/esm/configs/index.d.ts +3 -0
  85. package/dist/esm/configs/index.d.ts.map +1 -0
  86. package/dist/esm/configs/style.d.ts +9 -0
  87. package/dist/esm/configs/style.d.ts.map +1 -0
  88. package/dist/esm/constants/index.d.ts +5 -0
  89. package/dist/esm/constants/index.d.ts.map +1 -0
  90. package/dist/esm/helpers/iframe.d.ts +3 -0
  91. package/dist/esm/helpers/iframe.d.ts.map +1 -0
  92. package/dist/esm/helpers/index.d.ts +2 -0
  93. package/dist/esm/helpers/index.d.ts.map +1 -0
  94. package/dist/esm/helpers/viz-elements.d.ts +10 -0
  95. package/dist/esm/helpers/viz-elements.d.ts.map +1 -0
  96. package/dist/esm/hooks/index.d.ts +4 -0
  97. package/dist/esm/hooks/index.d.ts.map +1 -0
  98. package/dist/esm/hooks/useHeatmapByMode.d.ts +6 -0
  99. package/dist/esm/hooks/useHeatmapByMode.d.ts.map +1 -0
  100. package/dist/esm/hooks/useHeatmapRender.d.ts +6 -0
  101. package/dist/esm/hooks/useHeatmapRender.d.ts.map +1 -0
  102. package/dist/esm/hooks/useHeatmapScale.d.ts +28 -0
  103. package/dist/esm/hooks/useHeatmapScale.d.ts.map +1 -0
  104. package/dist/esm/hooks/useReplayRender.d.ts +9 -0
  105. package/dist/esm/hooks/useReplayRender.d.ts.map +1 -0
  106. package/dist/esm/hooks/vix-elements/index.d.ts +5 -0
  107. package/dist/esm/hooks/vix-elements/index.d.ts.map +1 -0
  108. package/dist/esm/hooks/vix-elements/useClickedElement.d.ts +14 -0
  109. package/dist/esm/hooks/vix-elements/useClickedElement.d.ts.map +1 -0
  110. package/dist/esm/hooks/vix-elements/useHeatmapEffects.d.ts +8 -0
  111. package/dist/esm/hooks/vix-elements/useHeatmapEffects.d.ts.map +1 -0
  112. package/dist/esm/hooks/vix-elements/useHeatmapElementPosition.d.ts +13 -0
  113. package/dist/esm/hooks/vix-elements/useHeatmapElementPosition.d.ts.map +1 -0
  114. package/dist/esm/hooks/vix-elements/useHoveredElement.d.ts +17 -0
  115. package/dist/esm/hooks/vix-elements/useHoveredElement.d.ts.map +1 -0
  116. package/dist/esm/hooks/viz-render/index.d.ts +2 -0
  117. package/dist/esm/hooks/viz-render/index.d.ts.map +1 -0
  118. package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts +8 -0
  119. package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -0
  120. package/dist/esm/hooks/viz-render/useHeatmapVizRender.d.ts +8 -0
  121. package/dist/esm/hooks/viz-render/useHeatmapVizRender.d.ts.map +1 -0
  122. package/dist/esm/hooks/viz-render/useReplayRender.d.ts +11 -0
  123. package/dist/esm/hooks/viz-render/useReplayRender.d.ts.map +1 -0
  124. package/dist/esm/hooks/viz-scale/index.d.ts +2 -0
  125. package/dist/esm/hooks/viz-scale/index.d.ts.map +1 -0
  126. package/dist/esm/hooks/viz-scale/useContainerDimensions.d.ts +10 -0
  127. package/dist/esm/hooks/viz-scale/useContainerDimensions.d.ts.map +1 -0
  128. package/dist/esm/hooks/viz-scale/useContentDimensions.d.ts +11 -0
  129. package/dist/esm/hooks/viz-scale/useContentDimensions.d.ts.map +1 -0
  130. package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts +19 -0
  131. package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -0
  132. package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts +10 -0
  133. package/dist/esm/hooks/viz-scale/useIframeHeight.d.ts.map +1 -0
  134. package/dist/esm/hooks/viz-scale/useScaleCalculation.d.ts +10 -0
  135. package/dist/esm/hooks/viz-scale/useScaleCalculation.d.ts.map +1 -0
  136. package/dist/esm/hooks/viz-scale/useScrollSync.d.ts +10 -0
  137. package/dist/esm/hooks/viz-scale/useScrollSync.d.ts.map +1 -0
  138. package/dist/esm/index.d.ts +4 -0
  139. package/dist/esm/index.d.ts.map +1 -0
  140. package/dist/esm/index.js +1303 -0
  141. package/dist/esm/index.mjs +1303 -0
  142. package/dist/esm/stores/data.d.ts +18 -0
  143. package/dist/esm/stores/data.d.ts.map +1 -0
  144. package/dist/esm/stores/index.d.ts +2 -0
  145. package/dist/esm/stores/index.d.ts.map +1 -0
  146. package/dist/esm/types/index.d.ts +3 -0
  147. package/dist/esm/types/index.d.ts.map +1 -0
  148. package/dist/esm/ui/BoxStack/BoxStack.d.ts +56 -0
  149. package/dist/esm/ui/BoxStack/BoxStack.d.ts.map +1 -0
  150. package/dist/esm/ui/BoxStack/index.d.ts +2 -0
  151. package/dist/esm/ui/BoxStack/index.d.ts.map +1 -0
  152. package/dist/esm/ui/index.d.ts +2 -0
  153. package/dist/esm/ui/index.d.ts.map +1 -0
  154. package/dist/esm/utils/device.d.ts +2 -0
  155. package/dist/esm/utils/device.d.ts.map +1 -0
  156. package/dist/esm/utils/retry.d.ts +2 -0
  157. package/dist/esm/utils/retry.d.ts.map +1 -0
  158. package/dist/esm/utils/sort.d.ts +3 -0
  159. package/dist/esm/utils/sort.d.ts.map +1 -0
  160. package/dist/style.css +32 -0
  161. package/dist/umd/components/GraphView.d.ts +9 -0
  162. package/dist/umd/components/GraphView.d.ts.map +1 -0
  163. package/dist/umd/components/Layout/ContentHeader.d.ts +4 -0
  164. package/dist/umd/components/Layout/ContentHeader.d.ts.map +1 -0
  165. package/dist/umd/components/Layout/HeatmapLayout.d.ts +11 -0
  166. package/dist/umd/components/Layout/HeatmapLayout.d.ts.map +1 -0
  167. package/dist/umd/components/Layout/LeftSidebar.d.ts +4 -0
  168. package/dist/umd/components/Layout/LeftSidebar.d.ts.map +1 -0
  169. package/dist/umd/components/Layout/WrapperLayout.d.ts +8 -0
  170. package/dist/umd/components/Layout/WrapperLayout.d.ts.map +1 -0
  171. package/dist/umd/components/Layout/WrapperPreview.d.ts +4 -0
  172. package/dist/umd/components/Layout/WrapperPreview.d.ts.map +1 -0
  173. package/dist/umd/components/Layout/index.d.ts +2 -0
  174. package/dist/umd/components/Layout/index.d.ts.map +1 -0
  175. package/dist/umd/components/Test.d.ts +121 -0
  176. package/dist/umd/components/Test.d.ts.map +1 -0
  177. package/dist/umd/components/VizDom/ReplayControls.d.ts +2 -0
  178. package/dist/umd/components/VizDom/ReplayControls.d.ts.map +1 -0
  179. package/dist/umd/components/VizDom/VizDomContainer.d.ts +2 -0
  180. package/dist/umd/components/VizDom/VizDomContainer.d.ts.map +1 -0
  181. package/dist/umd/components/VizDom/VizDomRenderer.d.ts +6 -0
  182. package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -0
  183. package/dist/umd/components/VizDom/index.d.ts +2 -0
  184. package/dist/umd/components/VizDom/index.d.ts.map +1 -0
  185. package/dist/umd/components/VizElement/ClickedElementOverlay.d.ts +17 -0
  186. package/dist/umd/components/VizElement/ClickedElementOverlay.d.ts.map +1 -0
  187. package/dist/umd/components/VizElement/DefaultRankBadges.d.ts +11 -0
  188. package/dist/umd/components/VizElement/DefaultRankBadges.d.ts.map +1 -0
  189. package/dist/umd/components/VizElement/ElementCallout.d.ts +17 -0
  190. package/dist/umd/components/VizElement/ElementCallout.d.ts.map +1 -0
  191. package/dist/umd/components/VizElement/HeatmapElements.d.ts +23 -0
  192. package/dist/umd/components/VizElement/HeatmapElements.d.ts.map +1 -0
  193. package/dist/umd/components/VizElement/HoveredElementOverlay.d.ts +12 -0
  194. package/dist/umd/components/VizElement/HoveredElementOverlay.d.ts.map +1 -0
  195. package/dist/umd/components/VizElement/MissingElementMessage.d.ts +7 -0
  196. package/dist/umd/components/VizElement/MissingElementMessage.d.ts.map +1 -0
  197. package/dist/umd/components/VizElement/RankBadge.d.ts +10 -0
  198. package/dist/umd/components/VizElement/RankBadge.d.ts.map +1 -0
  199. package/dist/umd/components/VizElement/VizElementRank.d.ts +75 -0
  200. package/dist/umd/components/VizElement/VizElementRank.d.ts.map +1 -0
  201. package/dist/umd/components/VizElement/VizElements.d.ts +10 -0
  202. package/dist/umd/components/VizElement/VizElements.d.ts.map +1 -0
  203. package/dist/umd/components/VizElement/index.d.ts +2 -0
  204. package/dist/umd/components/VizElement/index.d.ts.map +1 -0
  205. package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts +150 -0
  206. package/dist/umd/components/VizElement/temp/ClarityVisualizer.d.ts.map +1 -0
  207. package/dist/umd/components/VizElement/temp/VizElementRank.d.ts +74 -0
  208. package/dist/umd/components/VizElement/temp/VizElementRank.d.ts.map +1 -0
  209. package/dist/umd/components/index.d.ts +4 -0
  210. package/dist/umd/components/index.d.ts.map +1 -0
  211. package/dist/umd/configs/iframe.d.ts +10 -0
  212. package/dist/umd/configs/iframe.d.ts.map +1 -0
  213. package/dist/umd/configs/index.d.ts +3 -0
  214. package/dist/umd/configs/index.d.ts.map +1 -0
  215. package/dist/umd/configs/style.d.ts +9 -0
  216. package/dist/umd/configs/style.d.ts.map +1 -0
  217. package/dist/umd/constants/index.d.ts +5 -0
  218. package/dist/umd/constants/index.d.ts.map +1 -0
  219. package/dist/umd/helpers/iframe.d.ts +3 -0
  220. package/dist/umd/helpers/iframe.d.ts.map +1 -0
  221. package/dist/umd/helpers/index.d.ts +2 -0
  222. package/dist/umd/helpers/index.d.ts.map +1 -0
  223. package/dist/umd/helpers/viz-elements.d.ts +10 -0
  224. package/dist/umd/helpers/viz-elements.d.ts.map +1 -0
  225. package/dist/umd/hooks/index.d.ts +4 -0
  226. package/dist/umd/hooks/index.d.ts.map +1 -0
  227. package/dist/umd/hooks/vix-elements/index.d.ts +5 -0
  228. package/dist/umd/hooks/vix-elements/index.d.ts.map +1 -0
  229. package/dist/umd/hooks/vix-elements/useClickedElement.d.ts +14 -0
  230. package/dist/umd/hooks/vix-elements/useClickedElement.d.ts.map +1 -0
  231. package/dist/umd/hooks/vix-elements/useHeatmapEffects.d.ts +8 -0
  232. package/dist/umd/hooks/vix-elements/useHeatmapEffects.d.ts.map +1 -0
  233. package/dist/umd/hooks/vix-elements/useHeatmapElementPosition.d.ts +13 -0
  234. package/dist/umd/hooks/vix-elements/useHeatmapElementPosition.d.ts.map +1 -0
  235. package/dist/umd/hooks/vix-elements/useHoveredElement.d.ts +17 -0
  236. package/dist/umd/hooks/vix-elements/useHoveredElement.d.ts.map +1 -0
  237. package/dist/umd/hooks/viz-render/index.d.ts +2 -0
  238. package/dist/umd/hooks/viz-render/index.d.ts.map +1 -0
  239. package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts +8 -0
  240. package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -0
  241. package/dist/umd/hooks/viz-render/useHeatmapVizRender.d.ts +8 -0
  242. package/dist/umd/hooks/viz-render/useHeatmapVizRender.d.ts.map +1 -0
  243. package/dist/umd/hooks/viz-render/useReplayRender.d.ts +11 -0
  244. package/dist/umd/hooks/viz-render/useReplayRender.d.ts.map +1 -0
  245. package/dist/umd/hooks/viz-scale/index.d.ts +2 -0
  246. package/dist/umd/hooks/viz-scale/index.d.ts.map +1 -0
  247. package/dist/umd/hooks/viz-scale/useContainerDimensions.d.ts +10 -0
  248. package/dist/umd/hooks/viz-scale/useContainerDimensions.d.ts.map +1 -0
  249. package/dist/umd/hooks/viz-scale/useContentDimensions.d.ts +11 -0
  250. package/dist/umd/hooks/viz-scale/useContentDimensions.d.ts.map +1 -0
  251. package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts +19 -0
  252. package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -0
  253. package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts +10 -0
  254. package/dist/umd/hooks/viz-scale/useIframeHeight.d.ts.map +1 -0
  255. package/dist/umd/hooks/viz-scale/useScaleCalculation.d.ts +10 -0
  256. package/dist/umd/hooks/viz-scale/useScaleCalculation.d.ts.map +1 -0
  257. package/dist/umd/hooks/viz-scale/useScrollSync.d.ts +10 -0
  258. package/dist/umd/hooks/viz-scale/useScrollSync.d.ts.map +1 -0
  259. package/dist/umd/index.d.ts +4 -0
  260. package/dist/umd/index.d.ts.map +1 -0
  261. package/dist/umd/index.js +10 -0
  262. package/dist/umd/stores/data.d.ts +18 -0
  263. package/dist/umd/stores/data.d.ts.map +1 -0
  264. package/dist/umd/stores/index.d.ts +2 -0
  265. package/dist/umd/stores/index.d.ts.map +1 -0
  266. package/dist/umd/ui/BoxStack/BoxStack.d.ts +56 -0
  267. package/dist/umd/ui/BoxStack/BoxStack.d.ts.map +1 -0
  268. package/dist/umd/ui/BoxStack/index.d.ts +2 -0
  269. package/dist/umd/ui/BoxStack/index.d.ts.map +1 -0
  270. package/dist/umd/ui/index.d.ts +2 -0
  271. package/dist/umd/ui/index.d.ts.map +1 -0
  272. package/dist/umd/utils/device.d.ts +2 -0
  273. package/dist/umd/utils/device.d.ts.map +1 -0
  274. package/dist/umd/utils/retry.d.ts +2 -0
  275. package/dist/umd/utils/retry.d.ts.map +1 -0
  276. package/dist/umd/utils/sort.d.ts +3 -0
  277. package/dist/umd/utils/sort.d.ts.map +1 -0
  278. package/package.json +11 -14
  279. package/src/components/GraphView.tsx +58 -0
  280. package/src/components/Layout/ContentHeader.tsx +15 -0
  281. package/src/components/Layout/HeatmapLayout.tsx +63 -0
  282. package/src/components/Layout/LeftSidebar.tsx +32 -0
  283. package/src/components/Layout/WrapperLayout.tsx +18 -0
  284. package/src/components/Layout/WrapperPreview.tsx +14 -0
  285. package/src/components/Layout/index.ts +1 -0
  286. package/src/components/Test.tsx +1106 -0
  287. package/src/components/VizDom/ReplayControls.tsx +48 -0
  288. package/src/components/VizDom/VizDomContainer.tsx +25 -0
  289. package/src/components/VizDom/VizDomRenderer.tsx +87 -0
  290. package/src/components/VizDom/index.ts +1 -0
  291. package/src/components/VizElement/ClickedElementOverlay.tsx +65 -0
  292. package/src/components/VizElement/DefaultRankBadges.tsx +33 -0
  293. package/src/components/VizElement/ElementCallout.tsx +337 -0
  294. package/src/components/VizElement/HeatmapElements.tsx +147 -0
  295. package/src/components/VizElement/HoveredElementOverlay.tsx +46 -0
  296. package/src/components/VizElement/MissingElementMessage.tsx +32 -0
  297. package/src/components/VizElement/RankBadge.tsx +25 -0
  298. package/src/components/VizElement/VizElements.tsx +80 -0
  299. package/src/components/VizElement/index.ts +1 -0
  300. package/src/components/VizElement/temp/ClarityVisualizer.ts +764 -0
  301. package/src/components/VizElement/temp/VizElementRank.tsx +579 -0
  302. package/src/components/index.tsx +4 -0
  303. package/src/configs/iframe.ts +15 -0
  304. package/src/configs/index.ts +2 -0
  305. package/src/configs/style.ts +9 -0
  306. package/src/constants/index.ts +4 -0
  307. package/src/dist/components/GraphView.d.ts +9 -0
  308. package/src/dist/components/GraphView.d.ts.map +1 -0
  309. package/src/dist/components/Layout/ContentHeader.d.ts +4 -0
  310. package/src/dist/components/Layout/ContentHeader.d.ts.map +1 -0
  311. package/src/dist/components/Layout/HeatmapLayout.d.ts +11 -0
  312. package/src/dist/components/Layout/HeatmapLayout.d.ts.map +1 -0
  313. package/src/dist/components/Layout/LeftSidebar.d.ts +4 -0
  314. package/src/dist/components/Layout/LeftSidebar.d.ts.map +1 -0
  315. package/src/dist/components/Layout/WrapperLayout.d.ts +8 -0
  316. package/src/dist/components/Layout/WrapperLayout.d.ts.map +1 -0
  317. package/src/dist/components/Layout/WrapperPreview.d.ts +4 -0
  318. package/src/dist/components/Layout/WrapperPreview.d.ts.map +1 -0
  319. package/src/dist/components/Layout/index.d.ts +2 -0
  320. package/src/dist/components/Layout/index.d.ts.map +1 -0
  321. package/src/dist/components/Test.d.ts +121 -0
  322. package/src/dist/components/Test.d.ts.map +1 -0
  323. package/src/dist/components/VizDom/ReplayControls.d.ts +2 -0
  324. package/src/dist/components/VizDom/ReplayControls.d.ts.map +1 -0
  325. package/src/dist/components/VizDom/VizDomContainer.d.ts +2 -0
  326. package/src/dist/components/VizDom/VizDomContainer.d.ts.map +1 -0
  327. package/src/dist/components/VizDom/VizDomRenderer.d.ts +6 -0
  328. package/src/dist/components/VizDom/VizDomRenderer.d.ts.map +1 -0
  329. package/src/dist/components/VizDom/index.d.ts +2 -0
  330. package/src/dist/components/VizDom/index.d.ts.map +1 -0
  331. package/src/dist/components/VizElement/ClickedElementOverlay.d.ts +17 -0
  332. package/src/dist/components/VizElement/ClickedElementOverlay.d.ts.map +1 -0
  333. package/src/dist/components/VizElement/DefaultRankBadges.d.ts +11 -0
  334. package/src/dist/components/VizElement/DefaultRankBadges.d.ts.map +1 -0
  335. package/src/dist/components/VizElement/ElementCallout.d.ts +17 -0
  336. package/src/dist/components/VizElement/ElementCallout.d.ts.map +1 -0
  337. package/src/dist/components/VizElement/HeatmapElements.d.ts +23 -0
  338. package/src/dist/components/VizElement/HeatmapElements.d.ts.map +1 -0
  339. package/src/dist/components/VizElement/HoveredElementOverlay.d.ts +12 -0
  340. package/src/dist/components/VizElement/HoveredElementOverlay.d.ts.map +1 -0
  341. package/src/dist/components/VizElement/MissingElementMessage.d.ts +7 -0
  342. package/src/dist/components/VizElement/MissingElementMessage.d.ts.map +1 -0
  343. package/src/dist/components/VizElement/RankBadge.d.ts +10 -0
  344. package/src/dist/components/VizElement/RankBadge.d.ts.map +1 -0
  345. package/src/dist/components/VizElement/VizElements.d.ts +10 -0
  346. package/src/dist/components/VizElement/VizElements.d.ts.map +1 -0
  347. package/src/dist/components/VizElement/index.d.ts +2 -0
  348. package/src/dist/components/VizElement/index.d.ts.map +1 -0
  349. package/src/dist/components/VizElement/temp/ClarityVisualizer.d.ts +150 -0
  350. package/src/dist/components/VizElement/temp/ClarityVisualizer.d.ts.map +1 -0
  351. package/src/dist/components/VizElement/temp/VizElementRank.d.ts +74 -0
  352. package/src/dist/components/VizElement/temp/VizElementRank.d.ts.map +1 -0
  353. package/src/dist/components/index.d.ts +4 -0
  354. package/src/dist/components/index.d.ts.map +1 -0
  355. package/src/dist/configs/iframe.d.ts +10 -0
  356. package/src/dist/configs/iframe.d.ts.map +1 -0
  357. package/src/dist/configs/index.d.ts +3 -0
  358. package/src/dist/configs/index.d.ts.map +1 -0
  359. package/src/dist/configs/style.d.ts +9 -0
  360. package/src/dist/configs/style.d.ts.map +1 -0
  361. package/src/dist/constants/index.d.ts +5 -0
  362. package/src/dist/constants/index.d.ts.map +1 -0
  363. package/src/dist/helpers/iframe.d.ts +3 -0
  364. package/src/dist/helpers/iframe.d.ts.map +1 -0
  365. package/src/dist/helpers/index.d.ts +2 -0
  366. package/src/dist/helpers/index.d.ts.map +1 -0
  367. package/src/dist/helpers/viz-elements.d.ts +10 -0
  368. package/src/dist/helpers/viz-elements.d.ts.map +1 -0
  369. package/src/dist/hooks/index.d.ts +4 -0
  370. package/src/dist/hooks/index.d.ts.map +1 -0
  371. package/src/dist/hooks/vix-elements/index.d.ts +5 -0
  372. package/src/dist/hooks/vix-elements/index.d.ts.map +1 -0
  373. package/src/dist/hooks/vix-elements/useClickedElement.d.ts +14 -0
  374. package/src/dist/hooks/vix-elements/useClickedElement.d.ts.map +1 -0
  375. package/src/dist/hooks/vix-elements/useHeatmapEffects.d.ts +8 -0
  376. package/src/dist/hooks/vix-elements/useHeatmapEffects.d.ts.map +1 -0
  377. package/src/dist/hooks/vix-elements/useHeatmapElementPosition.d.ts +13 -0
  378. package/src/dist/hooks/vix-elements/useHeatmapElementPosition.d.ts.map +1 -0
  379. package/src/dist/hooks/vix-elements/useHoveredElement.d.ts +17 -0
  380. package/src/dist/hooks/vix-elements/useHoveredElement.d.ts.map +1 -0
  381. package/src/dist/hooks/viz-render/index.d.ts +2 -0
  382. package/src/dist/hooks/viz-render/index.d.ts.map +1 -0
  383. package/src/dist/hooks/viz-render/useHeatmapRender.d.ts +8 -0
  384. package/src/dist/hooks/viz-render/useHeatmapRender.d.ts.map +1 -0
  385. package/src/dist/hooks/viz-render/useHeatmapVizRender.d.ts +8 -0
  386. package/src/dist/hooks/viz-render/useHeatmapVizRender.d.ts.map +1 -0
  387. package/src/dist/hooks/viz-render/useReplayRender.d.ts +11 -0
  388. package/src/dist/hooks/viz-render/useReplayRender.d.ts.map +1 -0
  389. package/src/dist/hooks/viz-scale/index.d.ts +2 -0
  390. package/src/dist/hooks/viz-scale/index.d.ts.map +1 -0
  391. package/src/dist/hooks/viz-scale/useContainerDimensions.d.ts +10 -0
  392. package/src/dist/hooks/viz-scale/useContainerDimensions.d.ts.map +1 -0
  393. package/src/dist/hooks/viz-scale/useContentDimensions.d.ts +11 -0
  394. package/src/dist/hooks/viz-scale/useContentDimensions.d.ts.map +1 -0
  395. package/src/dist/hooks/viz-scale/useHeatmapScale.d.ts +19 -0
  396. package/src/dist/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -0
  397. package/src/dist/hooks/viz-scale/useIframeHeight.d.ts +10 -0
  398. package/src/dist/hooks/viz-scale/useIframeHeight.d.ts.map +1 -0
  399. package/src/dist/hooks/viz-scale/useScaleCalculation.d.ts +10 -0
  400. package/src/dist/hooks/viz-scale/useScaleCalculation.d.ts.map +1 -0
  401. package/src/dist/hooks/viz-scale/useScrollSync.d.ts +10 -0
  402. package/src/dist/hooks/viz-scale/useScrollSync.d.ts.map +1 -0
  403. package/src/dist/index.d.ts +4 -0
  404. package/src/dist/index.d.ts.map +1 -0
  405. package/src/dist/stores/data.d.ts +18 -0
  406. package/src/dist/stores/data.d.ts.map +1 -0
  407. package/src/dist/stores/index.d.ts +2 -0
  408. package/src/dist/stores/index.d.ts.map +1 -0
  409. package/src/dist/ui/BoxStack/BoxStack.d.ts +56 -0
  410. package/src/dist/ui/BoxStack/BoxStack.d.ts.map +1 -0
  411. package/src/dist/ui/BoxStack/index.d.ts +2 -0
  412. package/src/dist/ui/BoxStack/index.d.ts.map +1 -0
  413. package/src/dist/ui/index.d.ts +2 -0
  414. package/src/dist/ui/index.d.ts.map +1 -0
  415. package/src/dist/utils/device.d.ts +2 -0
  416. package/src/dist/utils/device.d.ts.map +1 -0
  417. package/src/dist/utils/retry.d.ts +2 -0
  418. package/src/dist/utils/retry.d.ts.map +1 -0
  419. package/src/dist/utils/sort.d.ts +3 -0
  420. package/src/dist/utils/sort.d.ts.map +1 -0
  421. package/src/global.d.ts +5 -0
  422. package/src/helpers/iframe.ts +33 -0
  423. package/src/helpers/index.ts +1 -0
  424. package/src/helpers/viz-elements.ts +34 -0
  425. package/src/hooks/index.ts +3 -0
  426. package/src/hooks/vix-elements/index.ts +4 -0
  427. package/src/hooks/vix-elements/useClickedElement.ts +62 -0
  428. package/src/hooks/vix-elements/useHeatmapEffects.ts +29 -0
  429. package/src/hooks/vix-elements/useHeatmapElementPosition.ts +66 -0
  430. package/src/hooks/vix-elements/useHoveredElement.ts +135 -0
  431. package/src/hooks/viz-render/index.ts +1 -0
  432. package/src/hooks/viz-render/useHeatmapRender.ts +98 -0
  433. package/src/hooks/viz-render/useHeatmapVizRender.ts +22 -0
  434. package/src/hooks/viz-render/useReplayRender.ts +162 -0
  435. package/src/hooks/viz-scale/index.ts +1 -0
  436. package/src/hooks/viz-scale/useContainerDimensions.ts +46 -0
  437. package/src/hooks/viz-scale/useContentDimensions.ts +29 -0
  438. package/src/hooks/viz-scale/useHeatmapScale.ts +53 -0
  439. package/src/hooks/viz-scale/useIframeHeight.ts +119 -0
  440. package/src/hooks/viz-scale/useScaleCalculation.ts +28 -0
  441. package/src/hooks/viz-scale/useScrollSync.ts +36 -0
  442. package/src/index.ts +5 -0
  443. package/src/stores/data.ts +34 -0
  444. package/src/stores/index.ts +1 -0
  445. package/src/styles/base.css +1 -0
  446. package/src/styles/style.css +30 -0
  447. package/src/types/clarity.d.ts +38 -0
  448. package/src/types/heatmap.d.ts +3 -0
  449. package/src/types/index.d.ts +3 -0
  450. package/src/types/viz-element.d.ts +39 -0
  451. package/src/ui/BoxStack/BoxStack.tsx +120 -0
  452. package/src/ui/BoxStack/index.ts +1 -0
  453. package/src/ui/index.ts +1 -0
  454. package/src/utils/device.ts +7 -0
  455. package/src/utils/retry.ts +20 -0
  456. package/src/utils/sort.ts +5 -0
@@ -0,0 +1,1106 @@
1
+ import React, { Component, RefObject, useCallback, useEffect, useRef, useState } from 'react';
2
+
3
+ // ===== Type Definitions =====
4
+
5
+ interface IHeatmapConfig {
6
+ attentionMapInfo?: any[];
7
+ height?: number;
8
+ width?: number;
9
+ }
10
+
11
+ interface ImpressionData {
12
+ documentHeight?: number;
13
+ device?: string;
14
+ url?: string;
15
+ sessionId?: string;
16
+ userId?: string;
17
+ pageNum?: string;
18
+ timestamp?: number;
19
+ duration?: number;
20
+ playbackTokenA?: string;
21
+ playbackTokenB?: string;
22
+ }
23
+
24
+ interface TimelineItem {
25
+ key: string;
26
+ pageNum?: string;
27
+ impressionData?: ImpressionData;
28
+ isDead?: boolean;
29
+ isMissing?: boolean;
30
+ failedToFetch?: boolean;
31
+ }
32
+
33
+ interface MergedPayload {
34
+ events: any[];
35
+ }
36
+
37
+ interface ActiveDuration {
38
+ startTime: number;
39
+ duration: number;
40
+ active: boolean;
41
+ }
42
+
43
+ enum PanelContent {
44
+ Sessions = 'Sessions',
45
+ Timeline = 'Timeline',
46
+ Area = 'Area',
47
+ Click = 'Click',
48
+ Scroll = 'Scroll',
49
+ Attention = 'Attention',
50
+ }
51
+
52
+ enum ErrorType {
53
+ NoResults = 'NoResults',
54
+ NoClicks = 'NoClicks',
55
+ NoScroll = 'NoScroll',
56
+ ServerError = 'ServerError',
57
+ DataError = 'DataError',
58
+ }
59
+
60
+ interface Visualizer {
61
+ merge: (data: any[]) => MergedPayload;
62
+ }
63
+
64
+ interface HeatmapVisualizer {
65
+ attention: (data: any[]) => any;
66
+ }
67
+
68
+ // ===== Utility Functions =====
69
+
70
+ const hideInteractionElements = (iframe: HTMLIFrameElement | null, shouldHide: boolean): void => {
71
+ const canvas = iframe?.contentWindow?.document?.getElementById('clarity-interaction-canvas');
72
+ const pointer = iframe?.contentWindow?.document?.getElementById('clarity-pointer');
73
+ const clicks = iframe?.contentWindow?.document?.getElementsByClassName('clarity-click');
74
+
75
+ if (shouldHide) {
76
+ if (canvas) canvas.style.display = 'none';
77
+ if (pointer) pointer.style.display = 'none';
78
+ if (clicks) {
79
+ for (let i = 0; i < clicks.length; i++) {
80
+ (clicks[i] as HTMLElement).style.display = 'none';
81
+ }
82
+ }
83
+ } else {
84
+ if (canvas) canvas.style.display = '';
85
+ if (pointer) pointer.style.display = '';
86
+ if (clicks) {
87
+ for (let i = 0; i < clicks.length; i++) {
88
+ (clicks[i] as HTMLElement).style.display = '';
89
+ }
90
+ }
91
+ }
92
+ };
93
+
94
+ const clearHeatmapCanvas = (iframe: HTMLIFrameElement | null, heatmapVisualizer?: any): void => {
95
+ const canvas = iframe?.contentWindow?.document?.getElementById('clarity-heatmap-canvas');
96
+ const areaMap = iframe?.contentWindow?.document?.getElementById('clarity-area-map');
97
+
98
+ if ((canvas || areaMap) && heatmapVisualizer) {
99
+ heatmapVisualizer.clearmap();
100
+ }
101
+
102
+ if (canvas?.parentNode) {
103
+ canvas.parentNode.removeChild(canvas);
104
+ }
105
+ };
106
+
107
+ // ===== Heatmap Renderer Component =====
108
+
109
+ interface HeatmapPoint {
110
+ x: number;
111
+ y: number;
112
+ value: number;
113
+ timestamp?: number;
114
+ }
115
+
116
+ interface ClickData {
117
+ x: number;
118
+ y: number;
119
+ count: number;
120
+ elementPath?: string;
121
+ }
122
+
123
+ interface ScrollData {
124
+ depth: number;
125
+ percentage: number;
126
+ users: number;
127
+ }
128
+
129
+ interface AreaData {
130
+ selector: string;
131
+ clicks: number;
132
+ elementBounds: DOMRect;
133
+ }
134
+
135
+ interface HeatmapRendererProps {
136
+ projectId: string;
137
+ isVisible: boolean;
138
+ panelContent: PanelContent;
139
+ widthScale: number;
140
+ height: number;
141
+ iframeHeight: number;
142
+ heatmapConfig?: IHeatmapConfig;
143
+ selectedElement?: any;
144
+ heatmapLoading: boolean;
145
+ showNoHeatmapModal: boolean;
146
+ deviceType?: string;
147
+ recordingUrl?: string;
148
+ iframeRef: RefObject<HTMLIFrameElement | null>;
149
+ heatmapWrapperRef: RefObject<HTMLDivElement | null>;
150
+ parentRef: RefObject<HTMLDivElement>;
151
+ heatmapSidebarRef?: RefObject<HTMLDivElement>;
152
+ selectElement: (element: any) => void;
153
+ setIframeHeight: (height: number) => void;
154
+ setElementToShow: (element: string) => void;
155
+ heatmapVisualizer: HeatmapVisualizer;
156
+ areaMapEditKey: string;
157
+ attentionAggregatedData?: any;
158
+ setPanelContent: (content: PanelContent) => void;
159
+ }
160
+
161
+ const HeatmapRenderer: React.FC<HeatmapRendererProps> = (props) => {
162
+ const canvasRef = useRef<HTMLCanvasElement>(null);
163
+ const [heatmapReady, setHeatmapReady] = useState(false);
164
+ const [clickPoints, setClickPoints] = useState<ClickData[]>([]);
165
+ const [scrollData, setScrollData] = useState<ScrollData[]>([]);
166
+ const [areaData, setAreaData] = useState<AreaData[]>([]);
167
+
168
+ // Initialize canvas for heatmap rendering
169
+ useEffect(() => {
170
+ if (!props.isVisible || !canvasRef.current) return;
171
+
172
+ const canvas = canvasRef.current;
173
+ const ctx = canvas.getContext('2d');
174
+
175
+ if (!ctx) return;
176
+
177
+ // Set canvas dimensions
178
+ canvas.width = props.iframeRef.current?.contentWindow?.innerWidth || 1920;
179
+ canvas.height = props.iframeHeight;
180
+
181
+ setHeatmapReady(true);
182
+ }, [props.isVisible, props.iframeHeight]);
183
+
184
+ // Render click heatmap
185
+ const renderClickHeatmap = useCallback(() => {
186
+ if (!canvasRef.current || !props.heatmapConfig) return;
187
+
188
+ const canvas = canvasRef.current;
189
+ const ctx = canvas.getContext('2d');
190
+ if (!ctx) return;
191
+
192
+ // Clear canvas
193
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
194
+
195
+ // Draw each click point
196
+ clickPoints.forEach((click) => {
197
+ const gradient = ctx.createRadialGradient(click.x, click.y, 0, click.x, click.y, 40);
198
+
199
+ // Color intensity based on click count
200
+ const intensity = Math.min(click.count / 10, 1);
201
+ gradient.addColorStop(0, `rgba(255, 0, 0, ${intensity * 0.8})`);
202
+ gradient.addColorStop(0.5, `rgba(255, 165, 0, ${intensity * 0.4})`);
203
+ gradient.addColorStop(1, 'rgba(255, 255, 0, 0)');
204
+
205
+ ctx.fillStyle = gradient;
206
+ ctx.fillRect(click.x - 40, click.y - 40, 80, 80);
207
+ });
208
+ }, [clickPoints, props.heatmapConfig]);
209
+
210
+ // Render scroll heatmap
211
+ const renderScrollHeatmap = useCallback(() => {
212
+ if (!canvasRef.current || !props.heatmapConfig) return;
213
+
214
+ const canvas = canvasRef.current;
215
+ const ctx = canvas.getContext('2d');
216
+ if (!ctx) return;
217
+
218
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
219
+
220
+ // Draw scroll depth gradient
221
+ scrollData.forEach((scroll, index) => {
222
+ const y = (scroll.depth / 100) * canvas.height;
223
+ const nextY =
224
+ index < scrollData.length - 1
225
+ ? (scrollData[index + 1].depth / 100) * canvas.height
226
+ : canvas.height;
227
+
228
+ const gradient = ctx.createLinearGradient(0, y, 0, nextY);
229
+
230
+ // Color based on engagement
231
+ const intensity = scroll.percentage / 100;
232
+ const red = Math.floor(255 * (1 - intensity));
233
+ const green = Math.floor(255 * intensity);
234
+
235
+ gradient.addColorStop(0, `rgba(${red}, ${green}, 0, 0.3)`);
236
+ gradient.addColorStop(1, `rgba(${red}, ${green}, 0, 0.3)`);
237
+
238
+ ctx.fillStyle = gradient;
239
+ ctx.fillRect(0, y, canvas.width, nextY - y);
240
+ });
241
+ }, [scrollData, props.heatmapConfig]);
242
+
243
+ // Render attention heatmap
244
+ const renderAttentionHeatmap = useCallback(() => {
245
+ if (!canvasRef.current || !props.attentionAggregatedData) return;
246
+
247
+ const canvas = canvasRef.current;
248
+ const ctx = canvas.getContext('2d');
249
+ if (!ctx) return;
250
+
251
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
252
+
253
+ // Use heatmap.js style rendering
254
+ const heatmapPoints = props.attentionAggregatedData.points || [];
255
+
256
+ heatmapPoints.forEach((point: HeatmapPoint) => {
257
+ const gradient = ctx.createRadialGradient(point.x, point.y, 0, point.x, point.y, 60);
258
+
259
+ const intensity = Math.min(point.value / 100, 1);
260
+
261
+ // Heat gradient: blue (low) -> green -> yellow -> red (high)
262
+ if (intensity < 0.25) {
263
+ gradient.addColorStop(0, `rgba(0, 0, 255, ${intensity * 4 * 0.6})`);
264
+ gradient.addColorStop(1, 'rgba(0, 0, 255, 0)');
265
+ } else if (intensity < 0.5) {
266
+ gradient.addColorStop(0, `rgba(0, 255, 0, ${(intensity - 0.25) * 4 * 0.6})`);
267
+ gradient.addColorStop(1, 'rgba(0, 255, 0, 0)');
268
+ } else if (intensity < 0.75) {
269
+ gradient.addColorStop(0, `rgba(255, 255, 0, ${(intensity - 0.5) * 4 * 0.6})`);
270
+ gradient.addColorStop(1, 'rgba(255, 255, 0, 0)');
271
+ } else {
272
+ gradient.addColorStop(0, `rgba(255, 0, 0, ${(intensity - 0.75) * 4 * 0.6})`);
273
+ gradient.addColorStop(1, 'rgba(255, 0, 0, 0)');
274
+ }
275
+
276
+ ctx.fillStyle = gradient;
277
+ ctx.fillRect(point.x - 60, point.y - 60, 120, 120);
278
+ });
279
+ }, [props.attentionAggregatedData]);
280
+
281
+ // Render area map (clickable regions)
282
+ const renderAreaMap = useCallback(() => {
283
+ if (!props.iframeRef.current?.contentDocument) return;
284
+
285
+ const doc = props.iframeRef.current.contentDocument;
286
+
287
+ // Remove existing area overlays
288
+ const existingOverlays = doc.querySelectorAll('.clarity-area-overlay');
289
+ existingOverlays.forEach((el) => el.remove());
290
+
291
+ // Create overlay for each area
292
+ areaData.forEach((area) => {
293
+ const overlay = doc.createElement('div');
294
+ overlay.className = 'clarity-area-overlay';
295
+ overlay.style.cssText = `
296
+ position: absolute;
297
+ left: ${area.elementBounds.left}px;
298
+ top: ${area.elementBounds.top}px;
299
+ width: ${area.elementBounds.width}px;
300
+ height: ${area.elementBounds.height}px;
301
+ background: rgba(0, 123, 255, 0.2);
302
+ border: 2px solid rgba(0, 123, 255, 0.6);
303
+ pointer-events: auto;
304
+ cursor: pointer;
305
+ z-index: 10000;
306
+ `;
307
+
308
+ // Add click count badge
309
+ const badge = doc.createElement('div');
310
+ badge.className = 'clarity-area-badge';
311
+ badge.textContent = area.clicks.toString();
312
+ badge.style.cssText = `
313
+ position: absolute;
314
+ top: -10px;
315
+ right: -10px;
316
+ background: #007bff;
317
+ color: white;
318
+ border-radius: 50%;
319
+ width: 24px;
320
+ height: 24px;
321
+ display: flex;
322
+ align-items: center;
323
+ justify-content: center;
324
+ font-size: 12px;
325
+ font-weight: bold;
326
+ `;
327
+ overlay.appendChild(badge);
328
+
329
+ overlay.addEventListener('click', () => {
330
+ props.selectElement(area);
331
+ props.setElementToShow(area.selector);
332
+ });
333
+
334
+ doc.body.appendChild(overlay);
335
+ });
336
+ }, [areaData, props]);
337
+
338
+ // Process heatmap data based on panel content
339
+ useEffect(() => {
340
+ if (!props.heatmapConfig || props.heatmapLoading) return;
341
+
342
+ switch (props.panelContent) {
343
+ case PanelContent.Click:
344
+ // Extract click data from heatmapConfig
345
+ const clicks = (props.heatmapConfig as any).clicks || [];
346
+ setClickPoints(clicks);
347
+ break;
348
+
349
+ case PanelContent.Scroll:
350
+ // Extract scroll data
351
+ const scrolls = (props.heatmapConfig as any).scrollDepth || [];
352
+ setScrollData(scrolls);
353
+ break;
354
+
355
+ case PanelContent.Area:
356
+ // Extract area data
357
+ const areas = (props.heatmapConfig as any).areas || [];
358
+ setAreaData(areas);
359
+ break;
360
+
361
+ case PanelContent.Attention:
362
+ // Attention data is already processed via attentionAggregatedData
363
+ break;
364
+ }
365
+ }, [props.heatmapConfig, props.panelContent, props.heatmapLoading]);
366
+
367
+ // Render appropriate heatmap based on panel content
368
+ useEffect(() => {
369
+ if (!heatmapReady || props.heatmapLoading || props.showNoHeatmapModal) return;
370
+
371
+ switch (props.panelContent) {
372
+ case PanelContent.Click:
373
+ renderClickHeatmap();
374
+ break;
375
+
376
+ case PanelContent.Scroll:
377
+ renderScrollHeatmap();
378
+ break;
379
+
380
+ case PanelContent.Attention:
381
+ renderAttentionHeatmap();
382
+ break;
383
+
384
+ case PanelContent.Area:
385
+ renderAreaMap();
386
+ break;
387
+ }
388
+ }, [
389
+ heatmapReady,
390
+ props.panelContent,
391
+ props.heatmapLoading,
392
+ props.showNoHeatmapModal,
393
+ renderClickHeatmap,
394
+ renderScrollHeatmap,
395
+ renderAttentionHeatmap,
396
+ renderAreaMap,
397
+ ]);
398
+
399
+ // Handle element selection
400
+ const handleCanvasClick = (e: React.MouseEvent<HTMLCanvasElement>) => {
401
+ if (!canvasRef.current) return;
402
+
403
+ const rect = canvasRef.current.getBoundingClientRect();
404
+ const x = e.clientX - rect.left;
405
+ const y = e.clientY - rect.top;
406
+
407
+ // Find clicked element in heatmap data
408
+ const clickedPoint = clickPoints.find(
409
+ (point) => Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2)) < 40,
410
+ );
411
+
412
+ if (clickedPoint) {
413
+ props.selectElement(clickedPoint);
414
+ }
415
+ };
416
+
417
+ if (!props.isVisible) return null;
418
+
419
+ return (
420
+ <div className="heatmap-renderer">
421
+ {props.heatmapLoading && (
422
+ <div className="heatmap-loading">
423
+ <div className="spinner">Loading heatmap...</div>
424
+ </div>
425
+ )}
426
+
427
+ {props.showNoHeatmapModal && (
428
+ <div className="no-heatmap-modal">
429
+ <div className="modal-content">
430
+ <h3>No Data Available</h3>
431
+ <p>There is no {props.panelContent.toLowerCase()} data for this page.</p>
432
+ </div>
433
+ </div>
434
+ )}
435
+
436
+ {props.panelContent !== PanelContent.Area && (
437
+ <canvas
438
+ ref={canvasRef}
439
+ className="clarity-heatmap-canvas"
440
+ id="clarity-heatmap-canvas"
441
+ onClick={handleCanvasClick}
442
+ style={{
443
+ position: 'absolute',
444
+ top: 0,
445
+ left: 0,
446
+ width: '100%',
447
+ height: '100%',
448
+ pointerEvents: 'auto',
449
+ zIndex: 9999,
450
+ }}
451
+ />
452
+ )}
453
+
454
+ {props.selectedElement && (
455
+ <div className="heatmap-element-info">
456
+ <h4>Selected Element</h4>
457
+ <p>Clicks: {props.selectedElement.count || props.selectedElement.clicks}</p>
458
+ {props.selectedElement.elementPath && <p>Path: {props.selectedElement.elementPath}</p>}
459
+ </div>
460
+ )}
461
+ </div>
462
+ );
463
+ };
464
+
465
+ // ===== Snapshot Player Component =====
466
+
467
+ interface SnapshotPlayerProps {
468
+ isVisible: boolean;
469
+ mergedPayload: MergedPayload | null;
470
+ time: number;
471
+ videoAreaRef: RefObject<HTMLDivElement>;
472
+ deviceType?: string;
473
+ refOverride: RefObject<HTMLIFrameElement | null>;
474
+ impressionHeight?: number;
475
+ panelContent: PanelContent;
476
+ width: number;
477
+ height: number;
478
+ iframeStyles: React.CSSProperties;
479
+ elementToShow: string;
480
+ snapshotStyleClassName?: string;
481
+ heatmapConfig?: IHeatmapConfig;
482
+ loadingCallback?: (loading: boolean) => void;
483
+ snapshotResizeCallback: (width: number, height: number) => void;
484
+ visualizer: HeatmapVisualizer;
485
+ areaMapEditKey: string;
486
+ snapshotLoading?: (loading: boolean) => void;
487
+ isDead?: boolean;
488
+ }
489
+
490
+ const SnapshotPlayer: React.FC<SnapshotPlayerProps> = (props) => {
491
+ const [snapshotHtml, setSnapshotHtml] = useState('');
492
+ const [isLoading, setIsLoading] = useState(true);
493
+
494
+ useEffect(() => {
495
+ if (!props.mergedPayload) return;
496
+
497
+ // Render snapshot from merged payload
498
+ const html = renderSnapshotFromPayload(props.mergedPayload, props.time);
499
+ setSnapshotHtml(html);
500
+ setIsLoading(false);
501
+ props.snapshotLoading?.(false);
502
+ }, [props.mergedPayload, props.time]);
503
+
504
+ const renderSnapshotFromPayload = (payload: MergedPayload, time: number): string => {
505
+ // Find the snapshot at the given time
506
+ // This would use the visualizer to render the DOM state
507
+ return '<html><body><p>Snapshot rendered here</p></body></html>';
508
+ };
509
+
510
+ useEffect(() => {
511
+ if (!props.refOverride.current) return;
512
+
513
+ const iframe = props.refOverride.current;
514
+ const doc = iframe.contentDocument;
515
+
516
+ if (doc && snapshotHtml) {
517
+ doc.open();
518
+ doc.write(snapshotHtml);
519
+ doc.close();
520
+
521
+ // Measure dimensions
522
+ setTimeout(() => {
523
+ const width = doc.documentElement.scrollWidth;
524
+ const height = doc.documentElement.scrollHeight;
525
+ props.snapshotResizeCallback(width, height);
526
+ }, 100);
527
+ }
528
+ }, [snapshotHtml, props.refOverride]);
529
+
530
+ // Highlight element if needed
531
+ useEffect(() => {
532
+ if (!props.elementToShow || !props.refOverride.current) return;
533
+
534
+ const doc = props.refOverride.current.contentDocument;
535
+ if (!doc) return;
536
+
537
+ const element = doc.querySelector(props.elementToShow);
538
+ if (element) {
539
+ element.classList.add('clarity-highlighted');
540
+ element.scrollIntoView({ behavior: 'smooth', block: 'center' });
541
+ }
542
+
543
+ return () => {
544
+ if (element) {
545
+ element.classList.remove('clarity-highlighted');
546
+ }
547
+ };
548
+ }, [props.elementToShow, props.refOverride]);
549
+
550
+ return (
551
+ <iframe
552
+ ref={props.refOverride}
553
+ className={`clarity-snapshot ${props.snapshotStyleClassName || ''}`}
554
+ style={{
555
+ width: props.width,
556
+ height: props.height,
557
+ border: 'none',
558
+ ...props.iframeStyles,
559
+ }}
560
+ title="Session Recording"
561
+ />
562
+ );
563
+ };
564
+
565
+ // ===== Main Component Props =====
566
+
567
+ interface HeatmapWrapperProps {
568
+ projectId: string;
569
+ isVisible: boolean;
570
+ panelContent: PanelContent;
571
+ heatmapConfig?: IHeatmapConfig;
572
+ impressionHeight?: number;
573
+ deviceType?: string;
574
+ url?: string;
575
+ heatmapLoading?: boolean;
576
+ heatmapErrorType?: ErrorType;
577
+ videoAreaRef: RefObject<HTMLDivElement>;
578
+ parentRef: RefObject<HTMLDivElement>;
579
+ heatmapSidebarRef?: RefObject<HTMLDivElement>;
580
+ visualizer: Visualizer;
581
+ heatmapVisualizer: HeatmapVisualizer;
582
+ areaMapEditKey: string;
583
+ snapshotStyleClassName?: string;
584
+ mergedPayload: MergedPayload | null;
585
+ time: number;
586
+ loadingCallback?: (loading: boolean) => void;
587
+ setPanelContent: (content: PanelContent) => void;
588
+ snapshotLoading?: (loading: boolean) => void;
589
+ isDead?: boolean;
590
+ }
591
+
592
+ // ===== Heatmap Wrapper Component =====
593
+
594
+ const HeatmapWrapper: React.FC<HeatmapWrapperProps> = (props) => {
595
+ const resizeObserverRef = useRef<ResizeObserver>(null);
596
+ const wrapperRef = useRef<HTMLDivElement>(null);
597
+ const iframeRef = useRef<HTMLIFrameElement>(null);
598
+
599
+ // State for dimensions and scaling
600
+ const [containerWidth, setContainerWidth] = useState(1);
601
+ const [containerHeight, setContainerHeight] = useState(1);
602
+ const [scaleRatio, setScaleRatio] = useState(1);
603
+ const [widthScale, setWidthScale] = useState(1);
604
+ const [heightScale, setHeightScale] = useState(1);
605
+ const [finalScale, setFinalScale] = useState(1);
606
+
607
+ // State for iframe dimensions
608
+ const [iframeWidth, setIframeWidth] = useState(0);
609
+ const [iframeHeight, setIframeHeight] = useState(0);
610
+ const [contentWidth, setContentWidth] = useState(0);
611
+ const [contentHeight, setContentHeight] = useState(0);
612
+ const [actualHeight, setActualHeight] = useState(0);
613
+
614
+ // Other state
615
+ const [selectedElement, setSelectedElement] = useState<any>();
616
+ const [elementToShow, setElementToShow] = useState('');
617
+ const [showNoHeatmapModal, setShowNoHeatmapModal] = useState(false);
618
+ const [attentionData, setAttentionData] = useState<any>();
619
+
620
+ const isHeatmapView =
621
+ props.panelContent === PanelContent.Attention ||
622
+ props.panelContent === PanelContent.Click ||
623
+ props.panelContent === PanelContent.Area;
624
+
625
+ // Update container dimensions
626
+ const updateDimensions = useCallback(() => {
627
+ const parent = wrapperRef.current?.parentElement?.parentElement;
628
+ if (parent) {
629
+ const width = parent.clientWidth;
630
+ const height = parent.clientHeight;
631
+
632
+ if (iframeWidth !== width) setIframeWidth(width);
633
+ if (iframeHeight !== height) setIframeHeight(height);
634
+ }
635
+ }, [iframeWidth, iframeHeight]);
636
+
637
+ // Setup resize listener
638
+ useEffect(() => {
639
+ updateDimensions();
640
+ window.addEventListener('resize', updateDimensions);
641
+ return () => window.removeEventListener('resize', updateDimensions);
642
+ }, [updateDimensions]);
643
+
644
+ // Handle attention data
645
+ useEffect(() => {
646
+ if (
647
+ props.panelContent === PanelContent.Attention &&
648
+ props.heatmapConfig?.attentionMapInfo &&
649
+ props.heatmapConfig.attentionMapInfo.length > 0
650
+ ) {
651
+ setAttentionData(props.heatmapVisualizer.attention(props.heatmapConfig.attentionMapInfo));
652
+ }
653
+ }, [props.heatmapConfig, props.panelContent, props.heatmapVisualizer]);
654
+
655
+ // Setup ResizeObserver for iframe content
656
+ useEffect(() => {
657
+ if (typeof window.ResizeObserver !== 'undefined') {
658
+ resizeObserverRef.current = new ResizeObserver((entries) => {
659
+ for (const entry of entries) {
660
+ if (entry.contentRect) {
661
+ // Update height logic here
662
+ }
663
+ }
664
+ });
665
+ }
666
+
667
+ const iframeBody = iframeRef.current?.contentDocument?.body;
668
+ if (resizeObserverRef.current && iframeBody) {
669
+ resizeObserverRef.current.observe(iframeBody);
670
+ return () => {
671
+ if (iframeBody) {
672
+ resizeObserverRef.current?.unobserve(iframeBody);
673
+ }
674
+ };
675
+ }
676
+ }, [finalScale]);
677
+
678
+ // Update actual height from heatmap data
679
+ useEffect(() => {
680
+ if (props.heatmapConfig?.height) {
681
+ setActualHeight(props.heatmapConfig.height);
682
+ }
683
+ }, [props.heatmapConfig?.width, props.heatmapConfig?.height]);
684
+
685
+ // Calculate scales based on dimensions
686
+ useEffect(() => {
687
+ if (iframeWidth > 0 && contentWidth > 0) {
688
+ setWidthScale(Math.min(iframeWidth / contentWidth, 1));
689
+ setScaleRatio(Math.min((iframeWidth - 20) / contentWidth, 1));
690
+ }
691
+ }, [contentWidth, iframeWidth]);
692
+
693
+ useEffect(() => {
694
+ if (iframeHeight > 0 && contentHeight > 0) {
695
+ setHeightScale(Math.min((iframeHeight - 20) / contentHeight, 1));
696
+ }
697
+ }, [iframeHeight, contentHeight]);
698
+
699
+ useEffect(() => {
700
+ if (scaleRatio > 0 && heightScale > 0) {
701
+ setFinalScale(Math.min(Math.min(scaleRatio, heightScale), 1));
702
+ }
703
+ }, [scaleRatio, heightScale]);
704
+
705
+ // Handle heatmap visibility and error states
706
+ useEffect(() => {
707
+ if (isHeatmapView) {
708
+ if (props.impressionHeight && props.videoAreaRef.current) {
709
+ props.videoAreaRef.current.style.height = `${props.impressionHeight * widthScale}px`;
710
+ }
711
+
712
+ if (props.heatmapLoading || props.heatmapConfig) {
713
+ if (props.heatmapErrorType === ErrorType.NoResults) {
714
+ setShowNoHeatmapModal(true);
715
+ } else if (
716
+ props.panelContent === PanelContent.Click ||
717
+ props.panelContent === PanelContent.Area
718
+ ) {
719
+ if (props.heatmapErrorType === ErrorType.NoClicks) {
720
+ setShowNoHeatmapModal(true);
721
+ } else {
722
+ setShowNoHeatmapModal(false);
723
+ if (props.parentRef.current) {
724
+ props.parentRef.current.style.overflow = '';
725
+ }
726
+ }
727
+ } else if (props.panelContent === PanelContent.Scroll) {
728
+ if (props.heatmapErrorType === ErrorType.NoScroll) {
729
+ setShowNoHeatmapModal(true);
730
+ } else {
731
+ setShowNoHeatmapModal(false);
732
+ if (props.parentRef.current) {
733
+ props.parentRef.current.style.overflow = '';
734
+ }
735
+ }
736
+ }
737
+ } else {
738
+ if (props.parentRef.current) {
739
+ props.parentRef.current.style.overflow = 'hidden';
740
+ }
741
+ if (props.heatmapErrorType === ErrorType.NoResults) {
742
+ setShowNoHeatmapModal(true);
743
+ }
744
+ }
745
+ } else {
746
+ setShowNoHeatmapModal(false);
747
+ if (props.videoAreaRef.current?.style) {
748
+ props.videoAreaRef.current.style.height = '';
749
+ }
750
+ }
751
+ }, [
752
+ isHeatmapView,
753
+ widthScale,
754
+ props.impressionHeight,
755
+ props.heatmapConfig,
756
+ props.heatmapErrorType,
757
+ props.panelContent,
758
+ props.heatmapLoading,
759
+ ]);
760
+
761
+ const handleSnapshotResize = useCallback(
762
+ (width: number, height: number) => {
763
+ if (width !== contentWidth) setContentWidth(width);
764
+ if (height !== contentHeight) setContentHeight(height);
765
+ },
766
+ [contentWidth, contentHeight],
767
+ );
768
+
769
+ return (
770
+ <div
771
+ className={isHeatmapView ? 'heatmap-wrapper' : 'session-wrapper'}
772
+ style={
773
+ isHeatmapView
774
+ ? {
775
+ width: contentWidth,
776
+ height: props.impressionHeight,
777
+ transform: `scale(${widthScale})`,
778
+ transformOrigin: 'center',
779
+ }
780
+ : {
781
+ height: contentHeight * finalScale,
782
+ maxWidth: contentWidth * finalScale,
783
+ }
784
+ }
785
+ ref={wrapperRef}
786
+ >
787
+ {/* Cover overlay for certain views */}
788
+ {(props.panelContent === PanelContent.Sessions ||
789
+ props.panelContent === PanelContent.Timeline) && <div className="cover" />}
790
+
791
+ <HeatmapRenderer
792
+ projectId={props.projectId}
793
+ isVisible={isHeatmapView}
794
+ panelContent={props.panelContent}
795
+ widthScale={widthScale}
796
+ height={iframeHeight / widthScale}
797
+ iframeHeight={actualHeight}
798
+ heatmapConfig={props.heatmapConfig}
799
+ selectedElement={selectedElement}
800
+ heatmapLoading={!!props.heatmapLoading}
801
+ showNoHeatmapModal={showNoHeatmapModal}
802
+ deviceType={props.deviceType}
803
+ recordingUrl={props.url}
804
+ iframeRef={iframeRef}
805
+ heatmapWrapperRef={wrapperRef}
806
+ parentRef={props.parentRef}
807
+ heatmapSidebarRef={props.heatmapSidebarRef}
808
+ selectElement={setSelectedElement}
809
+ setIframeHeight={setActualHeight}
810
+ setElementToShow={setElementToShow}
811
+ heatmapVisualizer={props.heatmapVisualizer}
812
+ areaMapEditKey={props.areaMapEditKey}
813
+ attentionAggregatedData={attentionData}
814
+ setPanelContent={props.setPanelContent}
815
+ />
816
+
817
+ <SnapshotPlayer
818
+ isVisible={props.isVisible}
819
+ mergedPayload={props.mergedPayload}
820
+ time={props.time}
821
+ videoAreaRef={props.videoAreaRef}
822
+ deviceType={props.deviceType}
823
+ refOverride={iframeRef}
824
+ impressionHeight={props.impressionHeight}
825
+ panelContent={props.panelContent}
826
+ width={contentWidth}
827
+ height={isHeatmapView ? iframeHeight / widthScale : contentHeight}
828
+ iframeStyles={
829
+ isHeatmapView
830
+ ? {}
831
+ : {
832
+ transform: `scale(${finalScale})`,
833
+ transformOrigin: '0 0',
834
+ }
835
+ }
836
+ elementToShow={elementToShow}
837
+ snapshotStyleClassName={
838
+ showNoHeatmapModal ? 'deadSessionSnapshot' : props.snapshotStyleClassName
839
+ }
840
+ heatmapConfig={props.heatmapConfig}
841
+ loadingCallback={props.loadingCallback}
842
+ snapshotResizeCallback={handleSnapshotResize}
843
+ visualizer={props.heatmapVisualizer}
844
+ areaMapEditKey={props.areaMapEditKey}
845
+ snapshotLoading={props.snapshotLoading}
846
+ isDead={props.isDead}
847
+ />
848
+ </div>
849
+ );
850
+ };
851
+
852
+ // ===== Impression Player Component (Class Component) =====
853
+
854
+ interface ImpressionPlayerProps {
855
+ loading: boolean;
856
+ projectId: string;
857
+ isVisible: boolean;
858
+ data?: any[];
859
+ pageUrl?: string;
860
+ timestamp?: number;
861
+ visualizer: Visualizer;
862
+ heatmapVisualizer: HeatmapVisualizer;
863
+ time: number;
864
+ parentRef: RefObject<HTMLDivElement>;
865
+ videoAreaRef: RefObject<HTMLDivElement>;
866
+ impressionData?: ImpressionData;
867
+ panelContent: PanelContent;
868
+ heatmapInfo?: IHeatmapConfig;
869
+ heatmapLoading?: boolean;
870
+ heatmapError?: any;
871
+ heatmapErrorType?: ErrorType;
872
+ snapshotStyleClassName?: string;
873
+ heatmapSidebarRef?: RefObject<HTMLDivElement>;
874
+ deviceType?: string;
875
+ url?: string;
876
+ sessionId: string;
877
+ userId: string;
878
+ pageNum: string;
879
+ areaMapEditKey?: string;
880
+ skipInactivity?: boolean;
881
+ isPlaying?: boolean;
882
+ timeChange: (time: number) => void;
883
+ loadingCallback?: (loading: boolean) => void;
884
+ latencyTrackerStart?: () => void;
885
+ latencyTrackerEnd?: () => void;
886
+ timelineInfo?: { timeline: TimelineItem[] };
887
+ setFailedToFetchImpression?: (pageNum: number) => void;
888
+ error?: any;
889
+ errorType?: ErrorType;
890
+ isLive?: boolean;
891
+ setPanelContent: (content: PanelContent) => void;
892
+ isDead?: boolean;
893
+ classRef?: RefObject<ImpressionPlayer>;
894
+ }
895
+
896
+ interface ImpressionPlayerState {
897
+ mergedPayload: MergedPayload | null;
898
+ activeDurations: ActiveDuration[];
899
+ snapshotRendered: boolean;
900
+ }
901
+
902
+ class ImpressionPlayer extends Component<ImpressionPlayerProps, ImpressionPlayerState> {
903
+ private componentName = 'ImpressionPlayer';
904
+ private goToEnd = false;
905
+ private timeLineUpdateCb?: () => void;
906
+
907
+ constructor(props: ImpressionPlayerProps) {
908
+ super(props);
909
+
910
+ this.state = {
911
+ mergedPayload: null,
912
+ activeDurations: [],
913
+ snapshotRendered: false,
914
+ };
915
+
916
+ if (props.classRef) {
917
+ (props.classRef as any).current = this;
918
+ }
919
+ }
920
+
921
+ componentDidMount(): void {
922
+ this.process();
923
+ }
924
+
925
+ componentDidUpdate(prevProps: ImpressionPlayerProps, prevState: ImpressionPlayerState): void {
926
+ this.process(prevProps.data);
927
+ this.goToActiveTime();
928
+
929
+ if (prevProps.loading || !this.props.loading || this.props.isLive) {
930
+ this.setSnapshotLoading(true);
931
+ }
932
+
933
+ if (prevState.activeDurations !== this.state.activeDurations && this.timeLineUpdateCb) {
934
+ this.timeLineUpdateCb();
935
+ this.timeLineUpdateCb = undefined;
936
+ }
937
+
938
+ if (
939
+ prevState.snapshotRendered !== this.state.snapshotRendered ||
940
+ prevState.mergedPayload?.events?.length !== this.state.mergedPayload?.events?.length
941
+ ) {
942
+ this.props.loadingCallback?.(!this.state.snapshotRendered || !this.isProcessed());
943
+ }
944
+
945
+ if (this.props.error) {
946
+ this.handleImpressionFetchError();
947
+ }
948
+ }
949
+
950
+ private process = (prevData?: any[]): void => {
951
+ if (
952
+ this.props.data &&
953
+ (!this.state.mergedPayload ||
954
+ (Array.isArray(prevData) && this.props.data.length !== prevData?.length))
955
+ ) {
956
+ this.props.latencyTrackerStart?.();
957
+
958
+ let data = this.props.data;
959
+ // Filter logic if needed based on pageUrl and timestamp
960
+
961
+ const merged = this.props.visualizer.merge(data);
962
+
963
+ this.setState({
964
+ mergedPayload: merged,
965
+ activeDurations: this.calculateActiveDurations(merged.events),
966
+ });
967
+
968
+ this.props.latencyTrackerEnd?.();
969
+ }
970
+ };
971
+
972
+ private calculateActiveDurations = (events: any[]): ActiveDuration[] => {
973
+ // Implementation to calculate active durations from events
974
+ return [];
975
+ };
976
+
977
+ private isProcessed = (): boolean => {
978
+ return !!(
979
+ this.state.mergedPayload &&
980
+ this.state.mergedPayload.events &&
981
+ this.state.mergedPayload.events.length > 0
982
+ );
983
+ };
984
+
985
+ private handleImpressionFetchError = (): void => {
986
+ if (!this.props.timelineInfo) return;
987
+
988
+ this.props.loadingCallback?.(false);
989
+
990
+ const currentPage = this.props.timelineInfo.timeline[parseInt(this.props.pageNum)];
991
+
992
+ if (currentPage && !currentPage.failedToFetch && this.props.impressionData) {
993
+ this.props.setFailedToFetchImpression?.(parseInt(this.props.pageNum));
994
+
995
+ const newTime =
996
+ this.props.time +
997
+ Math.max(
998
+ 0.8 * this.props.impressionData.duration!,
999
+ this.props.impressionData.duration! - 3000,
1000
+ );
1001
+
1002
+ this.props.timeChange(newTime);
1003
+ }
1004
+ };
1005
+
1006
+ private getNextActiveTime = (currentTime: number, callback?: () => void): number => {
1007
+ if (this.state.activeDurations && this.state.activeDurations.length > 0) {
1008
+ for (let i = 0; i < this.state.activeDurations.length; i++) {
1009
+ if (currentTime < this.state.activeDurations[i].startTime) {
1010
+ if (this.state.activeDurations[i].active) {
1011
+ return this.state.activeDurations[i].startTime;
1012
+ } else if (i < this.state.activeDurations.length - 1) {
1013
+ return this.state.activeDurations[i + 1].startTime;
1014
+ } else {
1015
+ return this.state.activeDurations[i].startTime + this.state.activeDurations[i].duration;
1016
+ }
1017
+ }
1018
+ }
1019
+ this.timeLineUpdateCb = callback;
1020
+ }
1021
+ return currentTime;
1022
+ };
1023
+
1024
+ private goToActiveTime = (): void => {
1025
+ if (this.props.skipInactivity && !this.props.isLive) {
1026
+ let index = 0;
1027
+ let found = false;
1028
+
1029
+ while (index < this.state.activeDurations.length) {
1030
+ if (this.props.time < this.state.activeDurations[index].startTime) {
1031
+ found = true;
1032
+ break;
1033
+ }
1034
+ index++;
1035
+ }
1036
+
1037
+ if (this.state.activeDurations && this.state.activeDurations.length > 0) {
1038
+ if (index > 0 && found && !this.state.activeDurations[index - 1].active) {
1039
+ this.goToEnd = false;
1040
+ this.props.timeChange(this.state.activeDurations[index].startTime);
1041
+ } else if (
1042
+ index !== this.state.activeDurations.length ||
1043
+ this.state.activeDurations[index - 1].active ||
1044
+ this.goToEnd
1045
+ ) {
1046
+ if (this.goToEnd) {
1047
+ this.goToEnd = false;
1048
+ }
1049
+ } else {
1050
+ this.goToEnd = true;
1051
+ this.props.timeChange(
1052
+ this.state.activeDurations[index - 1].startTime +
1053
+ this.state.activeDurations[index - 1].duration,
1054
+ );
1055
+ }
1056
+ }
1057
+ }
1058
+ };
1059
+
1060
+ private setSnapshotLoading = (loading: boolean): void => {
1061
+ this.setState({
1062
+ snapshotRendered: !loading,
1063
+ });
1064
+ };
1065
+
1066
+ render() {
1067
+ if (!this.isProcessed()) {
1068
+ if (this.props.error) {
1069
+ return <div className="error-message">Error loading impression</div>;
1070
+ }
1071
+ return <div className="loadingCentered">Loading...</div>;
1072
+ }
1073
+
1074
+ return (
1075
+ <>
1076
+ {!this.state.snapshotRendered && <div className="loadingCentered">Loading snapshot...</div>}
1077
+ <HeatmapWrapper
1078
+ projectId={this.props.projectId}
1079
+ isVisible={this.props.isVisible}
1080
+ loadingCallback={this.props.loadingCallback}
1081
+ mergedPayload={this.state.mergedPayload}
1082
+ time={this.props.time}
1083
+ parentRef={this.props.parentRef}
1084
+ videoAreaRef={this.props.videoAreaRef}
1085
+ impressionHeight={this.props.impressionData?.documentHeight}
1086
+ panelContent={this.props.panelContent}
1087
+ heatmapConfig={this.props.heatmapInfo}
1088
+ heatmapLoading={this.props.heatmapLoading}
1089
+ heatmapErrorType={this.props.heatmapErrorType}
1090
+ snapshotStyleClassName={this.props.snapshotStyleClassName}
1091
+ heatmapSidebarRef={this.props.heatmapSidebarRef}
1092
+ deviceType={this.props.impressionData?.device}
1093
+ url={this.props.impressionData?.url}
1094
+ visualizer={this.props.visualizer}
1095
+ heatmapVisualizer={this.props.heatmapVisualizer}
1096
+ areaMapEditKey={`${this.props.projectId}${this.props.sessionId}${this.props.userId}${this.props.pageNum}${this.props.impressionData?.url}`}
1097
+ snapshotLoading={this.setSnapshotLoading}
1098
+ setPanelContent={this.props.setPanelContent}
1099
+ isDead={this.props.isDead}
1100
+ />
1101
+ </>
1102
+ );
1103
+ }
1104
+ }
1105
+
1106
+ export default ImpressionPlayer;