@gemx-dev/heatmap-react 3.5.48 → 3.5.49

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 (196) hide show
  1. package/dist/esm/components/Layout/ContentTopBar.d.ts.map +1 -1
  2. package/dist/esm/components/Layout/ContentVizByMode.d.ts.map +1 -1
  3. package/dist/esm/components/Layout/LeftSidebar.d.ts.map +1 -1
  4. package/dist/esm/components/VizCompare/CompareGrid.d.ts +1 -0
  5. package/dist/esm/components/VizCompare/CompareGrid.d.ts.map +1 -0
  6. package/dist/esm/components/VizCompare/CompareView.d.ts +1 -0
  7. package/dist/esm/components/VizCompare/CompareView.d.ts.map +1 -0
  8. package/dist/esm/components/VizCompare/CompareViewHeader.d.ts +1 -0
  9. package/dist/esm/components/VizCompare/CompareViewHeader.d.ts.map +1 -0
  10. package/dist/esm/components/VizCompare/CompareVizRenderer.d.ts +1 -0
  11. package/dist/esm/components/VizCompare/CompareVizRenderer.d.ts.map +1 -0
  12. package/dist/esm/components/VizCompare/VizCompareHeatmap.d.ts +1 -0
  13. package/dist/esm/components/VizCompare/VizCompareHeatmap.d.ts.map +1 -0
  14. package/dist/esm/components/VizCompare/index.d.ts +1 -0
  15. package/dist/esm/components/VizCompare/index.d.ts.map +1 -0
  16. package/dist/esm/components/VizDom/VizContainer.d.ts +1 -1
  17. package/dist/esm/components/VizDom/VizContainer.d.ts.map +1 -1
  18. package/dist/esm/components/VizDom/VizDomHeatmap.d.ts.map +1 -1
  19. package/dist/esm/components/VizDom/VizDomRenderer.d.ts.map +1 -1
  20. package/dist/esm/components/VizDom/WrapperVisual.d.ts.map +1 -1
  21. package/dist/esm/components/VizElement/DefaultRankBadges.d.ts.map +1 -1
  22. package/dist/esm/components/VizElement/ElementMissing.d.ts.map +1 -1
  23. package/dist/esm/components/VizElement/VizElements.d.ts.map +1 -1
  24. package/dist/esm/components/VizLive/VizLiveHeatmap.d.ts.map +1 -1
  25. package/dist/esm/components/VizLive/VizLiveRenderer.d.ts.map +1 -1
  26. package/dist/esm/components/VizScrollmap/AverageFoldLine.d.ts.map +1 -1
  27. package/dist/esm/components/VizScrollmap/HoverZones.d.ts.map +1 -1
  28. package/dist/esm/components/VizScrollmap/ScrollMapOverlay.d.ts.map +1 -1
  29. package/dist/esm/components/VizScrollmap/VizScrollMap.d.ts.map +1 -1
  30. package/dist/esm/components/VizScrollmapV2/useScrollmapOverlay.d.ts.map +1 -1
  31. package/dist/esm/contexts/CompareViewContext.d.ts +28 -0
  32. package/dist/esm/contexts/CompareViewContext.d.ts.map +1 -0
  33. package/dist/esm/contexts/index.d.ts +2 -0
  34. package/dist/esm/contexts/index.d.ts.map +1 -0
  35. package/dist/esm/hooks/compare/index.d.ts +4 -0
  36. package/dist/esm/hooks/compare/index.d.ts.map +1 -0
  37. package/dist/esm/hooks/compare/useCompareAwareConfig.d.ts +21 -0
  38. package/dist/esm/hooks/compare/useCompareAwareConfig.d.ts.map +1 -0
  39. package/dist/esm/hooks/compare/useCompareAwareData.d.ts +28 -0
  40. package/dist/esm/hooks/compare/useCompareAwareData.d.ts.map +1 -0
  41. package/dist/esm/hooks/compare/useCompareAwareViz.d.ts +34 -0
  42. package/dist/esm/hooks/compare/useCompareAwareViz.d.ts.map +1 -0
  43. package/dist/esm/hooks/index.d.ts +4 -0
  44. package/dist/esm/hooks/index.d.ts.map +1 -1
  45. package/dist/esm/hooks/register/useRegisterData.d.ts.map +1 -1
  46. package/dist/esm/hooks/register/useRegisterHeatmap.d.ts.map +1 -1
  47. package/dist/esm/hooks/useHeatmapData.d.ts +16 -0
  48. package/dist/esm/hooks/useHeatmapData.d.ts.map +1 -0
  49. package/dist/esm/hooks/useHeatmapViz.d.ts +24 -0
  50. package/dist/esm/hooks/useHeatmapViz.d.ts.map +1 -0
  51. package/dist/esm/hooks/useViewId.d.ts +15 -0
  52. package/dist/esm/hooks/useViewId.d.ts.map +1 -0
  53. package/dist/esm/hooks/viz-canvas/useAreamap.d.ts.map +1 -1
  54. package/dist/esm/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
  55. package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
  56. package/dist/esm/hooks/viz-elements/useClickedElement.d.ts.map +1 -1
  57. package/dist/esm/hooks/viz-elements/useElementCalloutVisible.d.ts.map +1 -1
  58. package/dist/esm/hooks/viz-elements/useHeatmapElementPosition.d.ts.map +1 -1
  59. package/dist/esm/hooks/viz-elements/useHoveredElement.d.ts.map +1 -1
  60. package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts.map +1 -1
  61. package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  62. package/dist/esm/hooks/viz-render/useReplayRender.d.ts.map +1 -1
  63. package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts +1 -0
  64. package/dist/esm/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
  65. package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts +1 -0
  66. package/dist/esm/hooks/viz-scale/useObserveIframeHeight.d.ts.map +1 -1
  67. package/dist/esm/hooks/viz-scale/useScaleCalculation.d.ts +1 -1
  68. package/dist/esm/hooks/viz-scale/useScaleCalculation.d.ts.map +1 -1
  69. package/dist/esm/hooks/viz-scale/useScrollSync.d.ts +2 -1
  70. package/dist/esm/hooks/viz-scale/useScrollSync.d.ts.map +1 -1
  71. package/dist/esm/hooks/viz-scale/useWrapperRefHeight.d.ts +0 -1
  72. package/dist/esm/hooks/viz-scale/useWrapperRefHeight.d.ts.map +1 -1
  73. package/dist/esm/hooks/viz-scrollmap/useScrollmapZones.d.ts.map +1 -1
  74. package/dist/esm/hooks/viz-scrollmap/useZonePositions.d.ts.map +1 -1
  75. package/dist/esm/index.d.ts +3 -1
  76. package/dist/esm/index.d.ts.map +1 -1
  77. package/dist/esm/index.js +671 -133
  78. package/dist/esm/index.mjs +671 -133
  79. package/dist/esm/stores/config.d.ts +2 -0
  80. package/dist/esm/stores/config.d.ts.map +1 -1
  81. package/dist/esm/stores/data.d.ts +11 -10
  82. package/dist/esm/stores/data.d.ts.map +1 -1
  83. package/dist/esm/stores/index.d.ts +1 -0
  84. package/dist/esm/stores/index.d.ts.map +1 -1
  85. package/dist/esm/stores/mode-compare.d.ts +33 -0
  86. package/dist/esm/stores/mode-compare.d.ts.map +1 -0
  87. package/dist/esm/stores/mode-live.d.ts +0 -4
  88. package/dist/esm/stores/mode-live.d.ts.map +1 -1
  89. package/dist/esm/stores/mode-single.d.ts +9 -4
  90. package/dist/esm/stores/mode-single.d.ts.map +1 -1
  91. package/dist/esm/stores/viz.d.ts +13 -10
  92. package/dist/esm/stores/viz.d.ts.map +1 -1
  93. package/dist/esm/types/compare.d.ts +68 -0
  94. package/dist/esm/types/compare.d.ts.map +1 -0
  95. package/dist/esm/types/control.d.ts +1 -1
  96. package/dist/esm/types/control.d.ts.map +1 -1
  97. package/dist/esm/types/index.d.ts +1 -0
  98. package/dist/esm/types/index.d.ts.map +1 -1
  99. package/dist/umd/components/Layout/ContentTopBar.d.ts.map +1 -1
  100. package/dist/umd/components/Layout/ContentVizByMode.d.ts.map +1 -1
  101. package/dist/umd/components/Layout/LeftSidebar.d.ts.map +1 -1
  102. package/dist/umd/components/VizCompare/CompareGrid.d.ts +1 -0
  103. package/dist/umd/components/VizCompare/CompareGrid.d.ts.map +1 -0
  104. package/dist/umd/components/VizCompare/CompareView.d.ts +1 -0
  105. package/dist/umd/components/VizCompare/CompareView.d.ts.map +1 -0
  106. package/dist/umd/components/VizCompare/CompareViewHeader.d.ts +1 -0
  107. package/dist/umd/components/VizCompare/CompareViewHeader.d.ts.map +1 -0
  108. package/dist/umd/components/VizCompare/CompareVizRenderer.d.ts +1 -0
  109. package/dist/umd/components/VizCompare/CompareVizRenderer.d.ts.map +1 -0
  110. package/dist/umd/components/VizCompare/VizCompareHeatmap.d.ts +1 -0
  111. package/dist/umd/components/VizCompare/VizCompareHeatmap.d.ts.map +1 -0
  112. package/dist/umd/components/VizCompare/index.d.ts +1 -0
  113. package/dist/umd/components/VizCompare/index.d.ts.map +1 -0
  114. package/dist/umd/components/VizDom/VizContainer.d.ts +1 -1
  115. package/dist/umd/components/VizDom/VizContainer.d.ts.map +1 -1
  116. package/dist/umd/components/VizDom/VizDomHeatmap.d.ts.map +1 -1
  117. package/dist/umd/components/VizDom/VizDomRenderer.d.ts.map +1 -1
  118. package/dist/umd/components/VizDom/WrapperVisual.d.ts.map +1 -1
  119. package/dist/umd/components/VizElement/DefaultRankBadges.d.ts.map +1 -1
  120. package/dist/umd/components/VizElement/ElementMissing.d.ts.map +1 -1
  121. package/dist/umd/components/VizElement/VizElements.d.ts.map +1 -1
  122. package/dist/umd/components/VizLive/VizLiveHeatmap.d.ts.map +1 -1
  123. package/dist/umd/components/VizLive/VizLiveRenderer.d.ts.map +1 -1
  124. package/dist/umd/components/VizScrollmap/AverageFoldLine.d.ts.map +1 -1
  125. package/dist/umd/components/VizScrollmap/HoverZones.d.ts.map +1 -1
  126. package/dist/umd/components/VizScrollmap/ScrollMapOverlay.d.ts.map +1 -1
  127. package/dist/umd/components/VizScrollmap/VizScrollMap.d.ts.map +1 -1
  128. package/dist/umd/components/VizScrollmapV2/useScrollmapOverlay.d.ts.map +1 -1
  129. package/dist/umd/contexts/CompareViewContext.d.ts +28 -0
  130. package/dist/umd/contexts/CompareViewContext.d.ts.map +1 -0
  131. package/dist/umd/contexts/index.d.ts +2 -0
  132. package/dist/umd/contexts/index.d.ts.map +1 -0
  133. package/dist/umd/hooks/compare/index.d.ts +4 -0
  134. package/dist/umd/hooks/compare/index.d.ts.map +1 -0
  135. package/dist/umd/hooks/compare/useCompareAwareConfig.d.ts +21 -0
  136. package/dist/umd/hooks/compare/useCompareAwareConfig.d.ts.map +1 -0
  137. package/dist/umd/hooks/compare/useCompareAwareData.d.ts +28 -0
  138. package/dist/umd/hooks/compare/useCompareAwareData.d.ts.map +1 -0
  139. package/dist/umd/hooks/compare/useCompareAwareViz.d.ts +34 -0
  140. package/dist/umd/hooks/compare/useCompareAwareViz.d.ts.map +1 -0
  141. package/dist/umd/hooks/index.d.ts +4 -0
  142. package/dist/umd/hooks/index.d.ts.map +1 -1
  143. package/dist/umd/hooks/register/useRegisterData.d.ts.map +1 -1
  144. package/dist/umd/hooks/register/useRegisterHeatmap.d.ts.map +1 -1
  145. package/dist/umd/hooks/useHeatmapData.d.ts +16 -0
  146. package/dist/umd/hooks/useHeatmapData.d.ts.map +1 -0
  147. package/dist/umd/hooks/useHeatmapViz.d.ts +24 -0
  148. package/dist/umd/hooks/useHeatmapViz.d.ts.map +1 -0
  149. package/dist/umd/hooks/useViewId.d.ts +15 -0
  150. package/dist/umd/hooks/useViewId.d.ts.map +1 -0
  151. package/dist/umd/hooks/viz-canvas/useAreamap.d.ts.map +1 -1
  152. package/dist/umd/hooks/viz-canvas/useClickmap.d.ts.map +1 -1
  153. package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
  154. package/dist/umd/hooks/viz-elements/useClickedElement.d.ts.map +1 -1
  155. package/dist/umd/hooks/viz-elements/useElementCalloutVisible.d.ts.map +1 -1
  156. package/dist/umd/hooks/viz-elements/useHeatmapElementPosition.d.ts.map +1 -1
  157. package/dist/umd/hooks/viz-elements/useHoveredElement.d.ts.map +1 -1
  158. package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts.map +1 -1
  159. package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  160. package/dist/umd/hooks/viz-render/useReplayRender.d.ts.map +1 -1
  161. package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts +1 -0
  162. package/dist/umd/hooks/viz-scale/useHeatmapScale.d.ts.map +1 -1
  163. package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts +1 -0
  164. package/dist/umd/hooks/viz-scale/useObserveIframeHeight.d.ts.map +1 -1
  165. package/dist/umd/hooks/viz-scale/useScaleCalculation.d.ts +1 -1
  166. package/dist/umd/hooks/viz-scale/useScaleCalculation.d.ts.map +1 -1
  167. package/dist/umd/hooks/viz-scale/useScrollSync.d.ts +2 -1
  168. package/dist/umd/hooks/viz-scale/useScrollSync.d.ts.map +1 -1
  169. package/dist/umd/hooks/viz-scale/useWrapperRefHeight.d.ts +0 -1
  170. package/dist/umd/hooks/viz-scale/useWrapperRefHeight.d.ts.map +1 -1
  171. package/dist/umd/hooks/viz-scrollmap/useScrollmapZones.d.ts.map +1 -1
  172. package/dist/umd/hooks/viz-scrollmap/useZonePositions.d.ts.map +1 -1
  173. package/dist/umd/index.d.ts +3 -1
  174. package/dist/umd/index.d.ts.map +1 -1
  175. package/dist/umd/index.js +2 -2
  176. package/dist/umd/stores/config.d.ts +2 -0
  177. package/dist/umd/stores/config.d.ts.map +1 -1
  178. package/dist/umd/stores/data.d.ts +11 -10
  179. package/dist/umd/stores/data.d.ts.map +1 -1
  180. package/dist/umd/stores/index.d.ts +1 -0
  181. package/dist/umd/stores/index.d.ts.map +1 -1
  182. package/dist/umd/stores/mode-compare.d.ts +33 -0
  183. package/dist/umd/stores/mode-compare.d.ts.map +1 -0
  184. package/dist/umd/stores/mode-live.d.ts +0 -4
  185. package/dist/umd/stores/mode-live.d.ts.map +1 -1
  186. package/dist/umd/stores/mode-single.d.ts +9 -4
  187. package/dist/umd/stores/mode-single.d.ts.map +1 -1
  188. package/dist/umd/stores/viz.d.ts +13 -10
  189. package/dist/umd/stores/viz.d.ts.map +1 -1
  190. package/dist/umd/types/compare.d.ts +68 -0
  191. package/dist/umd/types/compare.d.ts.map +1 -0
  192. package/dist/umd/types/control.d.ts +1 -1
  193. package/dist/umd/types/control.d.ts.map +1 -1
  194. package/dist/umd/types/index.d.ts +1 -0
  195. package/dist/umd/types/index.d.ts.map +1 -1
  196. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
  import { useNodesState, ReactFlow, Controls, Background } from '@xyflow/react';
4
- import { useEffect, useCallback, useState, useRef, useMemo, forwardRef, Fragment as Fragment$1 } from 'react';
4
+ import { useEffect, createContext, useContext, useCallback, useState, useRef, useMemo, forwardRef, Fragment as Fragment$1 } from 'react';
5
5
  import { create } from 'zustand';
6
6
  import { decode } from '@gemx-dev/clarity-decode';
7
7
  import { Visualizer } from '@gemx-dev/clarity-visualize';
@@ -71,11 +71,11 @@ const useHeatmapControlStore = create()((set, get) => {
71
71
  return {
72
72
  controls: {
73
73
  Sidebar: null,
74
- TopBar: null,
75
74
  Toolbar: null,
76
75
  MetricBar: null,
77
76
  VizLoading: null,
78
- ElementCallout: null,
77
+ TopBar: undefined,
78
+ ElementCallout: undefined,
79
79
  },
80
80
  registerControl: (key, control) => {
81
81
  set({
@@ -117,6 +117,7 @@ const useHeatmapConfigStore = create()((set, get) => {
117
117
  heatmapType: IHeatmapType.Scroll,
118
118
  clickType: IClickType.Total,
119
119
  scrollType: IScrollType.Depth,
120
+ isRendering: true,
120
121
  setMode: (mode) => set({ mode }),
121
122
  resetMode: () => set({ mode: 'single' }),
122
123
  setWidth: (width) => set({ width }),
@@ -124,21 +125,57 @@ const useHeatmapConfigStore = create()((set, get) => {
124
125
  setHeatmapType: (heatmapType) => set({ heatmapType }),
125
126
  setClickType: (clickType) => set({ clickType }),
126
127
  setScrollType: (scrollType) => set({ scrollType }),
128
+ setIsRendering: (isRendering) => set({ isRendering }),
127
129
  };
128
130
  });
129
131
 
132
+ const DEFAULT_VIEW_ID$2 = 'default';
130
133
  const useHeatmapDataStore = create()((set, get) => {
131
134
  return {
132
- data: undefined,
133
- clickmap: undefined,
134
- dataInfo: undefined,
135
- scrollmap: undefined,
136
- isRendering: true,
137
- setIsRendering: (isRendering) => set({ isRendering }),
138
- setDataInfo: (dataInfo) => set({ dataInfo }),
139
- setData: (data) => set({ data }),
140
- setClickmap: (clickmap) => set({ clickmap }),
141
- setScrollmap: (scrollmap) => set({ scrollmap }),
135
+ data: { [DEFAULT_VIEW_ID$2]: undefined },
136
+ clickmap: { [DEFAULT_VIEW_ID$2]: undefined },
137
+ dataInfo: { [DEFAULT_VIEW_ID$2]: undefined },
138
+ scrollmap: { [DEFAULT_VIEW_ID$2]: undefined },
139
+ setDataInfo: (dataInfo, viewId = DEFAULT_VIEW_ID$2) => set((state) => ({
140
+ dataInfo: { ...state.dataInfo, [viewId]: dataInfo },
141
+ })),
142
+ setData: (data, viewId = DEFAULT_VIEW_ID$2) => set((state) => ({
143
+ data: { ...state.data, [viewId]: data },
144
+ })),
145
+ setClickmap: (clickmap, viewId = DEFAULT_VIEW_ID$2) => set((state) => ({
146
+ clickmap: { ...state.clickmap, [viewId]: clickmap },
147
+ })),
148
+ setScrollmap: (scrollmap, viewId = DEFAULT_VIEW_ID$2) => set((state) => ({
149
+ scrollmap: { ...state.scrollmap, [viewId]: scrollmap },
150
+ })),
151
+ copyView: (fromViewId, toViewId) => set((state) => ({
152
+ data: { ...state.data, [toViewId]: state.data[fromViewId] },
153
+ clickmap: { ...state.clickmap, [toViewId]: state.clickmap[fromViewId] },
154
+ dataInfo: { ...state.dataInfo, [toViewId]: state.dataInfo[fromViewId] },
155
+ scrollmap: { ...state.scrollmap, [toViewId]: state.scrollmap[fromViewId] },
156
+ })),
157
+ clearView: (viewId) => set((state) => {
158
+ const newData = { ...state.data };
159
+ const newClickmap = { ...state.clickmap };
160
+ const newDataInfo = { ...state.dataInfo };
161
+ const newScrollmap = { ...state.scrollmap };
162
+ delete newData[viewId];
163
+ delete newClickmap[viewId];
164
+ delete newDataInfo[viewId];
165
+ delete newScrollmap[viewId];
166
+ return {
167
+ data: newData,
168
+ clickmap: newClickmap,
169
+ dataInfo: newDataInfo,
170
+ scrollmap: newScrollmap,
171
+ };
172
+ }),
173
+ resetAll: () => set({
174
+ data: { [DEFAULT_VIEW_ID$2]: undefined },
175
+ clickmap: { [DEFAULT_VIEW_ID$2]: undefined },
176
+ dataInfo: { [DEFAULT_VIEW_ID$2]: undefined },
177
+ scrollmap: { [DEFAULT_VIEW_ID$2]: undefined },
178
+ }),
142
179
  };
143
180
  });
144
181
 
@@ -157,18 +194,62 @@ const useHeatmapInteractionStore = create()((set, get) => {
157
194
  };
158
195
  });
159
196
 
197
+ const DEFAULT_VIEW_ID$1 = 'default';
160
198
  const useHeatmapVizStore = create()((set, get) => {
161
199
  return {
162
- isRenderViz: false,
163
- setIsRenderViz: (isRenderViz) => set({ isRenderViz }),
164
- zoomRatio: 100,
165
- minZoomRatio: 10,
166
- setMinZoomRatio: (minZoomRatio) => set({ minZoomRatio }),
167
- setZoomRatio: (zoomRatio) => set({ zoomRatio }),
168
- scale: 1,
169
- setScale: (scale) => set({ scale }),
170
- isScaledToFit: false,
171
- setIsScaledToFit: (isScaledToFit) => set({ isScaledToFit }),
200
+ isRenderViz: { [DEFAULT_VIEW_ID$1]: false },
201
+ zoomRatio: { [DEFAULT_VIEW_ID$1]: 100 },
202
+ minZoomRatio: { [DEFAULT_VIEW_ID$1]: 10 },
203
+ scale: { [DEFAULT_VIEW_ID$1]: 1 },
204
+ isScaledToFit: { [DEFAULT_VIEW_ID$1]: false },
205
+ setIsRenderViz: (isRenderViz, viewId = DEFAULT_VIEW_ID$1) => set((state) => ({
206
+ isRenderViz: { ...state.isRenderViz, [viewId]: isRenderViz },
207
+ })),
208
+ setZoomRatio: (zoomRatio, viewId = DEFAULT_VIEW_ID$1) => set((state) => ({
209
+ zoomRatio: { ...state.zoomRatio, [viewId]: zoomRatio },
210
+ })),
211
+ setMinZoomRatio: (minZoomRatio, viewId = DEFAULT_VIEW_ID$1) => set((state) => ({
212
+ minZoomRatio: { ...state.minZoomRatio, [viewId]: minZoomRatio },
213
+ })),
214
+ setScale: (scale, viewId = DEFAULT_VIEW_ID$1) => set((state) => ({
215
+ scale: { ...state.scale, [viewId]: scale },
216
+ })),
217
+ setIsScaledToFit: (isScaledToFit, viewId = DEFAULT_VIEW_ID$1) => set((state) => ({
218
+ isScaledToFit: { ...state.isScaledToFit, [viewId]: isScaledToFit },
219
+ })),
220
+ copyView: (fromViewId, toViewId) => set((state) => ({
221
+ isRenderViz: { ...state.isRenderViz, [toViewId]: state.isRenderViz[fromViewId] ?? false },
222
+ zoomRatio: { ...state.zoomRatio, [toViewId]: state.zoomRatio[fromViewId] ?? 100 },
223
+ minZoomRatio: { ...state.minZoomRatio, [toViewId]: state.minZoomRatio[fromViewId] ?? 10 },
224
+ scale: { ...state.scale, [toViewId]: state.scale[fromViewId] ?? 1 },
225
+ isScaledToFit: { ...state.isScaledToFit, [toViewId]: state.isScaledToFit[fromViewId] ?? false },
226
+ })),
227
+ clearView: (viewId) => set((state) => {
228
+ const newIsRenderViz = { ...state.isRenderViz };
229
+ const newZoomRatio = { ...state.zoomRatio };
230
+ const newMinZoomRatio = { ...state.minZoomRatio };
231
+ const newScale = { ...state.scale };
232
+ const newIsScaledToFit = { ...state.isScaledToFit };
233
+ delete newIsRenderViz[viewId];
234
+ delete newZoomRatio[viewId];
235
+ delete newMinZoomRatio[viewId];
236
+ delete newScale[viewId];
237
+ delete newIsScaledToFit[viewId];
238
+ return {
239
+ isRenderViz: newIsRenderViz,
240
+ zoomRatio: newZoomRatio,
241
+ minZoomRatio: newMinZoomRatio,
242
+ scale: newScale,
243
+ isScaledToFit: newIsScaledToFit,
244
+ };
245
+ }),
246
+ resetAll: () => set({
247
+ isRenderViz: { [DEFAULT_VIEW_ID$1]: false },
248
+ zoomRatio: { [DEFAULT_VIEW_ID$1]: 100 },
249
+ minZoomRatio: { [DEFAULT_VIEW_ID$1]: 10 },
250
+ scale: { [DEFAULT_VIEW_ID$1]: 1 },
251
+ isScaledToFit: { [DEFAULT_VIEW_ID$1]: false },
252
+ }),
172
253
  };
173
254
  });
174
255
 
@@ -186,8 +267,6 @@ const useHeatmapVizScrollmapStore = create()((set, get) => {
186
267
  const initialState = {
187
268
  payloads: [],
188
269
  htmlContent: '',
189
- wrapperHeight: 0,
190
- iframeHeight: 0,
191
270
  };
192
271
  const useHeatmapLiveStore = create()((set, get) => {
193
272
  return {
@@ -196,17 +275,179 @@ const useHeatmapLiveStore = create()((set, get) => {
196
275
  setPayloads: (payloads) => set({ payloads }),
197
276
  addPayload: (payload) => set((state) => ({ payloads: [...state.payloads, payload] })),
198
277
  setHtmlContent: (htmlContent) => set({ htmlContent }),
199
- setWrapperHeight: (wrapperHeight) => set({ wrapperHeight }),
200
- setIframeHeight: (iframeHeight) => set({ iframeHeight }),
201
278
  };
202
279
  });
203
280
 
281
+ const DEFAULT_VIEW_ID = 'default';
204
282
  const useHeatmapSingleStore = create()((set, get) => {
205
283
  return {
206
- vizRef: null,
207
- iframeHeight: 0,
208
- setVizRef: (vizRef) => set({ vizRef }),
209
- setIframeHeight: (iframeHeight) => set({ iframeHeight }),
284
+ vizRef: { [DEFAULT_VIEW_ID]: null },
285
+ iframeHeight: { [DEFAULT_VIEW_ID]: 0 },
286
+ wrapperHeight: { [DEFAULT_VIEW_ID]: 0 },
287
+ setVizRef: (vizRef, viewId = DEFAULT_VIEW_ID) => set((state) => ({
288
+ vizRef: { ...state.vizRef, [viewId]: vizRef },
289
+ })),
290
+ setIframeHeight: (iframeHeight, viewId = DEFAULT_VIEW_ID) => {
291
+ set((state) => ({
292
+ iframeHeight: { ...state.iframeHeight, [viewId]: iframeHeight },
293
+ }));
294
+ },
295
+ setWrapperHeight: (wrapperHeight, viewId = DEFAULT_VIEW_ID) => {
296
+ set((state) => ({
297
+ wrapperHeight: { ...state.wrapperHeight, [viewId]: wrapperHeight },
298
+ }));
299
+ },
300
+ copyView: (fromViewId, toViewId) => set((state) => ({
301
+ // Don't copy vizRef - each view needs its own visualizer instance
302
+ iframeHeight: { ...state.iframeHeight, [toViewId]: state.iframeHeight[fromViewId] ?? 0 },
303
+ wrapperHeight: { ...state.wrapperHeight, [toViewId]: state.wrapperHeight[fromViewId] ?? 0 },
304
+ })),
305
+ clearView: (viewId) => set((state) => {
306
+ const newVizRef = { ...state.vizRef };
307
+ const newIframeHeight = { ...state.iframeHeight };
308
+ const newWrapperHeight = { ...state.wrapperHeight };
309
+ delete newVizRef[viewId];
310
+ delete newIframeHeight[viewId];
311
+ delete newWrapperHeight[viewId];
312
+ return {
313
+ vizRef: newVizRef,
314
+ iframeHeight: newIframeHeight,
315
+ wrapperHeight: newWrapperHeight,
316
+ };
317
+ }),
318
+ resetAll: () => set({
319
+ vizRef: { [DEFAULT_VIEW_ID]: null },
320
+ iframeHeight: { [DEFAULT_VIEW_ID]: 0 },
321
+ wrapperHeight: { [DEFAULT_VIEW_ID]: 0 },
322
+ }),
323
+ };
324
+ });
325
+
326
+ const createDefaultView = (id, label, options) => ({
327
+ id,
328
+ label,
329
+ heatmapType: options?.heatmapType ?? IHeatmapType.Scroll,
330
+ clickType: options?.clickType ?? IClickType.Total,
331
+ scrollType: options?.scrollType ?? IScrollType.Depth,
332
+ data: options?.data,
333
+ clickmap: undefined,
334
+ scrollmap: undefined,
335
+ dataInfo: undefined,
336
+ vizRef: null,
337
+ iframeHeight: 0,
338
+ zoomRatio: 100,
339
+ scale: 1,
340
+ isScaledToFit: false,
341
+ isRendering: true,
342
+ isRenderViz: false,
343
+ });
344
+ const useHeatmapCompareStore = create()((set, get) => {
345
+ return {
346
+ views: new Map(),
347
+ viewOrder: [],
348
+ layout: 'grid-2',
349
+ syncSettings: {
350
+ zoomRatio: false,
351
+ scrolling: false,
352
+ heatmapType: false,
353
+ },
354
+ viewIdCounter: 0,
355
+ addView: (options) => {
356
+ const state = get();
357
+ const viewId = `view-${state.viewIdCounter}`;
358
+ const label = options?.label ?? `Version ${state.viewOrder.length + 1}`;
359
+ const newView = createDefaultView(viewId, label, options);
360
+ const newViews = new Map(state.views);
361
+ newViews.set(viewId, newView);
362
+ set({
363
+ views: newViews,
364
+ viewOrder: [...state.viewOrder, viewId],
365
+ viewIdCounter: state.viewIdCounter + 1,
366
+ });
367
+ return viewId;
368
+ },
369
+ removeView: (viewId) => {
370
+ const state = get();
371
+ const newViews = new Map(state.views);
372
+ newViews.delete(viewId);
373
+ set({
374
+ views: newViews,
375
+ viewOrder: state.viewOrder.filter((id) => id !== viewId),
376
+ });
377
+ },
378
+ updateView: (viewId, updates) => {
379
+ const state = get();
380
+ const view = state.views.get(viewId);
381
+ if (!view)
382
+ return;
383
+ const newViews = new Map(state.views);
384
+ newViews.set(viewId, { ...view, ...updates });
385
+ set({ views: newViews });
386
+ // Handle syncing
387
+ const { syncSettings } = state;
388
+ if (syncSettings.zoomRatio && 'zoomRatio' in updates && updates.zoomRatio !== undefined) {
389
+ get().syncProperty('zoomRatio', updates.zoomRatio);
390
+ }
391
+ if (syncSettings.heatmapType &&
392
+ 'heatmapType' in updates &&
393
+ updates.heatmapType !== undefined) {
394
+ get().syncProperty('heatmapType', updates.heatmapType);
395
+ }
396
+ },
397
+ getView: (viewId) => {
398
+ return get().views.get(viewId);
399
+ },
400
+ setLayout: (layout) => {
401
+ set({ layout });
402
+ },
403
+ setSyncSettings: (settings) => {
404
+ set({ syncSettings: { ...get().syncSettings, ...settings } });
405
+ },
406
+ initializeCompare: (count, options) => {
407
+ const viewIds = [];
408
+ const newViews = new Map();
409
+ for (let i = 0; i < count; i++) {
410
+ const viewId = `view-${i}`;
411
+ const label = options?.label ?? String.fromCharCode(65 + i); // A, B, C, D
412
+ newViews.set(viewId, createDefaultView(viewId, `Version ${label}`, options));
413
+ viewIds.push(viewId);
414
+ }
415
+ const layoutMap = {
416
+ 2: 'grid-2',
417
+ 3: 'grid-3',
418
+ 4: 'grid-4',
419
+ };
420
+ set({
421
+ views: newViews,
422
+ viewOrder: viewIds,
423
+ layout: layoutMap[count],
424
+ viewIdCounter: count,
425
+ });
426
+ },
427
+ resetCompare: () => {
428
+ set({
429
+ views: new Map(),
430
+ viewOrder: [],
431
+ layout: 'grid-2',
432
+ viewIdCounter: 0,
433
+ syncSettings: {
434
+ zoomRatio: false,
435
+ scrolling: false,
436
+ heatmapType: false,
437
+ },
438
+ });
439
+ },
440
+ syncProperty: (property, value) => {
441
+ const state = get();
442
+ const newViews = new Map(state.views);
443
+ state.viewOrder.forEach((viewId) => {
444
+ const view = newViews.get(viewId);
445
+ if (view) {
446
+ newViews.set(viewId, { ...view, [property]: value });
447
+ }
448
+ });
449
+ set({ views: newViews });
450
+ },
210
451
  };
211
452
  });
212
453
 
@@ -215,7 +456,7 @@ const useRegisterConfig = () => {
215
456
  const width = useHeatmapConfigStore((state) => state.width);
216
457
  const sidebarWidth = useHeatmapConfigStore((state) => state.sidebarWidth);
217
458
  const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
218
- const setIsRendering = useHeatmapDataStore((state) => state.setIsRendering);
459
+ const setIsRendering = useHeatmapConfigStore((state) => state.setIsRendering);
219
460
  useEffect(() => {
220
461
  setIsRendering(true);
221
462
  setTimeout(() => {
@@ -234,10 +475,54 @@ const useRegisterControl = (control) => {
234
475
  registerControl('ElementCallout', control.ElementCallout);
235
476
  };
236
477
 
237
- const useRegisterData = (data, dataInfo) => {
478
+ /**
479
+ * Context to provide viewId to components
480
+ * Used in compare mode to isolate data between views
481
+ */
482
+ const ViewIdContext = createContext(undefined);
483
+ /**
484
+ * Hook to get current viewId
485
+ * Returns 'default' if not in a ViewIdContext (single mode)
486
+ */
487
+ const useViewId = () => {
488
+ const viewId = useContext(ViewIdContext);
489
+ return viewId || 'default';
490
+ };
491
+ /**
492
+ * Hook to check if currently in compare mode
493
+ */
494
+ const useIsCompareMode = () => {
495
+ const viewId = useContext(ViewIdContext);
496
+ return viewId !== undefined && viewId !== 'default';
497
+ };
498
+
499
+ const useHeatmapData = (props) => {
500
+ const viewId = props?.viewId || useViewId();
501
+ const data = useHeatmapDataStore((state) => state.data[viewId]);
502
+ const clickmap = useHeatmapDataStore((state) => state.clickmap[viewId]);
503
+ const scrollmap = useHeatmapDataStore((state) => state.scrollmap[viewId]);
504
+ const dataInfo = useHeatmapDataStore((state) => state.dataInfo[viewId]);
238
505
  const setData = useHeatmapDataStore((state) => state.setData);
239
- const setIsRendering = useHeatmapDataStore((state) => state.setIsRendering);
506
+ const setClickmap = useHeatmapDataStore((state) => state.setClickmap);
507
+ const setScrollmap = useHeatmapDataStore((state) => state.setScrollmap);
240
508
  const setDataInfo = useHeatmapDataStore((state) => state.setDataInfo);
509
+ return {
510
+ // Data
511
+ data,
512
+ clickmap,
513
+ scrollmap,
514
+ dataInfo,
515
+ // Setters (auto-inject viewId)
516
+ setData: (newData) => setData(newData, viewId),
517
+ setClickmap: (newClickmap) => setClickmap(newClickmap, viewId),
518
+ setScrollmap: (newScrollmap) => setScrollmap(newScrollmap, viewId),
519
+ setDataInfo: (newDataInfo) => setDataInfo(newDataInfo, viewId),
520
+ };
521
+ };
522
+
523
+ const useRegisterData = (data, dataInfo) => {
524
+ const setIsRendering = useHeatmapConfigStore((state) => state.setIsRendering);
525
+ const { setData, setDataInfo } = useHeatmapData();
241
526
  const handleSetData = useCallback((data) => {
242
527
  if (!data)
243
528
  return;
@@ -258,8 +543,7 @@ const useRegisterData = (data, dataInfo) => {
258
543
  };
259
544
 
260
545
  const useRegisterHeatmap = ({ clickmap, scrollmap }) => {
261
- const setClickmap = useHeatmapDataStore((state) => state.setClickmap);
262
- const setScrollmap = useHeatmapDataStore((state) => state.setScrollmap);
546
+ const { setClickmap, setScrollmap } = useHeatmapData();
263
547
  const handleSetClickmap = useCallback((clickmap) => {
264
548
  if (!clickmap)
265
549
  return;
@@ -1133,6 +1417,48 @@ function initIframeHelperFixer(config) {
1133
1417
  return fixer;
1134
1418
  }
1135
1419
 
1420
+ const useHeatmapViz = (props) => {
1421
+ const viewId = props?.viewId || useViewId();
1422
+ // Viz store
1423
+ const isRenderViz = useHeatmapVizStore((state) => state.isRenderViz[viewId] ?? false);
1424
+ const zoomRatio = useHeatmapVizStore((state) => state.zoomRatio[viewId] ?? 100);
1425
+ const minZoomRatio = useHeatmapVizStore((state) => state.minZoomRatio[viewId] ?? 10);
1426
+ const widthScale = useHeatmapVizStore((state) => state.scale[viewId] ?? 1);
1427
+ const isScaledToFit = useHeatmapVizStore((state) => state.isScaledToFit[viewId] ?? false);
1428
+ const setIsRenderViz = useHeatmapVizStore((state) => state.setIsRenderViz);
1429
+ const setZoomRatio = useHeatmapVizStore((state) => state.setZoomRatio);
1430
+ const setMinZoomRatio = useHeatmapVizStore((state) => state.setMinZoomRatio);
1431
+ const setScale = useHeatmapVizStore((state) => state.setScale);
1432
+ const setIsScaledToFit = useHeatmapVizStore((state) => state.setIsScaledToFit);
1433
+ // Single store
1434
+ const vizRef = useHeatmapSingleStore((state) => state.vizRef[viewId] ?? null);
1435
+ const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight[viewId] ?? 0);
1436
+ const wrapperHeight = useHeatmapSingleStore((state) => state.wrapperHeight[viewId] ?? 0);
1437
+ const setVizRef = useHeatmapSingleStore((state) => state.setVizRef);
1438
+ const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
1439
+ const setWrapperHeight = useHeatmapSingleStore((state) => state.setWrapperHeight);
1440
+ return {
1441
+ // State
1442
+ isRenderViz,
1443
+ zoomRatio,
1444
+ minZoomRatio,
1445
+ widthScale,
1446
+ isScaledToFit,
1447
+ vizRef,
1448
+ iframeHeight,
1449
+ wrapperHeight,
1450
+ // Setters (auto-inject viewId)
1451
+ setIsRenderViz: (value) => setIsRenderViz(value, viewId),
1452
+ setZoomRatio: (value) => setZoomRatio(value, viewId),
1453
+ setMinZoomRatio: (value) => setMinZoomRatio(value, viewId),
1454
+ setScale: (value) => setScale(value, viewId),
1455
+ setIsScaledToFit: (value) => setIsScaledToFit(value, viewId),
1456
+ setVizRef: (value) => setVizRef(value, viewId),
1457
+ setIframeHeight: (value) => setIframeHeight(value, viewId),
1458
+ setWrapperHeight: (value) => setWrapperHeight(value, viewId),
1459
+ };
1460
+ };
1461
+
1136
1462
  const scrollToElementIfNeeded = (visualRef, rect, scale) => {
1137
1463
  if (!visualRef.current)
1138
1464
  return;
@@ -1151,11 +1477,11 @@ const scrollToElementIfNeeded = (visualRef, rect, scale) => {
1151
1477
  });
1152
1478
  };
1153
1479
  const useClickedElement = ({ visualRef, getRect }) => {
1154
- const heatmapInfo = useHeatmapDataStore((state) => state.dataInfo);
1155
1480
  const selectedElement = useHeatmapInteractionStore((state) => state.selectedElement);
1156
1481
  const shouldShowCallout = useHeatmapInteractionStore((state) => state.shouldShowCallout);
1157
1482
  const setShouldShowCallout = useHeatmapInteractionStore((state) => state.setShouldShowCallout);
1158
- const scale = useHeatmapVizStore((state) => state.scale);
1483
+ const { widthScale } = useHeatmapViz();
1484
+ const { dataInfo } = useHeatmapData();
1159
1485
  const [clickedElement, setClickedElement] = useState(null);
1160
1486
  const [showMissingElement, setShowMissingElement] = useState(false);
1161
1487
  const reset = () => {
@@ -1164,11 +1490,11 @@ const useClickedElement = ({ visualRef, getRect }) => {
1164
1490
  setShouldShowCallout(false);
1165
1491
  };
1166
1492
  useEffect(() => {
1167
- if (!selectedElement || !heatmapInfo?.elementMapInfo) {
1493
+ if (!selectedElement || !dataInfo?.elementMapInfo) {
1168
1494
  reset();
1169
1495
  return;
1170
1496
  }
1171
- const info = heatmapInfo.elementMapInfo[selectedElement];
1497
+ const info = dataInfo.elementMapInfo[selectedElement];
1172
1498
  if (!info) {
1173
1499
  setClickedElement(null);
1174
1500
  return;
@@ -1176,7 +1502,7 @@ const useClickedElement = ({ visualRef, getRect }) => {
1176
1502
  const hash = selectedElement;
1177
1503
  const selector = info.selector;
1178
1504
  const rect = getRect({ hash: selectedElement, selector });
1179
- const elementInfo = buildElementInfo(hash, rect, heatmapInfo);
1505
+ const elementInfo = buildElementInfo(hash, rect, dataInfo);
1180
1506
  if (!rect) {
1181
1507
  setClickedElement(elementInfo);
1182
1508
  setShowMissingElement(true);
@@ -1184,29 +1510,29 @@ const useClickedElement = ({ visualRef, getRect }) => {
1184
1510
  return;
1185
1511
  }
1186
1512
  setShowMissingElement(false);
1187
- scrollToElementIfNeeded(visualRef, rect, scale);
1513
+ scrollToElementIfNeeded(visualRef, rect, widthScale);
1188
1514
  setShouldShowCallout(true);
1189
1515
  requestAnimationFrame(() => {
1190
1516
  setClickedElement(elementInfo);
1191
1517
  });
1192
- }, [selectedElement, heatmapInfo, getRect, visualRef, scale]);
1518
+ }, [selectedElement, dataInfo, getRect, visualRef, widthScale]);
1193
1519
  return { clickedElement, showMissingElement, shouldShowCallout, setShouldShowCallout };
1194
1520
  };
1195
1521
 
1196
1522
  const useElementCalloutVisible = ({ visualRef, getRect }) => {
1197
- const scale = useHeatmapVizStore((state) => state.scale);
1198
1523
  const selectedElement = useHeatmapInteractionStore((state) => state.selectedElement);
1199
- const heatmapInfo = useHeatmapDataStore((state) => state.dataInfo);
1200
1524
  const setShouldShowCallout = useHeatmapInteractionStore((state) => state.setShouldShowCallout);
1525
+ const { widthScale } = useHeatmapViz();
1526
+ const { dataInfo } = useHeatmapData();
1201
1527
  useEffect(() => {
1202
1528
  if (!selectedElement)
1203
1529
  return;
1204
1530
  const elementIsInViewportFn = () => {
1205
- const elementInfo = heatmapInfo?.elementMapInfo?.[selectedElement];
1531
+ const elementInfo = dataInfo?.elementMapInfo?.[selectedElement];
1206
1532
  if (!elementInfo)
1207
1533
  return;
1208
1534
  const rect = getRect({ hash: selectedElement, selector: elementInfo.selector });
1209
- const isInViewport = isElementInViewport(rect, visualRef, scale);
1535
+ const isInViewport = isElementInViewport(rect, visualRef, widthScale);
1210
1536
  setShouldShowCallout(isInViewport);
1211
1537
  };
1212
1538
  elementIsInViewportFn();
@@ -1221,7 +1547,7 @@ const useElementCalloutVisible = ({ visualRef, getRect }) => {
1221
1547
  window.removeEventListener('resize', handleUpdate);
1222
1548
  visualRef?.current?.removeEventListener('scroll', handleUpdate);
1223
1549
  };
1224
- }, [selectedElement, visualRef, getRect, scale, heatmapInfo, setShouldShowCallout]);
1550
+ }, [selectedElement, visualRef, getRect, widthScale, dataInfo, setShouldShowCallout]);
1225
1551
  return {};
1226
1552
  };
1227
1553
 
@@ -1244,9 +1570,8 @@ const useHeatmapEffects = ({ isVisible, isElementSidebarOpen, setShouldShowCallo
1244
1570
  };
1245
1571
 
1246
1572
  const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
1247
- const widthScale = useHeatmapVizStore((state) => state.scale);
1248
- const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
1249
1573
  const heatmapWidth = useHeatmapConfigStore((state) => state.width);
1574
+ const { iframeHeight, widthScale } = useHeatmapViz();
1250
1575
  return useCallback((element) => {
1251
1576
  const hash = element?.hash;
1252
1577
  if (!iframeRef.current?.contentDocument || !hash || !visualizer)
@@ -1400,8 +1725,8 @@ const useHoveredElement = ({ iframeRef, getRect }) => {
1400
1725
  const hoveredElement = useHeatmapInteractionStore((state) => state.hoveredElement);
1401
1726
  const setHoveredElement = useHeatmapInteractionStore((state) => state.setHoveredElement);
1402
1727
  const onSelect = useHeatmapInteractionStore((state) => state.setSelectedElement);
1403
- const widthScale = useHeatmapVizStore((state) => state.scale);
1404
- const heatmapInfo = useHeatmapDataStore((state) => state.dataInfo);
1728
+ const { widthScale } = useHeatmapViz();
1729
+ const { dataInfo } = useHeatmapData();
1405
1730
  const reset = useCallback(() => {
1406
1731
  setHoveredElement(null);
1407
1732
  }, [setHoveredElement]);
@@ -1409,7 +1734,7 @@ const useHoveredElement = ({ iframeRef, getRect }) => {
1409
1734
  reset();
1410
1735
  }, [reset]);
1411
1736
  const getHashFromEvent = useCallback((event) => {
1412
- if (!heatmapInfo || !isIframeReady(iframeRef, heatmapInfo)) {
1737
+ if (!dataInfo || !isIframeReady(iframeRef, dataInfo)) {
1413
1738
  reset();
1414
1739
  return;
1415
1740
  }
@@ -1417,8 +1742,8 @@ const useHoveredElement = ({ iframeRef, getRect }) => {
1417
1742
  const doc = iframe.contentDocument;
1418
1743
  const iframeRect = iframe.getBoundingClientRect();
1419
1744
  const { x, y } = convertViewportToIframeCoords(event.clientX, event.clientY, iframeRect, widthScale);
1420
- const targetElement = findTargetElement(doc, x, y, heatmapInfo);
1421
- if (!targetElement || !isValidElement(targetElement, heatmapInfo)) {
1745
+ const targetElement = findTargetElement(doc, x, y, dataInfo);
1746
+ if (!targetElement || !isValidElement(targetElement, dataInfo)) {
1422
1747
  reset();
1423
1748
  return;
1424
1749
  }
@@ -1427,9 +1752,9 @@ const useHoveredElement = ({ iframeRef, getRect }) => {
1427
1752
  return hash;
1428
1753
  reset();
1429
1754
  return;
1430
- }, [heatmapInfo, iframeRef, getRect, widthScale, reset]);
1755
+ }, [dataInfo, iframeRef, getRect, widthScale, reset]);
1431
1756
  const handleMouseMove = useCallback(debounce((event) => {
1432
- if (!heatmapInfo) {
1757
+ if (!dataInfo) {
1433
1758
  reset();
1434
1759
  return;
1435
1760
  }
@@ -1438,15 +1763,15 @@ const useHoveredElement = ({ iframeRef, getRect }) => {
1438
1763
  reset();
1439
1764
  return;
1440
1765
  }
1441
- const selector = heatmapInfo?.elementMapInfo?.[hash];
1766
+ const selector = dataInfo?.elementMapInfo?.[hash];
1442
1767
  const rect = getRect({ hash, selector });
1443
- const elementInfo = buildElementInfo(hash, rect, heatmapInfo);
1768
+ const elementInfo = buildElementInfo(hash, rect, dataInfo);
1444
1769
  if (!elementInfo) {
1445
1770
  reset();
1446
1771
  return;
1447
1772
  }
1448
1773
  setHoveredElement(elementInfo);
1449
- }, 16), [heatmapInfo, getRect, reset, getHashFromEvent]);
1774
+ }, 16), [dataInfo, getRect, reset, getHashFromEvent]);
1450
1775
  const handleClick = useCallback(() => {
1451
1776
  if (!hoveredElement?.hash)
1452
1777
  return;
@@ -1562,11 +1887,9 @@ function useVizLiveIframeMsg(options = {}) {
1562
1887
  }
1563
1888
 
1564
1889
  function useVizLiveRender() {
1565
- const wrapperHeight = useHeatmapLiveStore((state) => state.wrapperHeight);
1566
- const setIframeHeight = useHeatmapLiveStore((state) => state.setIframeHeight);
1890
+ const { setIframeHeight, wrapperHeight, setIsRenderViz } = useHeatmapViz();
1567
1891
  const contentWidth = useHeatmapConfigStore((state) => state.width);
1568
1892
  const htmlContent = useHeatmapLiveStore((state) => state.htmlContent);
1569
- const setIsRenderViz = useHeatmapVizStore((state) => state.setIsRenderViz);
1570
1893
  const { iframeRef, isReady } = useVizLiveIframeMsg();
1571
1894
  useEffect(() => {
1572
1895
  if (!htmlContent || !iframeRef.current)
@@ -1611,16 +1934,14 @@ function reset(iframe, rect, onSuccess) {
1611
1934
  fixer.enableNavigationBlocking();
1612
1935
  }
1613
1936
 
1614
- let visualizer = new Visualizer();
1615
1937
  const useHeatmapRender = () => {
1616
- const data = useHeatmapDataStore((state) => state.data);
1617
- const setVizRef = useHeatmapSingleStore((state) => state.setVizRef);
1618
- const setIsRenderViz = useHeatmapVizStore((state) => state.setIsRenderViz);
1619
- const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
1938
+ const { data } = useHeatmapData();
1939
+ const { vizRef, setVizRef, setIsRenderViz, setIframeHeight } = useHeatmapViz();
1620
1940
  const iframeRef = useRef(null);
1621
1941
  const renderHeatmap = useCallback(async (payloads) => {
1622
1942
  if (!payloads || payloads.length === 0)
1623
1943
  return;
1944
+ const visualizer = vizRef || new Visualizer();
1624
1945
  setIsRenderViz(false);
1625
1946
  const iframe = iframeRef.current;
1626
1947
  if (!iframe?.contentWindow)
@@ -1671,8 +1992,8 @@ function sortEvents(a, b) {
1671
1992
  }
1672
1993
 
1673
1994
  const useReplayRender = () => {
1674
- const data = useHeatmapDataStore((state) => state.data);
1675
1995
  const setWidth = useHeatmapConfigStore((state) => state.setWidth);
1996
+ const { data } = useHeatmapData();
1676
1997
  const visualizerRef = useRef(null);
1677
1998
  const iframeRef = useRef(null);
1678
1999
  const eventsRef = useRef([]);
@@ -1843,8 +2164,7 @@ const useContentDimensions = ({ iframeRef, }) => {
1843
2164
  };
1844
2165
 
1845
2166
  const useObserveIframeHeight = (props) => {
1846
- const { iframeRef, setIframeHeight } = props;
1847
- const isRenderViz = useHeatmapVizStore((state) => state.isRenderViz);
2167
+ const { iframeRef, setIframeHeight, isRenderViz } = props;
1848
2168
  const resizeObserverRef = useRef(null);
1849
2169
  const mutationObserverRef = useRef(null);
1850
2170
  const debounceTimerRef = useRef(null);
@@ -1969,13 +2289,8 @@ const useObserveIframeHeight = (props) => {
1969
2289
  };
1970
2290
 
1971
2291
  const useScaleCalculation = (props) => {
1972
- const scale = useHeatmapVizStore((state) => state.scale);
1973
- const zoomRatio = useHeatmapVizStore((state) => state.zoomRatio);
1974
- const setScale = useHeatmapVizStore((state) => state.setScale);
1975
- const isScaledToFit = useHeatmapVizStore((state) => state.isScaledToFit);
1976
- const setIsScaledToFit = useHeatmapVizStore((state) => state.setIsScaledToFit);
1977
- const minZoomRatio = useHeatmapVizStore((state) => state.minZoomRatio);
1978
- const setMinZoomRatio = useHeatmapVizStore((state) => state.setMinZoomRatio);
2292
+ const { widthScale, zoomRatio, isScaledToFit, minZoomRatio } = useHeatmapViz();
2293
+ const { setScale, setIsScaledToFit, setMinZoomRatio } = useHeatmapViz();
1979
2294
  const { containerWidth, containerHeight, contentWidth, contentHeight } = props;
1980
2295
  const calculateScaleResult = useCallback(() => {
1981
2296
  if (containerWidth > 0 && contentWidth > 0 && containerHeight > 0 && contentHeight > 0) {
@@ -2015,11 +2330,10 @@ const useScaleCalculation = (props) => {
2015
2330
  useEffect(() => {
2016
2331
  calculateScaleResult();
2017
2332
  }, [calculateScaleResult]);
2018
- return { scale, isScaledToFit, minZoomRatio };
2333
+ return { widthScale, isScaledToFit, minZoomRatio };
2019
2334
  };
2020
2335
 
2021
- const useScrollSync = ({ iframeRef }) => {
2022
- const widthScale = useHeatmapVizStore((state) => state.scale);
2336
+ const useScrollSync = ({ widthScale, iframeRef, }) => {
2023
2337
  const handleScroll = useCallback((scrollTop) => {
2024
2338
  const iframe = iframeRef.current;
2025
2339
  if (!iframe || widthScale <= 0)
@@ -2040,24 +2354,24 @@ const useScrollSync = ({ iframeRef }) => {
2040
2354
  };
2041
2355
 
2042
2356
  const useHeatmapScale = (props) => {
2043
- const { wrapperRef, iframeRef, iframeHeight, setIframeHeight } = props;
2357
+ const { wrapperRef, iframeRef, iframeHeight, setIframeHeight, isRenderViz } = props;
2044
2358
  // 1. Observe container dimensions
2045
2359
  const { containerWidth, containerHeight } = useContainerDimensions({ wrapperRef });
2046
2360
  // 2. Get content dimensions from config
2047
2361
  const { contentWidth } = useContentDimensions({ iframeRef });
2048
2362
  // 3. Observe iframe height (now reacts to width changes)
2049
- useObserveIframeHeight({ iframeRef, setIframeHeight });
2363
+ useObserveIframeHeight({ iframeRef, setIframeHeight, isRenderViz });
2050
2364
  // 4. Calculate scale
2051
- const { scale } = useScaleCalculation({
2365
+ const { widthScale } = useScaleCalculation({
2052
2366
  containerWidth,
2053
2367
  containerHeight,
2054
2368
  contentWidth,
2055
2369
  contentHeight: iframeHeight,
2056
2370
  });
2057
2371
  // 5. Setup scroll sync
2058
- const { handleScroll } = useScrollSync({ iframeRef });
2059
- const scaledHeight = iframeHeight * scale;
2060
- const scaledWidth = contentWidth * scale;
2372
+ const { handleScroll } = useScrollSync({ widthScale, iframeRef });
2373
+ const scaledHeight = iframeHeight * widthScale;
2374
+ const scaledWidth = contentWidth * widthScale;
2061
2375
  return {
2062
2376
  containerWidth,
2063
2377
  containerHeight,
@@ -2068,10 +2382,10 @@ const useHeatmapScale = (props) => {
2068
2382
  };
2069
2383
 
2070
2384
  const useWrapperRefHeight = (props) => {
2071
- const { isActive, wrapperRef, setWrapperHeight } = props;
2072
- const isRenderViz = useHeatmapVizStore((state) => state.isRenderViz);
2385
+ const { isActive, wrapperRef } = props;
2073
2386
  const resizeObserverRef = useRef(null);
2074
2387
  const mutationObserverRef = useRef(null);
2388
+ const { isRenderViz, setWrapperHeight } = useHeatmapViz();
2075
2389
  const updateWrapperHeight = useCallback(() => {
2076
2390
  const wrapper = wrapperRef.current;
2077
2391
  if (!wrapper)
@@ -2079,13 +2393,13 @@ const useWrapperRefHeight = (props) => {
2079
2393
  try {
2080
2394
  const wrapperHeight = wrapper.offsetHeight;
2081
2395
  if (wrapperHeight > 0) {
2082
- setWrapperHeight?.(wrapperHeight);
2396
+ setWrapperHeight(wrapperHeight);
2083
2397
  }
2084
2398
  }
2085
2399
  catch (error) {
2086
2400
  console.warn('Cannot measure iframe content:', error);
2087
2401
  }
2088
- }, [wrapperRef, setWrapperHeight]);
2402
+ }, [wrapperRef]);
2089
2403
  useEffect(() => {
2090
2404
  const wrapper = wrapperRef.current;
2091
2405
  if (!wrapper || !isRenderViz)
@@ -2137,7 +2451,7 @@ const useWrapperRefHeight = (props) => {
2137
2451
  };
2138
2452
 
2139
2453
  const useZonePositions = (options) => {
2140
- const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
2454
+ const { iframeHeight } = useHeatmapViz();
2141
2455
  const getZonePosition = useCallback((zone) => {
2142
2456
  if (!iframeHeight) {
2143
2457
  return null;
@@ -2163,12 +2477,13 @@ const useScrollmapZones = (options) => {
2163
2477
  const { mode = 'basic', enabled = true, iframeRef, wrapperRef } = options;
2164
2478
  const [isReady, setIsReady] = useState(false);
2165
2479
  const [zones, setZones] = useState([]);
2166
- const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
2167
- const scrollMapInfo = useHeatmapDataStore((state) => state.dataInfo?.scrollMapInfo);
2480
+ const { scrollmap } = useHeatmapData();
2481
+ const { dataInfo } = useHeatmapData();
2168
2482
  const { getZonePosition } = useZonePositions();
2483
+ const scrollMapInfo = dataInfo?.scrollMapInfo;
2169
2484
  const maxUsers = useMemo(() => {
2170
2485
  if (!scrollmap || scrollmap.length === 0)
2171
- return 100;
2486
+ return 0;
2172
2487
  return Math.max(...scrollmap.map((d) => d.percUsers));
2173
2488
  }, [scrollmap]);
2174
2489
  const createZones = useCallback((data) => {
@@ -2265,6 +2580,185 @@ const getScrollGradientColor = (normalized) => {
2265
2580
  return `rgb(${r}, ${g}, ${b})`;
2266
2581
  };
2267
2582
 
2583
+ const CompareViewContext = createContext(null);
2584
+ /**
2585
+ * Hook to safely access compare view context (returns null if not in compare mode)
2586
+ */
2587
+ const useCompareViewContextSafe = () => {
2588
+ return useContext(CompareViewContext);
2589
+ };
2590
+
2591
+ /**
2592
+ * Hook that returns data from compare view context if in compare mode,
2593
+ * otherwise returns data from global store
2594
+ */
2595
+ const useCompareAwareData = () => {
2596
+ const compareContext = useCompareViewContextSafe();
2597
+ // Global store values
2598
+ const globalData = useHeatmapDataStore((state) => state.data);
2599
+ const globalClickmap = useHeatmapDataStore((state) => state.clickmap);
2600
+ const globalScrollmap = useHeatmapDataStore((state) => state.scrollmap);
2601
+ const globalDataInfo = useHeatmapDataStore((state) => state.dataInfo);
2602
+ // If in compare mode, use view context
2603
+ if (compareContext) {
2604
+ return {
2605
+ data: compareContext.view.data,
2606
+ clickmap: compareContext.view.clickmap,
2607
+ scrollmap: compareContext.view.scrollmap,
2608
+ dataInfo: compareContext.view.dataInfo,
2609
+ };
2610
+ }
2611
+ // Otherwise use global store
2612
+ return {
2613
+ data: globalData,
2614
+ clickmap: globalClickmap,
2615
+ scrollmap: globalScrollmap,
2616
+ dataInfo: globalDataInfo,
2617
+ };
2618
+ };
2619
+ /**
2620
+ * Hook that returns setters for data
2621
+ * In compare mode, updates the view context
2622
+ * In single/live mode, updates the global store
2623
+ */
2624
+ const useCompareAwareDataSetters = () => {
2625
+ const compareContext = useCompareViewContextSafe();
2626
+ const setDataGlobal = useHeatmapDataStore((state) => state.setData);
2627
+ const setClickmapGlobal = useHeatmapDataStore((state) => state.setClickmap);
2628
+ const setScrollmapGlobal = useHeatmapDataStore((state) => state.setScrollmap);
2629
+ const setDataInfoGlobal = useHeatmapDataStore((state) => state.setDataInfo);
2630
+ if (compareContext) {
2631
+ return {
2632
+ setData: (data) => compareContext.updateView({ data }),
2633
+ setClickmap: (clickmap) => compareContext.updateView({ clickmap }),
2634
+ setScrollmap: (scrollmap) => compareContext.updateView({ scrollmap }),
2635
+ setDataInfo: (dataInfo) => compareContext.updateView({ dataInfo }),
2636
+ };
2637
+ }
2638
+ return {
2639
+ setData: setDataGlobal,
2640
+ setClickmap: setClickmapGlobal,
2641
+ setScrollmap: setScrollmapGlobal,
2642
+ setDataInfo: setDataInfoGlobal,
2643
+ };
2644
+ };
2645
+
2646
+ /**
2647
+ * Hook that returns config from compare view context if in compare mode,
2648
+ * otherwise returns config from global store
2649
+ */
2650
+ const useCompareAwareConfig = () => {
2651
+ const compareContext = useCompareViewContextSafe();
2652
+ // Global store values
2653
+ const globalHeatmapType = useHeatmapConfigStore((state) => state.heatmapType);
2654
+ const globalClickType = useHeatmapConfigStore((state) => state.clickType);
2655
+ const globalScrollType = useHeatmapConfigStore((state) => state.scrollType);
2656
+ // If in compare mode, use view context
2657
+ if (compareContext) {
2658
+ return {
2659
+ heatmapType: compareContext.view.heatmapType,
2660
+ clickType: compareContext.view.clickType,
2661
+ scrollType: compareContext.view.scrollType,
2662
+ };
2663
+ }
2664
+ // Otherwise use global store
2665
+ return {
2666
+ heatmapType: globalHeatmapType,
2667
+ clickType: globalClickType,
2668
+ scrollType: globalScrollType,
2669
+ };
2670
+ };
2671
+ /**
2672
+ * Hook that returns config setters
2673
+ * In compare mode, updates the view context
2674
+ * In single/live mode, updates the global store
2675
+ */
2676
+ const useCompareAwareConfigSetters = () => {
2677
+ const compareContext = useCompareViewContextSafe();
2678
+ const setHeatmapTypeGlobal = useHeatmapConfigStore((state) => state.setHeatmapType);
2679
+ const setClickTypeGlobal = useHeatmapConfigStore((state) => state.setClickType);
2680
+ const setScrollTypeGlobal = useHeatmapConfigStore((state) => state.setScrollType);
2681
+ if (compareContext) {
2682
+ return {
2683
+ setHeatmapType: (heatmapType) => compareContext.updateView({ heatmapType }),
2684
+ setClickType: (clickType) => compareContext.updateView({ clickType }),
2685
+ setScrollType: (scrollType) => compareContext.updateView({ scrollType }),
2686
+ };
2687
+ }
2688
+ return {
2689
+ setHeatmapType: setHeatmapTypeGlobal,
2690
+ setClickType: setClickTypeGlobal,
2691
+ setScrollType: setScrollTypeGlobal,
2692
+ };
2693
+ };
2694
+
2695
+ /**
2696
+ * Hook that returns viz state from compare view context if in compare mode,
2697
+ * otherwise returns viz state from global store
2698
+ */
2699
+ const useCompareAwareViz = () => {
2700
+ const compareContext = useCompareViewContextSafe();
2701
+ // Global store values
2702
+ const globalZoomRatio = useHeatmapVizStore((state) => state.zoomRatio);
2703
+ const globalScale = useHeatmapVizStore((state) => state.scale);
2704
+ const globalIsScaledToFit = useHeatmapVizStore((state) => state.isScaledToFit);
2705
+ const globalIsRenderViz = useHeatmapVizStore((state) => state.isRenderViz);
2706
+ const globalIframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
2707
+ const globalVizRef = useHeatmapSingleStore((state) => state.vizRef);
2708
+ // If in compare mode, use view context
2709
+ if (compareContext) {
2710
+ return {
2711
+ zoomRatio: compareContext.view.zoomRatio,
2712
+ scale: compareContext.view.scale,
2713
+ isScaledToFit: compareContext.view.isScaledToFit,
2714
+ isRenderViz: compareContext.view.isRenderViz,
2715
+ iframeHeight: compareContext.view.iframeHeight,
2716
+ vizRef: compareContext.view.vizRef,
2717
+ };
2718
+ }
2719
+ // Otherwise use global store
2720
+ return {
2721
+ zoomRatio: globalZoomRatio,
2722
+ scale: globalScale,
2723
+ isScaledToFit: globalIsScaledToFit,
2724
+ isRenderViz: globalIsRenderViz,
2725
+ iframeHeight: globalIframeHeight,
2726
+ vizRef: globalVizRef,
2727
+ };
2728
+ };
2729
+ /**
2730
+ * Hook that returns viz setters
2731
+ * In compare mode, updates the view context
2732
+ * In single/live mode, updates the global store
2733
+ */
2734
+ const useCompareAwareVizSetters = () => {
2735
+ const compareContext = useCompareViewContextSafe();
2736
+ const setZoomRatioGlobal = useHeatmapVizStore((state) => state.setZoomRatio);
2737
+ const setScaleGlobal = useHeatmapVizStore((state) => state.setScale);
2738
+ const setIsScaledToFitGlobal = useHeatmapVizStore((state) => state.setIsScaledToFit);
2739
+ const setIsRenderVizGlobal = useHeatmapVizStore((state) => state.setIsRenderViz);
2740
+ const setIframeHeightGlobal = useHeatmapSingleStore((state) => state.setIframeHeight);
2741
+ const setVizRefGlobal = useHeatmapSingleStore((state) => state.setVizRef);
2742
+ if (compareContext) {
2743
+ return {
2744
+ setZoomRatio: (zoomRatio) => compareContext.updateView({ zoomRatio }),
2745
+ setScale: (scale) => compareContext.updateView({ scale }),
2746
+ setIsScaledToFit: (isScaledToFit) => compareContext.updateView({ isScaledToFit }),
2747
+ setIsRenderViz: (isRenderViz) => compareContext.updateView({ isRenderViz }),
2748
+ setIframeHeight: (iframeHeight) => compareContext.updateView({ iframeHeight }),
2749
+ setVizRef: (vizRef) => compareContext.updateView({ vizRef }),
2750
+ };
2751
+ }
2752
+ return {
2753
+ setZoomRatio: setZoomRatioGlobal,
2754
+ setScale: setScaleGlobal,
2755
+ setIsScaledToFit: setIsScaledToFitGlobal,
2756
+ setIsRenderViz: setIsRenderVizGlobal,
2757
+ setIframeHeight: setIframeHeightGlobal,
2758
+ setVizRef: setVizRefGlobal,
2759
+ };
2760
+ };
2761
+
2268
2762
  const BoxStack = forwardRef(({ children, ...props }, ref) => {
2269
2763
  const id = props.id;
2270
2764
  const flexDirection = props.flexDirection;
@@ -2310,7 +2804,12 @@ const BoxStack = forwardRef(({ children, ...props }, ref) => {
2310
2804
 
2311
2805
  const ContentTopBar = () => {
2312
2806
  const controls = useHeatmapControlStore((state) => state.controls);
2807
+ useHeatmapConfigStore((state) => state.mode);
2313
2808
  const TopBar = controls.TopBar;
2809
+ // In compare mode, hide individual top bars since we have a global header
2810
+ // if (mode === 'compare') {
2811
+ // return null;
2812
+ // }
2314
2813
  return (jsx(BoxStack, { id: "gx-hm-content-header", flexDirection: "row", alignItems: "center", overflow: "auto", zIndex: 1, backgroundColor: "white", style: {
2315
2814
  borderBottom: `${HEATMAP_CONFIG.borderWidth}px solid ${HEATMAP_CONFIG.borderColor}`,
2316
2815
  }, children: TopBar && jsx(TopBar, {}) }));
@@ -2335,12 +2834,11 @@ const ContentToolbar = () => {
2335
2834
  }, children: controls.Toolbar ?? null }));
2336
2835
  };
2337
2836
 
2338
- const VizContainer = ({ children, setWrapperHeight }) => {
2837
+ const VizContainer = ({ children, isActive = false }) => {
2339
2838
  const wrapperRef = useRef(null);
2340
2839
  useWrapperRefHeight({
2341
- isActive: !!setWrapperHeight,
2840
+ isActive,
2342
2841
  wrapperRef,
2343
- setWrapperHeight,
2344
2842
  });
2345
2843
  return (jsx(BoxStack, { ref: wrapperRef, id: "gx-hm-viz-container", flexDirection: "column", flex: "1 1 auto", overflow: "auto", zIndex: 1, children: jsx(BoxStack, { id: "gx-hm-content", flexDirection: "column", flex: "1 1 auto", overflow: "hidden", style: {
2346
2844
  minWidth: '394px',
@@ -2349,8 +2847,8 @@ const VizContainer = ({ children, setWrapperHeight }) => {
2349
2847
 
2350
2848
  const useClickmap = () => {
2351
2849
  const [isInitialized, setIsInitialized] = useState(false);
2352
- const clickmap = useHeatmapDataStore((state) => state.clickmap);
2353
- const vizRef = useHeatmapSingleStore((state) => state.vizRef);
2850
+ const { clickmap } = useHeatmapData();
2851
+ const { vizRef } = useHeatmapViz();
2354
2852
  const start = useCallback(() => {
2355
2853
  if (isInitialized)
2356
2854
  return;
@@ -2369,8 +2867,8 @@ const useClickmap = () => {
2369
2867
  };
2370
2868
 
2371
2869
  const useScrollmap = () => {
2372
- const vizRef = useHeatmapSingleStore((state) => state.vizRef);
2373
- const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
2870
+ const { vizRef } = useHeatmapViz();
2871
+ const { scrollmap } = useHeatmapData();
2374
2872
  const start = useCallback(() => {
2375
2873
  // if (isInitialized) return;
2376
2874
  if (!vizRef || !scrollmap || scrollmap.length === 0)
@@ -2415,9 +2913,9 @@ const RankBadge = ({ index, elementRect, widthScale, clickOnElement, }) => {
2415
2913
 
2416
2914
  const NUMBER_OF_TOP_ELEMENTS = 10;
2417
2915
  const DefaultRankBadges = ({ getRect, hidden }) => {
2418
- const heatmapInfo = useHeatmapDataStore((state) => state.dataInfo);
2419
- const widthScale = useHeatmapVizStore((state) => state.scale);
2420
- const elements = heatmapInfo?.sortedElements?.slice(0, NUMBER_OF_TOP_ELEMENTS) ?? [];
2916
+ const { dataInfo } = useHeatmapData();
2917
+ const { widthScale } = useHeatmapViz();
2918
+ const elements = dataInfo?.sortedElements?.slice(0, NUMBER_OF_TOP_ELEMENTS) ?? [];
2421
2919
  if (hidden || elements.length === 0)
2422
2920
  return null;
2423
2921
  return (jsx(Fragment, { children: elements.map((element, index) => {
@@ -2474,9 +2972,9 @@ const ElementCallout = (props) => {
2474
2972
  };
2475
2973
 
2476
2974
  const ElementMissing = ({ show = true }) => {
2975
+ const { widthScale } = useHeatmapViz();
2477
2976
  if (!show)
2478
2977
  return null;
2479
- const widthScale = useHeatmapVizStore((state) => state.scale);
2480
2978
  return (jsx("div", { className: "missingElement", style: {
2481
2979
  position: 'fixed',
2482
2980
  top: '50%',
@@ -2505,7 +3003,7 @@ const TARGET_ID_BY_TYPE = {
2505
3003
  },
2506
3004
  };
2507
3005
  const ElementOverlay = ({ type, element, onClick, isSecondary }) => {
2508
- const widthScale = useHeatmapVizStore((state) => state.scale);
3006
+ const { widthScale } = useHeatmapViz();
2509
3007
  if (!element || (element.width === 0 && element.height === 0))
2510
3008
  return null;
2511
3009
  // Iframe has border, so we need to add it to the top position
@@ -2528,7 +3026,7 @@ const ELEMENT_CALLOUT = {
2528
3026
  alignment: 'left',
2529
3027
  };
2530
3028
  const HeatmapElements = (props) => {
2531
- const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
3029
+ const { iframeHeight } = useHeatmapViz();
2532
3030
  const { iframeRef, wrapperRef, visualRef, visualizer, iframeDimensions, isElementSidebarOpen, isVisible = true, areDefaultRanksHidden, isSecondary, } = props;
2533
3031
  const getRect = useHeatmapElementPosition({
2534
3032
  iframeRef,
@@ -2565,9 +3063,9 @@ const HeatmapElements = (props) => {
2565
3063
  };
2566
3064
 
2567
3065
  const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
2568
- const heatmapInfo = useHeatmapDataStore((state) => state.dataInfo);
2569
3066
  const contentWidth = useHeatmapConfigStore((state) => state.width);
2570
- const vizRef = useHeatmapSingleStore((state) => state.vizRef);
3067
+ const { dataInfo } = useHeatmapData();
3068
+ const { vizRef } = useHeatmapViz();
2571
3069
  const visualizer = {
2572
3070
  get: (hash) => {
2573
3071
  if (vizRef) {
@@ -2589,7 +3087,7 @@ const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
2589
3087
  };
2590
3088
  if (!iframeRef.current)
2591
3089
  return null;
2592
- return (jsx(HeatmapElements, { visualizer: visualizer, visualRef: visualRef, iframeRef: iframeRef, wrapperRef: wrapperRef, heatmapInfo: heatmapInfo, isVisible: true, iframeDimensions: {
3090
+ return (jsx(HeatmapElements, { visualizer: visualizer, visualRef: visualRef, iframeRef: iframeRef, wrapperRef: wrapperRef, heatmapInfo: dataInfo, isVisible: true, iframeDimensions: {
2593
3091
  width: contentWidth,
2594
3092
  position: 'absolute',
2595
3093
  top: 0,
@@ -2599,8 +3097,9 @@ const VizElements = ({ iframeRef, visualRef, wrapperRef }) => {
2599
3097
  };
2600
3098
 
2601
3099
  const AverageFoldLine = ({ iframeRef, wrapperRef }) => {
2602
- const averageFold = useHeatmapDataStore((state) => state.dataInfo?.averageFold || 50);
3100
+ const { dataInfo } = useHeatmapData();
2603
3101
  const { getZonePosition } = useZonePositions();
3102
+ const averageFold = dataInfo?.averageFold || 50;
2604
3103
  const position = getZonePosition({
2605
3104
  startY: averageFold,
2606
3105
  endY: averageFold,
@@ -2635,8 +3134,8 @@ const AverageFoldLine = ({ iframeRef, wrapperRef }) => {
2635
3134
  };
2636
3135
 
2637
3136
  const ScrollmapMarker = ({ iframeRef, wrapperRef }) => {
2638
- const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
2639
3137
  const scrollType = useHeatmapConfigStore((state) => state.scrollType);
3138
+ const { scrollmap } = useHeatmapData();
2640
3139
  const { getZonePosition } = useZonePositions();
2641
3140
  if (!scrollmap || scrollmap.length === 0)
2642
3141
  return null;
@@ -2816,7 +3315,7 @@ const MetricsTooltipContent = ({ zone }) => {
2816
3315
  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 })] }));
2817
3316
 
2818
3317
  const HoverZones = ({ iframeRef, wrapperRef, position, currentScrollPercent, }) => {
2819
- const scrollmap = useHeatmapDataStore((state) => state.scrollmap);
3318
+ const { scrollmap } = useHeatmapData();
2820
3319
  // const hoveredZone = useHeatmapVizScrollmapStore((state) => state.hoveredZone);
2821
3320
  // const setHoveredZone = useHeatmapVizScrollmapStore((state) => state.setHoveredZone);
2822
3321
  const { zones, isReady, maxUsers } = useScrollmapZones({
@@ -2834,8 +3333,7 @@ const ScrollMapOverlay = ({ wrapperRef, iframeRef }) => {
2834
3333
  const overlayRef = useRef(null);
2835
3334
  const [position, setPosition] = useState();
2836
3335
  const [currentScrollPercent, setCurrentScrollPercent] = useState(0);
2837
- const widthScale = useHeatmapVizStore((state) => state.scale);
2838
- const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
3336
+ const { widthScale, iframeHeight } = useHeatmapViz();
2839
3337
  const handleMouseMove = (event) => {
2840
3338
  if (!iframeRef.current || !wrapperRef.current)
2841
3339
  return;
@@ -2870,8 +3368,8 @@ const ScrollMapOverlay = ({ wrapperRef, iframeRef }) => {
2870
3368
 
2871
3369
  const SCROLL_TYPES = [IHeatmapType.Scroll];
2872
3370
  const VizScrollMap = ({ iframeRef, wrapperRef }) => {
2873
- const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
2874
3371
  const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
3372
+ const { iframeHeight } = useHeatmapViz();
2875
3373
  const isHeatmapScroll = SCROLL_TYPES.includes(heatmapType);
2876
3374
  if (!iframeHeight || !isHeatmapScroll)
2877
3375
  return null;
@@ -2887,7 +3385,7 @@ const VizScrollMap = ({ iframeRef, wrapperRef }) => {
2887
3385
 
2888
3386
  const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHeight, onScroll, }) => {
2889
3387
  const contentWidth = useHeatmapConfigStore((state) => state.width);
2890
- const widthScale = useHeatmapVizStore((state) => state.scale);
3388
+ const { widthScale } = useHeatmapViz();
2891
3389
  const contentHeight = scaledHeight > 0
2892
3390
  ? `${scaledHeight + HEATMAP_CONFIG['heightToolbar'] + HEATMAP_CONFIG['padding'] * 2}px`
2893
3391
  : 'auto';
@@ -2920,9 +3418,8 @@ const WrapperVisual = ({ children, visualRef, wrapperRef, scaledHeight, iframeHe
2920
3418
  const VizDomRenderer = ({ mode = 'heatmap' }) => {
2921
3419
  const width = useHeatmapConfigStore((state) => state.width);
2922
3420
  const heatmapType = useHeatmapConfigStore((state) => state.heatmapType);
2923
- const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
2924
- const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
2925
3421
  const setSelectedElement = useHeatmapInteractionStore((state) => state.setSelectedElement);
3422
+ const { iframeHeight, setIframeHeight, isRenderViz } = useHeatmapViz();
2926
3423
  const wrapperRef = useRef(null);
2927
3424
  const visualRef = useRef(null);
2928
3425
  const { iframeRef } = useHeatmapVizRender(mode);
@@ -2931,6 +3428,7 @@ const VizDomRenderer = ({ mode = 'heatmap' }) => {
2931
3428
  iframeRef,
2932
3429
  visualRef,
2933
3430
  iframeHeight,
3431
+ isRenderViz,
2934
3432
  });
2935
3433
  const contentWidth = width ?? 0;
2936
3434
  const onScroll = (e) => {
@@ -2954,12 +3452,13 @@ const VizLoading = () => {
2954
3452
 
2955
3453
  const VizDomHeatmap = () => {
2956
3454
  const controls = useHeatmapControlStore((state) => state.controls);
2957
- const isRendering = useHeatmapDataStore((state) => state.isRendering);
2958
- const iframeHeight = useHeatmapSingleStore((state) => state.iframeHeight);
2959
- const setIframeHeight = useHeatmapSingleStore((state) => state.setIframeHeight);
2960
- const setVizRef = useHeatmapSingleStore((state) => state.setVizRef);
3455
+ const { isRendering } = useHeatmapData();
3456
+ console.log(`🚀 🐥 ~ VizDomHeatmap ~ isRendering:`, isRendering);
3457
+ const { iframeHeight, setIframeHeight, setVizRef } = useHeatmapViz();
3458
+ const viewId = useViewId();
2961
3459
  useEffect(() => {
2962
3460
  return () => {
3461
+ console.log(`🚀 🐥 ~ useEffect ~ return:`, viewId, iframeHeight);
2963
3462
  setVizRef(null);
2964
3463
  setIframeHeight(0);
2965
3464
  };
@@ -2971,8 +3470,7 @@ const VizDomHeatmap = () => {
2971
3470
 
2972
3471
  const VizLiveRenderer = () => {
2973
3472
  const contentWidth = useHeatmapConfigStore((state) => state.width);
2974
- const iframeHeight = useHeatmapLiveStore((state) => state.iframeHeight);
2975
- const setIframeHeight = useHeatmapLiveStore((state) => state.setIframeHeight);
3473
+ const { isRenderViz, iframeHeight, setIframeHeight } = useHeatmapViz();
2976
3474
  const visualRef = useRef(null);
2977
3475
  const wrapperRef = useRef(null);
2978
3476
  const { iframeRef } = useVizLiveRender();
@@ -2981,6 +3479,7 @@ const VizLiveRenderer = () => {
2981
3479
  iframeRef,
2982
3480
  visualRef,
2983
3481
  iframeHeight,
3482
+ isRenderViz,
2984
3483
  setIframeHeight,
2985
3484
  });
2986
3485
  const onScroll = (e) => {
@@ -2994,19 +3493,17 @@ const VizLiveRenderer = () => {
2994
3493
 
2995
3494
  const VizLiveHeatmap = () => {
2996
3495
  const controls = useHeatmapControlStore((state) => state.controls);
2997
- const isRendering = useHeatmapDataStore((state) => state.isRendering);
2998
- const iframeHeight = useHeatmapLiveStore((state) => state.iframeHeight);
2999
- const wrapperHeight = useHeatmapLiveStore((state) => state.wrapperHeight);
3000
- const setWrapperHeight = useHeatmapLiveStore((state) => state.setWrapperHeight);
3496
+ const isRendering = useHeatmapConfigStore((state) => state.isRendering);
3497
+ const { iframeHeight, wrapperHeight } = useHeatmapViz();
3001
3498
  const reset = useHeatmapLiveStore((state) => state.reset);
3002
3499
  useEffect(() => {
3003
3500
  return () => {
3004
3501
  reset();
3005
3502
  };
3006
- }, [reset]);
3503
+ }, []);
3007
3504
  if (isRendering)
3008
3505
  return controls.VizLoading ?? null;
3009
- return (jsxs(VizContainer, { setWrapperHeight: setWrapperHeight, children: [jsx(VizLiveRenderer, {}), (!iframeHeight || !wrapperHeight) && jsx(VizLoading, {})] }));
3506
+ return (jsxs(VizContainer, { isActive: true, children: [jsx(VizLiveRenderer, {}), (!iframeHeight || !wrapperHeight) && jsx(VizLoading, {})] }));
3010
3507
  };
3011
3508
 
3012
3509
  const ContentVizByMode = () => {
@@ -3014,6 +3511,8 @@ const ContentVizByMode = () => {
3014
3511
  switch (mode) {
3015
3512
  case 'live':
3016
3513
  return jsx(VizLiveHeatmap, {});
3514
+ // case 'compare':
3515
+ // return <VizCompareHeatmap />;
3017
3516
  default:
3018
3517
  return jsx(VizDomHeatmap, {});
3019
3518
  }
@@ -3023,6 +3522,45 @@ const LeftSidebar = () => {
3023
3522
  const controls = useHeatmapControlStore((state) => state.controls);
3024
3523
  const isHideSidebar = useHeatmapInteractionStore((state) => state.state.hideSidebar);
3025
3524
  const sidebarWidth = useHeatmapConfigStore((state) => state.sidebarWidth);
3525
+ const mode = useHeatmapConfigStore((state) => state.mode);
3526
+ const [isPopoverOpen, setIsPopoverOpen] = useState(false);
3527
+ // In compare mode, render as popover
3528
+ if (mode === 'compare') {
3529
+ return (jsxs("div", { style: { position: 'relative', zIndex: 10 }, children: [jsx("button", { onClick: () => setIsPopoverOpen(!isPopoverOpen), style: {
3530
+ position: 'absolute',
3531
+ top: '8px',
3532
+ left: '8px',
3533
+ padding: '8px 16px',
3534
+ backgroundColor: '#fff',
3535
+ border: '1px solid #c9cccf',
3536
+ borderRadius: '8px',
3537
+ cursor: 'pointer',
3538
+ fontSize: '14px',
3539
+ fontWeight: 500,
3540
+ zIndex: 11,
3541
+ boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)',
3542
+ }, children: "Click data" }), isPopoverOpen && (jsxs(Fragment, { children: [jsx("div", { onClick: () => setIsPopoverOpen(false), style: {
3543
+ position: 'fixed',
3544
+ top: 0,
3545
+ left: 0,
3546
+ right: 0,
3547
+ bottom: 0,
3548
+ backgroundColor: 'rgba(0, 0, 0, 0.3)',
3549
+ zIndex: 12,
3550
+ } }), jsx("div", { className: "gx-hm-sidebar-popover", style: {
3551
+ position: 'fixed',
3552
+ top: 0,
3553
+ left: 0,
3554
+ height: '100vh',
3555
+ width: `calc(${sidebarWidth}px + ${HEATMAP_CONFIG.borderWidth}px)`,
3556
+ backgroundColor: '#fff',
3557
+ borderRight: `${HEATMAP_CONFIG.borderWidth}px solid ${HEATMAP_CONFIG.borderColor}`,
3558
+ zIndex: 13,
3559
+ boxShadow: '4px 0 12px rgba(0, 0, 0, 0.15)',
3560
+ overflow: 'auto',
3561
+ }, children: controls.Sidebar ?? null })] }))] }));
3562
+ }
3563
+ // Normal sidebar rendering for single mode
3026
3564
  if (isHideSidebar) {
3027
3565
  return null;
3028
3566
  }
@@ -3070,4 +3608,4 @@ const HeatmapLayout = ({ data, clickmap, scrollmap, controls, dataInfo, }) => {
3070
3608
  }
3071
3609
  };
3072
3610
 
3073
- export { GraphView, HeatmapLayout, IClickType, IHeatmapType, IScrollType, useHeatmapConfigStore, useHeatmapDataStore, useHeatmapInteractionStore, useHeatmapLiveStore, useHeatmapVizStore };
3611
+ export { GraphView, HeatmapLayout, IClickType, IHeatmapType, IScrollType, ViewIdContext, convertViewportToIframeCoords, getScrollGradientColor, useClickedElement, useCompareAwareConfig, useCompareAwareConfigSetters, useCompareAwareData, useCompareAwareDataSetters, useCompareAwareViz, useCompareAwareVizSetters, useElementCalloutVisible, useHeatmapCompareStore, useHeatmapConfigStore, useHeatmapData, useHeatmapDataStore, useHeatmapEffects, useHeatmapElementPosition, useHeatmapInteractionStore, useHeatmapLiveStore, useHeatmapScale, useHeatmapSingleStore, useHeatmapViz, useHeatmapVizRender, useHeatmapVizStore, useHoveredElement, useIsCompareMode, useRegisterConfig, useRegisterControl, useRegisterData, useRegisterHeatmap, useScrollmapZones, useViewId, useVizLiveRender, useWrapperRefHeight, useZonePositions };