@gemx-dev/heatmap-react 3.5.92-dev.3 → 3.5.92-dev.5

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 (106) hide show
  1. package/dist/esm/hooks/view-context/useHeatmapVizContext.d.ts +2 -2
  2. package/dist/esm/hooks/view-context/useHeatmapVizContext.d.ts.map +1 -1
  3. package/dist/esm/hooks/viz-live/useVizLiveRender.d.ts.map +1 -1
  4. package/dist/esm/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  5. package/dist/esm/index.js +793 -538
  6. package/dist/esm/index.mjs +793 -538
  7. package/dist/esm/libs/iframe-processor/index.d.ts +2 -5
  8. package/dist/esm/libs/iframe-processor/index.d.ts.map +1 -1
  9. package/dist/esm/libs/iframe-processor/lifecycle.d.ts +15 -7
  10. package/dist/esm/libs/iframe-processor/lifecycle.d.ts.map +1 -1
  11. package/dist/esm/libs/iframe-processor/orchestrator.d.ts +13 -45
  12. package/dist/esm/libs/iframe-processor/orchestrator.d.ts.map +1 -1
  13. package/dist/esm/libs/iframe-processor/processors/height-observer/index.d.ts +3 -14
  14. package/dist/esm/libs/iframe-processor/processors/height-observer/index.d.ts.map +1 -1
  15. package/dist/esm/libs/iframe-processor/processors/height-observer/types.d.ts +9 -1
  16. package/dist/esm/libs/iframe-processor/processors/height-observer/types.d.ts.map +1 -1
  17. package/dist/esm/libs/iframe-processor/processors/navigation/index.d.ts +3 -14
  18. package/dist/esm/libs/iframe-processor/processors/navigation/index.d.ts.map +1 -1
  19. package/dist/esm/libs/iframe-processor/processors/navigation/listeners.d.ts +3 -4
  20. package/dist/esm/libs/iframe-processor/processors/navigation/listeners.d.ts.map +1 -1
  21. package/dist/esm/libs/iframe-processor/processors/navigation/types.d.ts +13 -0
  22. package/dist/esm/libs/iframe-processor/processors/navigation/types.d.ts.map +1 -1
  23. package/dist/esm/libs/iframe-processor/processors/viewport/global-fixes/global-fixes/viewport-unit-replacer/fixes.d.ts.map +1 -1
  24. package/dist/esm/libs/iframe-processor/processors/viewport/global-fixes/gp-v7-fixes/gem-slider-item/fixes.d.ts.map +1 -1
  25. package/dist/esm/libs/iframe-processor/processors/viewport/global-fixes/types.d.ts +2 -2
  26. package/dist/esm/libs/iframe-processor/processors/viewport/index.d.ts +3 -9
  27. package/dist/esm/libs/iframe-processor/processors/viewport/index.d.ts.map +1 -1
  28. package/dist/esm/libs/iframe-processor/processors/viewport/listeners.d.ts +3 -2
  29. package/dist/esm/libs/iframe-processor/processors/viewport/listeners.d.ts.map +1 -1
  30. package/dist/esm/libs/iframe-processor/processors/viewport/shop-overrides/types.d.ts +2 -0
  31. package/dist/esm/libs/iframe-processor/processors/viewport/shop-overrides/types.d.ts.map +1 -1
  32. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer/constants.d.ts +5 -0
  33. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer/constants.d.ts.map +1 -0
  34. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer/functions.d.ts +11 -0
  35. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer/functions.d.ts.map +1 -0
  36. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer/index.d.ts +9 -0
  37. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer/index.d.ts.map +1 -0
  38. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer/state.d.ts +13 -0
  39. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer/state.d.ts.map +1 -0
  40. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer/types.d.ts +16 -0
  41. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer/types.d.ts.map +1 -0
  42. package/dist/esm/libs/iframe-processor/processors/viewport/types.d.ts +8 -0
  43. package/dist/esm/libs/iframe-processor/processors/viewport/types.d.ts.map +1 -0
  44. package/dist/esm/libs/iframe-processor/shared/factory-types.d.ts +24 -0
  45. package/dist/esm/libs/iframe-processor/shared/factory-types.d.ts.map +1 -0
  46. package/dist/esm/libs/iframe-processor/shared/iframe-types.d.ts +20 -0
  47. package/dist/esm/libs/iframe-processor/shared/iframe-types.d.ts.map +1 -0
  48. package/dist/esm/stores/viz.d.ts +2 -2
  49. package/dist/esm/stores/viz.d.ts.map +1 -1
  50. package/dist/esm/types/iframe-helper.d.ts +0 -19
  51. package/dist/esm/types/iframe-helper.d.ts.map +1 -1
  52. package/dist/umd/hooks/view-context/useHeatmapVizContext.d.ts +2 -2
  53. package/dist/umd/hooks/view-context/useHeatmapVizContext.d.ts.map +1 -1
  54. package/dist/umd/hooks/viz-live/useVizLiveRender.d.ts.map +1 -1
  55. package/dist/umd/hooks/viz-render/useHeatmapRender.d.ts.map +1 -1
  56. package/dist/umd/index.js +2 -2
  57. package/dist/umd/libs/iframe-processor/index.d.ts +2 -5
  58. package/dist/umd/libs/iframe-processor/index.d.ts.map +1 -1
  59. package/dist/umd/libs/iframe-processor/lifecycle.d.ts +15 -7
  60. package/dist/umd/libs/iframe-processor/lifecycle.d.ts.map +1 -1
  61. package/dist/umd/libs/iframe-processor/orchestrator.d.ts +13 -45
  62. package/dist/umd/libs/iframe-processor/orchestrator.d.ts.map +1 -1
  63. package/dist/umd/libs/iframe-processor/processors/height-observer/index.d.ts +3 -14
  64. package/dist/umd/libs/iframe-processor/processors/height-observer/index.d.ts.map +1 -1
  65. package/dist/umd/libs/iframe-processor/processors/height-observer/types.d.ts +9 -1
  66. package/dist/umd/libs/iframe-processor/processors/height-observer/types.d.ts.map +1 -1
  67. package/dist/umd/libs/iframe-processor/processors/navigation/index.d.ts +3 -14
  68. package/dist/umd/libs/iframe-processor/processors/navigation/index.d.ts.map +1 -1
  69. package/dist/umd/libs/iframe-processor/processors/navigation/listeners.d.ts +3 -4
  70. package/dist/umd/libs/iframe-processor/processors/navigation/listeners.d.ts.map +1 -1
  71. package/dist/umd/libs/iframe-processor/processors/navigation/types.d.ts +13 -0
  72. package/dist/umd/libs/iframe-processor/processors/navigation/types.d.ts.map +1 -1
  73. package/dist/umd/libs/iframe-processor/processors/viewport/global-fixes/global-fixes/viewport-unit-replacer/fixes.d.ts.map +1 -1
  74. package/dist/umd/libs/iframe-processor/processors/viewport/global-fixes/gp-v7-fixes/gem-slider-item/fixes.d.ts.map +1 -1
  75. package/dist/umd/libs/iframe-processor/processors/viewport/global-fixes/types.d.ts +2 -2
  76. package/dist/umd/libs/iframe-processor/processors/viewport/index.d.ts +3 -9
  77. package/dist/umd/libs/iframe-processor/processors/viewport/index.d.ts.map +1 -1
  78. package/dist/umd/libs/iframe-processor/processors/viewport/listeners.d.ts +3 -2
  79. package/dist/umd/libs/iframe-processor/processors/viewport/listeners.d.ts.map +1 -1
  80. package/dist/umd/libs/iframe-processor/processors/viewport/shop-overrides/types.d.ts +2 -0
  81. package/dist/umd/libs/iframe-processor/processors/viewport/shop-overrides/types.d.ts.map +1 -1
  82. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer/constants.d.ts +5 -0
  83. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer/constants.d.ts.map +1 -0
  84. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer/functions.d.ts +11 -0
  85. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer/functions.d.ts.map +1 -0
  86. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer/index.d.ts +9 -0
  87. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer/index.d.ts.map +1 -0
  88. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer/state.d.ts +13 -0
  89. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer/state.d.ts.map +1 -0
  90. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer/types.d.ts +16 -0
  91. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer/types.d.ts.map +1 -0
  92. package/dist/umd/libs/iframe-processor/processors/viewport/types.d.ts +8 -0
  93. package/dist/umd/libs/iframe-processor/processors/viewport/types.d.ts.map +1 -0
  94. package/dist/umd/libs/iframe-processor/shared/factory-types.d.ts +24 -0
  95. package/dist/umd/libs/iframe-processor/shared/factory-types.d.ts.map +1 -0
  96. package/dist/umd/libs/iframe-processor/shared/iframe-types.d.ts +20 -0
  97. package/dist/umd/libs/iframe-processor/shared/iframe-types.d.ts.map +1 -0
  98. package/dist/umd/stores/viz.d.ts +2 -2
  99. package/dist/umd/stores/viz.d.ts.map +1 -1
  100. package/dist/umd/types/iframe-helper.d.ts +0 -19
  101. package/dist/umd/types/iframe-helper.d.ts.map +1 -1
  102. package/package.json +1 -1
  103. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer.d.ts +0 -54
  104. package/dist/esm/libs/iframe-processor/processors/viewport/style-enforcer.d.ts.map +0 -1
  105. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer.d.ts +0 -54
  106. package/dist/umd/libs/iframe-processor/processors/viewport/style-enforcer.d.ts.map +0 -1
@@ -574,16 +574,16 @@ const useHeatmapSettingStore = create()(subscribeWithSelector((set) => {
574
574
 
575
575
  const useHeatmapVizStore = create()(subscribeWithSelector((set) => {
576
576
  return {
577
- isRenderViz: new Map([[DEFAULT_VIEW_ID, false]]),
577
+ isRenderedViz: new Map([[DEFAULT_VIEW_ID, false]]),
578
578
  zoomRatio: new Map([[DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO.DEFAULT]]),
579
579
  minZoomRatio: new Map([[DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO.MIN]]),
580
580
  maxZoomRatio: new Map([[DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO.MAX]]),
581
581
  scale: new Map([[DEFAULT_VIEW_ID, 1]]),
582
582
  isScaledToFit: new Map([[DEFAULT_VIEW_ID, false]]),
583
- setIsRenderViz: (isRenderViz, viewId = DEFAULT_VIEW_ID) => set((prev) => {
584
- const newIsRenderViz = new Map(prev.isRenderViz);
585
- newIsRenderViz.set(viewId, isRenderViz);
586
- return { isRenderViz: newIsRenderViz };
583
+ setIsRenderedViz: (isRenderedViz, viewId = DEFAULT_VIEW_ID) => set((prev) => {
584
+ const newIsRenderedViz = new Map(prev.isRenderedViz);
585
+ newIsRenderedViz.set(viewId, isRenderedViz);
586
+ return { isRenderedViz: newIsRenderedViz };
587
587
  }),
588
588
  setZoomRatio: (zoomRatio, viewId = DEFAULT_VIEW_ID) => set((prev) => {
589
589
  const newZoomRatio = new Map(prev.zoomRatio);
@@ -611,18 +611,18 @@ const useHeatmapVizStore = create()(subscribeWithSelector((set) => {
611
611
  return { isScaledToFit: newIsScaledToFit };
612
612
  }),
613
613
  copyView: (fromViewId, toViewId) => set((prev) => {
614
- const newIsRenderViz = new Map(prev.isRenderViz);
614
+ const newIsRenderedViz = new Map(prev.isRenderedViz);
615
615
  const newZoomRatio = new Map(prev.zoomRatio);
616
616
  const newMinZoomRatio = new Map(prev.minZoomRatio);
617
617
  const newScale = new Map(prev.scale);
618
618
  const newIsScaledToFit = new Map(prev.isScaledToFit);
619
- newIsRenderViz.set(toViewId, prev.isRenderViz.get(fromViewId) ?? false);
619
+ newIsRenderedViz.set(toViewId, prev.isRenderedViz.get(fromViewId) ?? false);
620
620
  newZoomRatio.set(toViewId, prev.zoomRatio.get(fromViewId) ?? 100);
621
621
  newMinZoomRatio.set(toViewId, prev.minZoomRatio.get(fromViewId) ?? 10);
622
622
  newScale.set(toViewId, prev.scale.get(fromViewId) ?? 1);
623
623
  newIsScaledToFit.set(toViewId, prev.isScaledToFit.get(fromViewId) ?? false);
624
624
  return {
625
- isRenderViz: newIsRenderViz,
625
+ isRenderedViz: newIsRenderedViz,
626
626
  zoomRatio: newZoomRatio,
627
627
  minZoomRatio: newMinZoomRatio,
628
628
  scale: newScale,
@@ -630,18 +630,18 @@ const useHeatmapVizStore = create()(subscribeWithSelector((set) => {
630
630
  };
631
631
  }),
632
632
  clearView: (viewId) => set((prev) => {
633
- const newIsRenderViz = new Map(prev.isRenderViz);
633
+ const newIsRenderedViz = new Map(prev.isRenderedViz);
634
634
  const newZoomRatio = new Map(prev.zoomRatio);
635
635
  const newMinZoomRatio = new Map(prev.minZoomRatio);
636
636
  const newScale = new Map(prev.scale);
637
637
  const newIsScaledToFit = new Map(prev.isScaledToFit);
638
- newIsRenderViz.delete(viewId);
638
+ newIsRenderedViz.delete(viewId);
639
639
  newZoomRatio.delete(viewId);
640
640
  newMinZoomRatio.delete(viewId);
641
641
  newScale.delete(viewId);
642
642
  newIsScaledToFit.delete(viewId);
643
643
  return {
644
- isRenderViz: newIsRenderViz,
644
+ isRenderedViz: newIsRenderedViz,
645
645
  zoomRatio: newZoomRatio,
646
646
  minZoomRatio: newMinZoomRatio,
647
647
  scale: newScale,
@@ -649,7 +649,7 @@ const useHeatmapVizStore = create()(subscribeWithSelector((set) => {
649
649
  };
650
650
  }),
651
651
  resetAll: () => set({
652
- isRenderViz: new Map([[DEFAULT_VIEW_ID, false]]),
652
+ isRenderedViz: new Map([[DEFAULT_VIEW_ID, false]]),
653
653
  zoomRatio: new Map([[DEFAULT_VIEW_ID, 100]]),
654
654
  minZoomRatio: new Map([[DEFAULT_VIEW_ID, 10]]),
655
655
  scale: new Map([[DEFAULT_VIEW_ID, 1]]),
@@ -1269,7 +1269,7 @@ const useHeatmapSettingContext = createViewContextHook({
1269
1269
  const useHeatmapVizContext = createViewContextHook({
1270
1270
  useStore: useHeatmapVizStore,
1271
1271
  getState: (store, viewId) => ({
1272
- isRenderViz: store.isRenderViz.get(viewId) ?? false,
1272
+ isRenderedViz: store.isRenderedViz.get(viewId) ?? false,
1273
1273
  zoomRatio: store.zoomRatio.get(viewId) ?? DEFAULT_ZOOM_RATIO.DEFAULT,
1274
1274
  minZoomRatio: store.minZoomRatio.get(viewId) ?? DEFAULT_ZOOM_RATIO.MIN,
1275
1275
  maxZoomRatio: store.maxZoomRatio.get(viewId) ?? DEFAULT_ZOOM_RATIO.MAX,
@@ -1277,7 +1277,7 @@ const useHeatmapVizContext = createViewContextHook({
1277
1277
  isScaledToFit: store.isScaledToFit.get(viewId) ?? false,
1278
1278
  }),
1279
1279
  getActions: (store, viewId) => ({
1280
- setIsRenderViz: (value) => store.setIsRenderViz(value, viewId),
1280
+ setIsRenderedViz: (value) => store.setIsRenderedViz(value, viewId),
1281
1281
  setZoomRatio: (value) => store.setZoomRatio(value, viewId),
1282
1282
  setMinZoomRatio: (value) => store.setMinZoomRatio(value, viewId),
1283
1283
  setMaxZoomRatio: (value) => store.setMaxZoomRatio(value, viewId),
@@ -1770,7 +1770,7 @@ class Logger {
1770
1770
  }
1771
1771
  }
1772
1772
  // Export singleton instance
1773
- const logger$9 = new Logger();
1773
+ const logger$4 = new Logger();
1774
1774
  // Export factory function để tạo logger với config riêng
1775
1775
  function createLogger(config = {}) {
1776
1776
  const instance = new Logger();
@@ -2159,7 +2159,7 @@ function findElementByHash(props) {
2159
2159
  }
2160
2160
  }
2161
2161
  catch (error) {
2162
- logger$9.warn(`Invalid selector "${selector}":`, error);
2162
+ logger$4.warn(`Invalid selector "${selector}":`, error);
2163
2163
  }
2164
2164
  const elementByHash = iframeDocument.querySelector(`[data-clarity-hashalpha="${hash}"], [data-clarity-hash="${hash}"], [data-clarity-hashbeta="${hash}"]`);
2165
2165
  return elementByHash;
@@ -2181,7 +2181,7 @@ function hydrateAreaNode(props) {
2181
2181
  const { id, hash, selector } = persistedData;
2182
2182
  const element = findElementByHash({ hash, selector, iframeDocument, vizRef });
2183
2183
  if (!element) {
2184
- logger$9.warn(`Cannot hydrate area ${id}: element not found for hash ${hash} or selector ${selector}`);
2184
+ logger$4.warn(`Cannot hydrate area ${id}: element not found for hash ${hash} or selector ${selector}`);
2185
2185
  return null;
2186
2186
  }
2187
2187
  const areaNode = buildAreaNode(element, hash, heatmapInfo, shadowRoot, persistedData);
@@ -2198,7 +2198,7 @@ function hydrateAreas(props) {
2198
2198
  hydratedAreas.push(area);
2199
2199
  }
2200
2200
  }
2201
- logger$9.info(`Hydrated ${hydratedAreas.length} of ${clickAreas.length} persisted areas`);
2201
+ logger$4.info(`Hydrated ${hydratedAreas.length} of ${clickAreas.length} persisted areas`);
2202
2202
  return hydratedAreas;
2203
2203
  }
2204
2204
  /**
@@ -2902,16 +2902,16 @@ const calcCalloutPositionAbsolute = (props) => {
2902
2902
 
2903
2903
  function validateAreaCreation(dataInfo, hash, areas) {
2904
2904
  if (!dataInfo?.clickMapMetrics || !dataInfo?.totalClicks) {
2905
- logger$9.warn('Cannot create area: missing heatmap data');
2905
+ logger$4.warn('Cannot create area: missing heatmap data');
2906
2906
  return false;
2907
2907
  }
2908
2908
  if (!hash) {
2909
- logger$9.warn('Cannot create area: missing hash');
2909
+ logger$4.warn('Cannot create area: missing hash');
2910
2910
  return false;
2911
2911
  }
2912
2912
  const alreadyExists = areas.some((area) => area.hash === hash);
2913
2913
  if (alreadyExists) {
2914
- logger$9.warn(`Area already exists for element: ${hash}`);
2914
+ logger$4.warn(`Area already exists for element: ${hash}`);
2915
2915
  return false;
2916
2916
  }
2917
2917
  return true;
@@ -2924,14 +2924,14 @@ function identifyConflictingAreas(area) {
2924
2924
  // Case 1: New area is a child of an existing area
2925
2925
  if (area.parentNode) {
2926
2926
  conflicts.parentId = area.parentNode.id;
2927
- logger$9.info(`New area "${area.selector}" is a child of existing area "${area.parentNode.selector}". Will remove parent.`);
2927
+ logger$4.info(`New area "${area.selector}" is a child of existing area "${area.parentNode.selector}". Will remove parent.`);
2928
2928
  }
2929
2929
  // Case 2: New area is a parent of existing area(s)
2930
2930
  if (area.childNodes.size > 0) {
2931
2931
  area.childNodes.forEach((childArea) => {
2932
2932
  conflicts.childrenIds.push(childArea.id);
2933
2933
  });
2934
- logger$9.info(`New area "${area.selector}" is a parent of ${area.childNodes.size} existing area(s). Will remove children.`);
2934
+ logger$4.info(`New area "${area.selector}" is a parent of ${area.childNodes.size} existing area(s). Will remove children.`);
2935
2935
  }
2936
2936
  return conflicts;
2937
2937
  }
@@ -2982,7 +2982,7 @@ function useAreaCreation(options = {}) {
2982
2982
  }
2983
2983
  }
2984
2984
  catch (error) {
2985
- logger$9.error('Failed to create area:', error);
2985
+ logger$4.error('Failed to create area:', error);
2986
2986
  }
2987
2987
  }, [dataInfo, areas, addArea, removeArea, removeClickArea, customShadowRoot, onAreaCreated]);
2988
2988
  return {
@@ -3097,16 +3097,16 @@ function useAreaHydration(options) {
3097
3097
  return;
3098
3098
  if (!dataInfo)
3099
3099
  return;
3100
- logger$9.info(`Hydrating ${clickAreas.length} persisted areas...`);
3100
+ logger$4.info(`Hydrating ${clickAreas.length} persisted areas...`);
3101
3101
  const hydratedAreas = hydrateAreas({ clickAreas, heatmapInfo: dataInfo, vizRef, shadowRoot });
3102
3102
  if (!hydratedAreas?.length) {
3103
- logger$9.warn('No areas could be hydrated - all elements may have been removed from DOM');
3103
+ logger$4.warn('No areas could be hydrated - all elements may have been removed from DOM');
3104
3104
  return;
3105
3105
  }
3106
3106
  setIsInitializing(true);
3107
3107
  buildAreaGraph(hydratedAreas);
3108
3108
  setAreas(hydratedAreas);
3109
- logger$9.info(`Successfully hydrated ${hydratedAreas.length} areas`);
3109
+ logger$4.info(`Successfully hydrated ${hydratedAreas.length} areas`);
3110
3110
  }, [dataInfo, vizRef, isInitializing, clickAreas]);
3111
3111
  useEffect(() => {
3112
3112
  if (!enabled)
@@ -3240,7 +3240,7 @@ function useAreaRectSync(options) {
3240
3240
  area.rect.update(newRect);
3241
3241
  }
3242
3242
  catch (error) {
3243
- logger$9.error(`Failed to update rect for area ${area.id}:`, error);
3243
+ logger$4.error(`Failed to update rect for area ${area.id}:`, error);
3244
3244
  }
3245
3245
  });
3246
3246
  buildAreaGraph(areas);
@@ -3345,9 +3345,9 @@ const useAreaClickmap = () => {
3345
3345
  const useClickmap = () => {
3346
3346
  const vizRef = useHeatmapVizRectContext((s) => s.vizRef);
3347
3347
  const clickmap = useHeatmapDataContext((s) => s.clickmap);
3348
- const isRenderViz = useHeatmapVizContext((s) => s.isRenderViz);
3348
+ const isRenderedViz = useHeatmapVizContext((s) => s.isRenderedViz);
3349
3349
  const start = useCallback(() => {
3350
- if (!vizRef || !clickmap || clickmap.length === 0 || !isRenderViz)
3350
+ if (!vizRef || !clickmap || clickmap.length === 0 || !isRenderedViz)
3351
3351
  return;
3352
3352
  try {
3353
3353
  vizRef?.clearmap?.();
@@ -3356,7 +3356,7 @@ const useClickmap = () => {
3356
3356
  catch (error) {
3357
3357
  console.error(`🚀 🐥 ~ useClickmap ~ error:`, error);
3358
3358
  }
3359
- }, [vizRef, clickmap, isRenderViz]);
3359
+ }, [vizRef, clickmap, isRenderedViz]);
3360
3360
  return { start };
3361
3361
  };
3362
3362
 
@@ -3384,7 +3384,7 @@ const useScrollmap = () => {
3384
3384
  vizRef?.scrollmap?.(scrollmap);
3385
3385
  }
3386
3386
  catch (error) {
3387
- logger$9.error(`🚀 🐥 ~ useScrollmap ~ error:`, error);
3387
+ logger$4.error(`🚀 🐥 ~ useScrollmap ~ error:`, error);
3388
3388
  }
3389
3389
  }, [vizRef, scrollmap]);
3390
3390
  return { start };
@@ -3908,17 +3908,241 @@ function useVizLiveIframeMsg(options = {}) {
3908
3908
  * DOM observation setup — ResizeObserver + MutationObserver.
3909
3909
  * Returns a cleanup function that disconnects both observers.
3910
3910
  */
3911
- createLogger({ enabled: false, prefix: 'IframeHeightObserver' });
3911
+ const logger$3 = createLogger({ enabled: false, prefix: 'IframeHeightObserver' });
3912
+ function setup(doc, onChange) {
3913
+ const resizeObserver = new ResizeObserver(onChange);
3914
+ resizeObserver.observe(doc.documentElement);
3915
+ resizeObserver.observe(doc.body);
3916
+ const mutationObserver = new MutationObserver(onChange);
3917
+ mutationObserver.observe(doc.body, {
3918
+ childList: true,
3919
+ subtree: true,
3920
+ attributes: true,
3921
+ attributeFilter: ['style', 'class', 'hidden', 'data-v'],
3922
+ });
3923
+ logger$3.log('DOM observers started (ResizeObserver + MutationObserver)');
3924
+ return () => {
3925
+ resizeObserver.disconnect();
3926
+ mutationObserver.disconnect();
3927
+ logger$3.log('DOM observers disconnected');
3928
+ };
3929
+ }
3912
3930
 
3913
3931
  /**
3914
3932
  * Height Observer Processor
3915
3933
  * Background observer — watches for iframe content height changes.
3916
3934
  */
3917
- createLogger({ enabled: true, prefix: 'IframeHeightObserver' });
3935
+ // ── Module-level functions ────────────────────────────────────────────────────
3936
+ function clearTimers(s) {
3937
+ if (s.throttleTimeout) {
3938
+ clearTimeout(s.throttleTimeout);
3939
+ s.throttleTimeout = null;
3940
+ }
3941
+ if (s.debounceTimeout) {
3942
+ clearTimeout(s.debounceTimeout);
3943
+ s.debounceTimeout = null;
3944
+ }
3945
+ }
3946
+ function getActualHeight(s) {
3947
+ if (!s.iframe?.contentDocument)
3948
+ return 0;
3949
+ const { documentElement: docEl, body } = s.iframe.contentDocument;
3950
+ const heights = [docEl.scrollHeight, docEl.offsetHeight, body.scrollHeight, body.offsetHeight];
3951
+ const maxHeight = Math.max(...heights.filter((h) => h > 0));
3952
+ s.logger.log('Height sources:', {
3953
+ 'documentElement.scrollHeight': docEl.scrollHeight,
3954
+ 'documentElement.offsetHeight': docEl.offsetHeight,
3955
+ 'body.scrollHeight': body.scrollHeight,
3956
+ 'body.offsetHeight': body.offsetHeight,
3957
+ maxHeight,
3958
+ });
3959
+ return maxHeight;
3960
+ }
3961
+ async function processHeightChange(s, newHeight) {
3962
+ if (!s.iframe || !s.config)
3963
+ return;
3964
+ s.isProcessing = true;
3965
+ s.logger.log(`Processing height change: ${newHeight}px`);
3966
+ try {
3967
+ const result = {
3968
+ height: newHeight,
3969
+ width: s.iframe.contentWindow?.innerWidth ?? 0,
3970
+ };
3971
+ s.lastHeight = newHeight;
3972
+ s.logger.log('Height change processed:', result);
3973
+ s.config.onHeightChange?.(result);
3974
+ window.dispatchEvent(new CustomEvent('iframe-dimensions-applied', { detail: result }));
3975
+ }
3976
+ catch (error) {
3977
+ s.logger.error('Failed to process height change:', error);
3978
+ s.config.onError?.(error);
3979
+ }
3980
+ finally {
3981
+ s.isProcessing = false;
3982
+ }
3983
+ }
3984
+ function handleHeightChange(s) {
3985
+ if (s.isProcessing || s.throttleTimeout)
3986
+ return;
3987
+ s.throttleTimeout = setTimeout(() => {
3988
+ s.throttleTimeout = null;
3989
+ const currentHeight = getActualHeight(s);
3990
+ if (currentHeight === s.lastHeight)
3991
+ return;
3992
+ s.logger.log(`Height changed: ${s.lastHeight}px -> ${currentHeight}px`);
3993
+ if (s.debounceTimeout)
3994
+ clearTimeout(s.debounceTimeout);
3995
+ s.debounceTimeout = setTimeout(() => {
3996
+ s.debounceTimeout = null;
3997
+ processHeightChange(s, currentHeight);
3998
+ }, s.debounceMs);
3999
+ }, s.throttleMs);
4000
+ }
4001
+ function observe(s) {
4002
+ if (!s.iframe?.contentDocument?.body) {
4003
+ s.logger.warn('Cannot observe height changes: iframe body not found');
4004
+ return;
4005
+ }
4006
+ s.observerCleanup?.();
4007
+ s.lastHeight = s.iframe.contentDocument.documentElement.scrollHeight;
4008
+ s.logger.log('Initial height:', s.lastHeight);
4009
+ s.observerCleanup = setup(s.iframe.contentDocument, () => handleHeightChange(s));
4010
+ }
4011
+ function start$5(s, cfg) {
4012
+ if (s.running) {
4013
+ s.logger.warn('Observer is already running. Call stop() first.');
4014
+ return;
4015
+ }
4016
+ s.iframe = cfg.iframe;
4017
+ s.config = cfg;
4018
+ s.throttleMs = cfg.throttleMs ?? 25;
4019
+ s.debounceMs = cfg.debounceMs ?? 500;
4020
+ s.running = true;
4021
+ observe(s);
4022
+ s.logger.log('Height observer started');
4023
+ }
4024
+ function stop$5(s) {
4025
+ if (!s.running)
4026
+ return;
4027
+ s.observerCleanup?.();
4028
+ s.observerCleanup = null;
4029
+ clearTimers(s);
4030
+ s.iframe = null;
4031
+ s.config = null;
4032
+ s.lastHeight = 0;
4033
+ s.isProcessing = false;
4034
+ s.running = false;
4035
+ s.logger.log('Height observer stopped');
4036
+ }
4037
+ function clear(s) {
4038
+ s.observerCleanup?.();
4039
+ s.observerCleanup = null;
4040
+ clearTimers(s);
4041
+ s.lastHeight = 0;
4042
+ s.isProcessing = false;
4043
+ }
4044
+ function updateConfig$3(s, cfg) {
4045
+ if (!s.running || !s.config) {
4046
+ s.logger.warn('Observer is not running.');
4047
+ return;
4048
+ }
4049
+ s.config = { ...s.config, ...cfg };
4050
+ if (cfg.throttleMs !== undefined)
4051
+ s.throttleMs = cfg.throttleMs;
4052
+ if (cfg.debounceMs !== undefined)
4053
+ s.debounceMs = cfg.debounceMs;
4054
+ s.logger.configure({ enabled: !!s.config.debug });
4055
+ s.logger.log('Config updated');
4056
+ }
4057
+ // ── Factory ───────────────────────────────────────────────────────────────────
4058
+ function createHeightObserver() {
4059
+ const s = {
4060
+ logger: createLogger({ enabled: true, prefix: 'IframeHeightObserver' }),
4061
+ iframe: null,
4062
+ config: null,
4063
+ observerCleanup: null,
4064
+ lastHeight: 0,
4065
+ throttleTimeout: null,
4066
+ debounceTimeout: null,
4067
+ isProcessing: false,
4068
+ throttleMs: 25,
4069
+ debounceMs: 500,
4070
+ running: false,
4071
+ };
4072
+ return {
4073
+ start: (cfg) => start$5(s, cfg),
4074
+ stop: () => stop$5(s),
4075
+ observe: () => observe(s),
4076
+ clear: () => clear(s),
4077
+ updateConfig: (cfg) => updateConfig$3(s, cfg),
4078
+ getCurrentHeight: () => s.lastHeight,
4079
+ isRunning: () => s.running,
4080
+ getStateInfo: () => ({
4081
+ isRunning: s.running,
4082
+ lastHeight: s.lastHeight,
4083
+ isProcessing: s.isProcessing,
4084
+ hasObservers: !!s.observerCleanup,
4085
+ }),
4086
+ };
4087
+ }
4088
+
4089
+ /**
4090
+ * Window-level event management for the navigation processor.
4091
+ *
4092
+ * Responsibilities:
4093
+ * - Subscribe to events dispatched by this processor (for logging/hooks)
4094
+ * - Dispatch navigation events to the parent window
4095
+ */
4096
+ // ── Module-level functions ────────────────────────────────────────────────────
4097
+ function attach$1(s, debug) {
4098
+ s.logger.configure({ enabled: !!debug });
4099
+ s.navigationBlockedListener = (e) => {
4100
+ const ev = e;
4101
+ s.logger.log('Navigation blocked:', ev.detail.url);
4102
+ };
4103
+ s.formSubmitWindowListener = (e) => {
4104
+ const ev = e;
4105
+ s.logger.log('Form submitted:', ev.detail.data);
4106
+ };
4107
+ window.addEventListener('iframe-navigation-blocked', s.navigationBlockedListener);
4108
+ window.addEventListener('iframe-form-submit', s.formSubmitWindowListener);
4109
+ }
4110
+ function detach$1(s) {
4111
+ if (s.navigationBlockedListener) {
4112
+ window.removeEventListener('iframe-navigation-blocked', s.navigationBlockedListener);
4113
+ s.navigationBlockedListener = null;
4114
+ }
4115
+ if (s.formSubmitWindowListener) {
4116
+ window.removeEventListener('iframe-form-submit', s.formSubmitWindowListener);
4117
+ s.formSubmitWindowListener = null;
4118
+ }
4119
+ }
4120
+ function dispatchBlocked(url, showMessage) {
4121
+ if (showMessage)
4122
+ alert(`Navigation blocked: ${url}`);
4123
+ window.dispatchEvent(new CustomEvent('iframe-navigation-blocked', { detail: { url } }));
4124
+ }
4125
+ function dispatchFormSubmit(form, data) {
4126
+ window.dispatchEvent(new CustomEvent('iframe-form-submit', { detail: { form, data } }));
4127
+ }
4128
+ // ── Factory ───────────────────────────────────────────────────────────────────
4129
+ function createNavigationListeners() {
4130
+ const s = {
4131
+ logger: createLogger({ enabled: false, prefix: 'IframeNavigationBlocker' }),
4132
+ navigationBlockedListener: null,
4133
+ formSubmitWindowListener: null,
4134
+ };
4135
+ return {
4136
+ attach: (debug) => attach$1(s, debug),
4137
+ detach: () => detach$1(s),
4138
+ dispatchBlocked,
4139
+ dispatchFormSubmit,
4140
+ };
4141
+ }
3918
4142
 
3919
- const logger$8 = createLogger({ enabled: false, prefix: 'IframeNavigationBlocker' });
4143
+ const logger$2 = createLogger({ enabled: false, prefix: 'IframeNavigationBlocker' });
3920
4144
  function configure$1(debug) {
3921
- logger$8.configure({ enabled: debug });
4145
+ logger$2.configure({ enabled: debug });
3922
4146
  }
3923
4147
  // ─── DOM Utilities ────────────────────────────────────────────────────────────
3924
4148
  function disableAllLinks(doc) {
@@ -3942,10 +4166,10 @@ function setupLinkBlocker(doc, isEnabled, onBlocked) {
3942
4166
  return;
3943
4167
  const href = link.getAttribute('href');
3944
4168
  if (!href || href === '' || href === '#' || href.startsWith('#')) {
3945
- logger$8.log('Allowed hash navigation:', href);
4169
+ logger$2.log('Allowed hash navigation:', href);
3946
4170
  return;
3947
4171
  }
3948
- logger$8.log('Blocked link navigation to:', href);
4172
+ logger$2.log('Blocked link navigation to:', href);
3949
4173
  e.preventDefault();
3950
4174
  e.stopPropagation();
3951
4175
  e.stopImmediatePropagation();
@@ -3959,7 +4183,7 @@ function setupLinkBlocker(doc, isEnabled, onBlocked) {
3959
4183
  return;
3960
4184
  const href = link.getAttribute('href');
3961
4185
  if (href && !href.startsWith('#')) {
3962
- logger$8.log('Blocked auxclick navigation');
4186
+ logger$2.log('Blocked auxclick navigation');
3963
4187
  e.preventDefault();
3964
4188
  e.stopPropagation();
3965
4189
  e.stopImmediatePropagation();
@@ -3980,7 +4204,7 @@ function setupFormBlocker(doc, isEnabled, onBlocked, onFormSubmit) {
3980
4204
  const form = e.target;
3981
4205
  const action = form.getAttribute('action');
3982
4206
  if (!action || action === '' || action === '#') {
3983
- logger$8.log('Allowed same-page form');
4207
+ logger$2.log('Allowed same-page form');
3984
4208
  e.preventDefault();
3985
4209
  const data = {};
3986
4210
  new FormData(form).forEach((value, key) => {
@@ -3989,7 +4213,7 @@ function setupFormBlocker(doc, isEnabled, onBlocked, onFormSubmit) {
3989
4213
  onFormSubmit(form, data);
3990
4214
  return;
3991
4215
  }
3992
- logger$8.log('Blocked form submission to:', action);
4216
+ logger$2.log('Blocked form submission to:', action);
3993
4217
  e.preventDefault();
3994
4218
  e.stopPropagation();
3995
4219
  e.stopImmediatePropagation();
@@ -4003,7 +4227,7 @@ function setupWindowOpenBlocker(win, originalOpen, isEnabled, onBlocked) {
4003
4227
  if (!isEnabled())
4004
4228
  return originalOpen(...args);
4005
4229
  const url = args[0]?.toString() || 'popup';
4006
- logger$8.log('Blocked window.open:', url);
4230
+ logger$2.log('Blocked window.open:', url);
4007
4231
  onBlocked(url);
4008
4232
  return null;
4009
4233
  });
@@ -4015,14 +4239,14 @@ function setupUnloadBlocker(win, isEnabled) {
4015
4239
  const beforeUnloadListener = (e) => {
4016
4240
  if (!isEnabled())
4017
4241
  return;
4018
- logger$8.log('Blocked beforeunload');
4242
+ logger$2.log('Blocked beforeunload');
4019
4243
  e.preventDefault();
4020
4244
  e.returnValue = '';
4021
4245
  };
4022
4246
  const unloadListener = (e) => {
4023
4247
  if (!isEnabled())
4024
4248
  return;
4025
- logger$8.log('Blocked unload');
4249
+ logger$2.log('Blocked unload');
4026
4250
  e.preventDefault();
4027
4251
  e.stopPropagation();
4028
4252
  };
@@ -4039,65 +4263,14 @@ function setupDOMMonitor(doc) {
4039
4263
  return () => observer.disconnect();
4040
4264
  }
4041
4265
 
4042
- /**
4043
- * Window-level event management for the navigation processor.
4044
- *
4045
- * Responsibilities:
4046
- * - Subscribe to events dispatched by this processor (for logging/hooks)
4047
- * - Dispatch navigation events to the parent window
4048
- */
4049
- const logger$7 = createLogger({ enabled: false, prefix: 'IframeNavigationBlocker' });
4050
- // ─── State ────────────────────────────────────────────────────────────────────
4051
- let navigationBlockedListener = null;
4052
- let formSubmitWindowListener = null;
4053
- // ─── Subscriptions ────────────────────────────────────────────────────────────
4054
- function attach$1(debug) {
4055
- logger$7.configure({ enabled: !!debug });
4056
- navigationBlockedListener = (e) => {
4057
- const ev = e;
4058
- logger$7.log('Navigation blocked:', ev.detail.url);
4059
- };
4060
- formSubmitWindowListener = (e) => {
4061
- const ev = e;
4062
- logger$7.log('Form submitted:', ev.detail.data);
4063
- };
4064
- window.addEventListener('iframe-navigation-blocked', navigationBlockedListener);
4065
- window.addEventListener('iframe-form-submit', formSubmitWindowListener);
4066
- }
4067
- function detach$1() {
4068
- if (navigationBlockedListener) {
4069
- window.removeEventListener('iframe-navigation-blocked', navigationBlockedListener);
4070
- navigationBlockedListener = null;
4071
- }
4072
- if (formSubmitWindowListener) {
4073
- window.removeEventListener('iframe-form-submit', formSubmitWindowListener);
4074
- formSubmitWindowListener = null;
4075
- }
4076
- }
4077
- // ─── Dispatchers ─────────────────────────────────────────────────────────────
4078
- function dispatchBlocked(url, showMessage) {
4079
- if (showMessage)
4080
- alert(`Navigation blocked: ${url}`);
4081
- window.dispatchEvent(new CustomEvent('iframe-navigation-blocked', { detail: { url } }));
4082
- }
4083
- function dispatchFormSubmit(form, data) {
4084
- window.dispatchEvent(new CustomEvent('iframe-form-submit', { detail: { form, data } }));
4085
- }
4086
-
4087
4266
  /**
4088
4267
  * Navigation Processor
4089
4268
  * Continuous guard — blocks all navigation attempts within the iframe.
4090
4269
  */
4091
- const logger$6 = createLogger({ enabled: false, prefix: 'IframeNavigationBlocker' });
4092
- // ─── State ────────────────────────────────────────────────────────────────────
4093
- let isEnabled = false;
4094
- let showMessage = false;
4095
- let running$4 = false;
4096
- let cleanups = [];
4097
- // ─── Public API ───────────────────────────────────────────────────────────────
4098
- function start$5(iframe, cfg) {
4099
- if (running$4) {
4100
- logger$6.warn('Blocker is already running. Call stop() first.');
4270
+ // ── Module-level functions ────────────────────────────────────────────────────
4271
+ function start$4(s, iframe, cfg) {
4272
+ if (s.running) {
4273
+ s.logger.warn('Blocker is already running. Call stop() first.');
4101
4274
  return;
4102
4275
  }
4103
4276
  if (!iframe.contentDocument || !iframe.contentWindow) {
@@ -4106,76 +4279,114 @@ function start$5(iframe, cfg) {
4106
4279
  const doc = iframe.contentDocument;
4107
4280
  const win = iframe.contentWindow;
4108
4281
  const originalOpen = win.open.bind(win);
4109
- logger$6.configure({ enabled: !!cfg?.debug });
4282
+ s.logger.configure({ enabled: !!cfg?.debug });
4110
4283
  configure$1(!!cfg?.debug);
4111
- cleanups = [
4112
- setupLinkBlocker(doc, () => isEnabled, (url) => dispatchBlocked(url, showMessage)),
4113
- setupFormBlocker(doc, () => isEnabled, (url) => dispatchBlocked(url, showMessage), dispatchFormSubmit),
4114
- setupWindowOpenBlocker(win, originalOpen, () => isEnabled, (url) => dispatchBlocked(url, showMessage)),
4115
- setupUnloadBlocker(win, () => isEnabled),
4284
+ s.cleanups = [
4285
+ setupLinkBlocker(doc, () => s.isEnabled, (url) => s.listeners.dispatchBlocked(url, s.showMessage)),
4286
+ setupFormBlocker(doc, () => s.isEnabled, (url) => s.listeners.dispatchBlocked(url, s.showMessage), s.listeners.dispatchFormSubmit),
4287
+ setupWindowOpenBlocker(win, originalOpen, () => s.isEnabled, (url) => s.listeners.dispatchBlocked(url, s.showMessage)),
4288
+ setupUnloadBlocker(win, () => s.isEnabled),
4116
4289
  setupDOMMonitor(doc),
4117
4290
  ];
4118
- attach$1(cfg?.debug);
4119
- running$4 = true;
4120
- logger$6.log('Navigation blocker started');
4291
+ s.listeners.attach(cfg?.debug);
4292
+ s.running = true;
4293
+ s.logger.log('Navigation blocker started');
4294
+ }
4295
+ function stop$4(s) {
4296
+ if (!s.running)
4297
+ return;
4298
+ s.cleanups.forEach((fn) => fn());
4299
+ s.cleanups = [];
4300
+ s.listeners.detach();
4301
+ s.isEnabled = false;
4302
+ s.showMessage = false;
4303
+ s.running = false;
4304
+ s.logger.log('Navigation blocker stopped');
4305
+ }
4306
+ function enable(s) {
4307
+ if (!s.running) {
4308
+ s.logger.warn('Blocker is not running.');
4309
+ return;
4310
+ }
4311
+ s.isEnabled = true;
4312
+ s.logger.log('Navigation blocking enabled');
4121
4313
  }
4122
- function stop$5() {
4123
- if (!running$4)
4314
+ function disable(s) {
4315
+ if (!s.running) {
4316
+ s.logger.warn('Blocker is not running.');
4124
4317
  return;
4125
- cleanups.forEach((fn) => fn());
4126
- cleanups = [];
4127
- detach$1();
4128
- isEnabled = false;
4129
- showMessage = false;
4130
- running$4 = false;
4131
- logger$6.log('Navigation blocker stopped');
4132
- }
4133
- function enable() {
4134
- if (!running$4) {
4135
- logger$6.warn('Blocker is not running. Call start() first.');
4318
+ }
4319
+ s.isEnabled = false;
4320
+ s.logger.log('Navigation blocking disabled');
4321
+ }
4322
+ function enableMessage(s) {
4323
+ if (!s.running) {
4324
+ s.logger.warn('Blocker is not running.');
4325
+ return;
4326
+ }
4327
+ s.showMessage = true;
4328
+ s.logger.log('Navigation blocking message enabled');
4329
+ }
4330
+ function disableMessage(s) {
4331
+ if (!s.running) {
4332
+ s.logger.warn('Blocker is not running.');
4136
4333
  return;
4137
4334
  }
4138
- isEnabled = true;
4139
- logger$6.log('Navigation blocking enabled');
4335
+ s.showMessage = false;
4336
+ s.logger.log('Navigation blocking message disabled');
4337
+ }
4338
+ // ── Factory ───────────────────────────────────────────────────────────────────
4339
+ function createNavigationBlocker() {
4340
+ const s = {
4341
+ logger: createLogger({ enabled: false, prefix: 'IframeNavigationBlocker' }),
4342
+ listeners: createNavigationListeners(),
4343
+ isEnabled: false,
4344
+ showMessage: false,
4345
+ running: false,
4346
+ cleanups: [],
4347
+ };
4348
+ return {
4349
+ start: (iframe, cfg) => start$4(s, iframe, cfg),
4350
+ stop: () => stop$4(s),
4351
+ enable: () => enable(s),
4352
+ disable: () => disable(s),
4353
+ enableMessage: () => enableMessage(s),
4354
+ disableMessage: () => disableMessage(s),
4355
+ isRunning: () => s.running,
4356
+ isBlockingEnabled: () => s.isEnabled,
4357
+ getStateInfo: () => ({ isRunning: s.running, isEnabled: s.isEnabled, showMessage: s.showMessage }),
4358
+ };
4140
4359
  }
4141
4360
 
4142
- const registry$1 = [];
4143
- /**
4144
- * Register a global fix.
4145
- * Fixes are run in registration order.
4146
- */
4147
- function register$1(fix) {
4148
- registry$1.push(fix);
4361
+ // ── Module-level functions ────────────────────────────────────────────────────
4362
+ function attach(s, debug) {
4363
+ s.logger.configure({ enabled: !!debug });
4364
+ s.dimensionsListener = (e) => {
4365
+ const ev = e;
4366
+ s.logger.log('Dimensions applied:', ev.detail);
4367
+ };
4368
+ window.addEventListener('iframe-dimensions-applied', s.dimensionsListener);
4149
4369
  }
4150
- /**
4151
- * Returns all fixes that are active for the given context.
4152
- * A fix is active if it has no `shouldApply`, or `shouldApply` returns true.
4153
- */
4154
- function getActiveFixes(ctx) {
4155
- return registry$1.filter((fix) => {
4156
- try {
4157
- return !fix.shouldApply || fix.shouldApply(ctx);
4158
- }
4159
- catch {
4160
- return false;
4161
- }
4162
- });
4370
+ function detach(s) {
4371
+ if (s.dimensionsListener) {
4372
+ window.removeEventListener('iframe-dimensions-applied', s.dimensionsListener);
4373
+ s.dimensionsListener = null;
4374
+ }
4375
+ }
4376
+ // ── Factory ───────────────────────────────────────────────────────────────────
4377
+ function createViewportListeners() {
4378
+ const s = {
4379
+ logger: createLogger({ enabled: false, prefix: 'ViewportReplacer' }),
4380
+ dimensionsListener: null,
4381
+ };
4382
+ return {
4383
+ attach: (debug) => attach(s, debug),
4384
+ detach: () => detach(s),
4385
+ };
4163
4386
  }
4164
4387
 
4165
- /**
4166
- * Computed Style Enforcer Module
4167
- * Enforces computed CSS styles with viewport unit verification
4168
- * @module computed-style-enforcer
4169
- */
4170
- const logger$5 = createLogger({
4171
- enabled: false,
4172
- prefix: 'ComputedStyleEnforcer',
4173
- });
4174
- // ============================================================================
4175
- // Constants
4176
- // ============================================================================
4177
4388
  const DEFAULT_TOLERANCE_PX = 5;
4178
- const VIEWPORT_UNIT_REGEX = /([-.\d]+)(vh|svh|lvh|dvh|%)/gi;
4389
+ const VIEWPORT_UNIT_REGEX = /([-.\\d]+)(vh|svh|lvh|dvh|%)/gi;
4179
4390
  const DEFAULT_CSS_VALUES = ['none', 'auto', 'normal', '0px'];
4180
4391
  const CRITICAL_PROPERTIES = [
4181
4392
  'display',
@@ -4212,220 +4423,221 @@ const CRITICAL_PROPERTIES = [
4212
4423
  'grid-template-rows',
4213
4424
  'gap',
4214
4425
  ];
4215
- // ============================================================================
4216
- // State
4217
- // ============================================================================
4218
- let doc$1 = null;
4219
- let win$1 = null;
4220
- let config$2 = null;
4221
- const elementsWithViewportUnits$1 = new Set();
4222
- let originalValues$1 = new WeakMap();
4223
- let running$3 = false;
4224
- // ============================================================================
4225
- // Helper Functions
4226
- // ============================================================================
4227
- /**
4228
- * Get viewport unit map for conversion from current state
4229
- */
4230
- function getViewportUnitMap() {
4231
- if (!config$2) {
4426
+
4427
+ // ── Helpers ───────────────────────────────────────────────────────────────────
4428
+ function getViewportUnitMap(s) {
4429
+ if (!s.config)
4232
4430
  throw new Error('Config is not initialized');
4233
- }
4234
4431
  return {
4235
- vh: config$2.targetHeight,
4236
- svh: config$2.targetHeight,
4237
- lvh: config$2.targetHeight,
4238
- dvh: config$2.targetHeight,
4239
- vw: config$2.targetWidth,
4240
- svw: config$2.targetWidth,
4241
- lvw: config$2.targetWidth,
4242
- dvw: config$2.targetWidth,
4432
+ vh: s.config.targetHeight,
4433
+ svh: s.config.targetHeight,
4434
+ lvh: s.config.targetHeight,
4435
+ dvh: s.config.targetHeight,
4436
+ vw: s.config.targetWidth,
4437
+ svw: s.config.targetWidth,
4438
+ lvw: s.config.targetWidth,
4439
+ dvw: s.config.targetWidth,
4243
4440
  };
4244
4441
  }
4245
- /**
4246
- * Calculate expected pixel value from viewport unit using current state
4247
- */
4248
- function calculateExpectedPx(value, unit) {
4249
- if (!config$2) {
4442
+ function calculateExpectedPx(s, value, unit) {
4443
+ if (!s.config)
4250
4444
  throw new Error('Config is not initialized');
4251
- }
4252
4445
  const unitLower = unit.toLowerCase();
4253
- if (unitLower === '%') {
4254
- return (value / 100) * config$2.targetHeight;
4255
- }
4256
- const unitMap = getViewportUnitMap();
4257
- return (value / 100) * (unitMap[unitLower] || 0);
4446
+ if (unitLower === '%')
4447
+ return (value / 100) * s.config.targetHeight;
4448
+ return (value / 100) * (getViewportUnitMap(s)[unitLower] || 0);
4258
4449
  }
4259
- /**
4260
- * Check if a CSS value is a default/initial value that should be skipped
4261
- */
4262
4450
  function isDefaultCssValue(value) {
4263
4451
  return DEFAULT_CSS_VALUES.includes(value);
4264
4452
  }
4265
- /**
4266
- * Verify if we should replace the computed value using current state
4267
- * Return true ONLY if computed value matches target config (within tolerance)
4268
- * Return false if computed value is different - don't override correct values
4269
- */
4270
- function shouldReplaceValue(computedValue, originalValue, tolerance = DEFAULT_TOLERANCE_PX) {
4271
- if (!config$2) {
4453
+ function shouldReplaceValue(s, computedValue, originalValue, tolerance = DEFAULT_TOLERANCE_PX) {
4454
+ if (!s.config)
4272
4455
  return false;
4273
- }
4274
- // Parse computed value (should be in px)
4275
4456
  const computedPx = parseFloat(computedValue);
4276
- if (isNaN(computedPx)) {
4277
- return false; // Cannot verify, don't replace
4278
- }
4279
- // Parse original value to check what it should be
4457
+ if (isNaN(computedPx))
4458
+ return false;
4280
4459
  const regex = new RegExp(VIEWPORT_UNIT_REGEX.source, VIEWPORT_UNIT_REGEX.flags);
4281
4460
  const match = originalValue.match(regex);
4282
- if (!match) {
4283
- return false; // No viewport units found, don't replace
4284
- }
4461
+ if (!match)
4462
+ return false;
4285
4463
  const [, value, unit] = match;
4286
4464
  const num = parseFloat(value);
4287
- if (isNaN(num)) {
4465
+ if (isNaN(num))
4288
4466
  return false;
4289
- }
4290
- // Calculate expected value based on unit and target config
4291
- const expectedPx = calculateExpectedPx(num, unit);
4292
- // Check if computed value matches expected value (within tolerance)
4467
+ const expectedPx = calculateExpectedPx(s, num, unit);
4293
4468
  const diff = Math.abs(computedPx - expectedPx);
4294
4469
  if (diff <= tolerance) {
4295
- // Matches target config, OK to replace
4296
- logger$5.log(`OK to replace: computed=${computedValue} matches expected=${expectedPx.toFixed(2)}px (diff=${diff.toFixed(2)}px)`);
4470
+ s.logger.log(`OK to replace: computed=${computedValue} matches expected=${expectedPx.toFixed(2)}px (diff=${diff.toFixed(2)}px)`);
4297
4471
  return true;
4298
4472
  }
4299
- // Different from target config, DON'T replace - value already has correct computation
4300
- logger$5.log(`Skip replace: computed=${computedValue} differs from expected=${expectedPx.toFixed(2)}px (diff=${diff.toFixed(2)}px) - keeping current value`);
4473
+ s.logger.log(`Skip replace: computed=${computedValue} differs from expected=${expectedPx.toFixed(2)}px (diff=${diff.toFixed(2)}px)`);
4301
4474
  return false;
4302
4475
  }
4303
- /**
4304
- * Apply a single property to an element with verification using current state
4305
- */
4306
- function applyPropertyWithVerification(element, prop, computedValue, originalValue, tolerance = DEFAULT_TOLERANCE_PX) {
4307
- // Verify before replacing - only replace if computed value matches target config
4308
- if (originalValue && shouldReplaceValue(computedValue, originalValue, tolerance)) {
4476
+ function applyPropertyWithVerification(s, element, prop, computedValue, originalValue, tolerance = DEFAULT_TOLERANCE_PX) {
4477
+ if (originalValue && shouldReplaceValue(s, computedValue, originalValue, tolerance)) {
4309
4478
  element.style.setProperty(prop, computedValue, 'important');
4310
4479
  return true;
4311
4480
  }
4312
4481
  else if (!originalValue) {
4313
- // No original value tracked, use old behavior
4314
4482
  element.style.setProperty(prop, computedValue, 'important');
4315
4483
  return true;
4316
4484
  }
4317
4485
  return false;
4318
4486
  }
4319
- // ============================================================================
4320
- // Public API Functions
4321
- // ============================================================================
4322
- /**
4323
- * Start the computed style enforcer
4324
- * Initialize with iframe document and config
4325
- */
4326
- function start$4(d, w, cfg, options = {}) {
4327
- if (running$3) {
4328
- logger$5.warn('Enforcer is already running. Call stop() first.');
4487
+ // ── Exported module-level functions ───────────────────────────────────────────
4488
+ function start$3(s, d, w, cfg, options = {}) {
4489
+ if (s.running) {
4490
+ s.logger.warn('Enforcer is already running. Call stop() first.');
4329
4491
  return;
4330
4492
  }
4331
- doc$1 = d;
4332
- win$1 = w;
4333
- config$2 = cfg;
4334
- running$3 = true;
4335
- logger$5.configure({ enabled: !!options.debug });
4336
- logger$5.log('Computed style enforcer started');
4493
+ s.doc = d;
4494
+ s.win = w;
4495
+ s.config = cfg;
4496
+ s.running = true;
4497
+ s.logger.configure({ enabled: !!options.debug });
4498
+ s.logger.log('Computed style enforcer started');
4337
4499
  }
4338
- /**
4339
- * Stop the enforcer and clear state
4340
- */
4341
- function stop$4() {
4342
- if (!running$3) {
4500
+ function stop$3(s) {
4501
+ if (!s.running)
4502
+ return;
4503
+ s.doc = null;
4504
+ s.win = null;
4505
+ s.config = null;
4506
+ s.elementsWithViewportUnits.clear();
4507
+ s.originalValues = new WeakMap();
4508
+ s.running = false;
4509
+ s.logger.log('Computed style enforcer stopped');
4510
+ }
4511
+ function reset(s) {
4512
+ if (!s.running) {
4513
+ s.logger.warn('Enforcer is not running. Call start() first.');
4343
4514
  return;
4344
4515
  }
4345
- doc$1 = null;
4346
- win$1 = null;
4347
- config$2 = null;
4348
- elementsWithViewportUnits$1.clear();
4349
- originalValues$1 = new WeakMap();
4350
- running$3 = false;
4351
- logger$5.log('Computed style enforcer stopped');
4516
+ s.elementsWithViewportUnits.clear();
4517
+ s.originalValues = new WeakMap();
4518
+ s.logger.log('Computed style enforcer reset');
4352
4519
  }
4353
- /**
4354
- * Track an element with viewport units
4355
- * Store original CSS values for later verification
4356
- */
4357
- function trackElement(element, propertyOriginalValues) {
4358
- if (!running$3) {
4359
- logger$5.warn('Enforcer is not running. Call start() first.');
4520
+ function trackElement(s, element, propertyOriginalValues) {
4521
+ if (!s.running) {
4522
+ s.logger.warn('Enforcer is not running. Call start() first.');
4360
4523
  return;
4361
4524
  }
4362
- elementsWithViewportUnits$1.add(element);
4363
- // Store original values for this element
4364
- let elementOriginals = originalValues$1.get(element);
4525
+ s.elementsWithViewportUnits.add(element);
4526
+ let elementOriginals = s.originalValues.get(element);
4365
4527
  if (!elementOriginals) {
4366
4528
  elementOriginals = new Map();
4367
- originalValues$1.set(element, elementOriginals);
4529
+ s.originalValues.set(element, elementOriginals);
4368
4530
  }
4369
- // Merge property original values (don't override existing)
4370
4531
  propertyOriginalValues.forEach((value, prop) => {
4371
- if (!elementOriginals.has(prop)) {
4532
+ if (!elementOriginals.has(prop))
4372
4533
  elementOriginals.set(prop, value);
4373
- }
4374
4534
  });
4375
4535
  }
4376
- /**
4377
- * Process a single element - enforce computed styles to inline
4378
- */
4379
- function processElement(element, options = {}) {
4380
- if (!running$3 || !doc$1 || !win$1 || !config$2) {
4381
- logger$5.warn('Enforcer is not running. Call start() first.');
4536
+ function processElement(s, element, options = {}) {
4537
+ if (!s.running || !s.doc || !s.win || !s.config) {
4538
+ s.logger.warn('Enforcer is not running.');
4382
4539
  return 0;
4383
4540
  }
4384
- if (!elementsWithViewportUnits$1.has(element)) {
4541
+ if (!s.elementsWithViewportUnits.has(element))
4385
4542
  return 0;
4386
- }
4387
4543
  const htmlElement = element;
4388
- const computed = win$1.getComputedStyle(htmlElement);
4544
+ const computed = s.win.getComputedStyle(htmlElement);
4389
4545
  const inlineStyle = htmlElement.style;
4390
- const elementOriginals = originalValues$1.get(element);
4546
+ const elementOriginals = s.originalValues.get(element);
4391
4547
  const tolerance = options.tolerance ?? DEFAULT_TOLERANCE_PX;
4392
4548
  let count = 0;
4393
4549
  CRITICAL_PROPERTIES.forEach((prop) => {
4394
4550
  const computedValue = computed.getPropertyValue(prop);
4395
4551
  const inlineValue = inlineStyle.getPropertyValue(prop);
4396
- if (computedValue && (!inlineValue || inlineValue !== computedValue)) {
4397
- if (!isDefaultCssValue(computedValue)) {
4398
- const originalValue = elementOriginals?.get(prop) || '';
4399
- if (applyPropertyWithVerification(htmlElement, prop, computedValue, originalValue, tolerance)) {
4400
- count++;
4401
- }
4402
- }
4552
+ if (computedValue && (!inlineValue || inlineValue !== computedValue) && !isDefaultCssValue(computedValue)) {
4553
+ const originalValue = elementOriginals?.get(prop) || '';
4554
+ if (applyPropertyWithVerification(s, htmlElement, prop, computedValue, originalValue, tolerance))
4555
+ count++;
4403
4556
  }
4404
4557
  });
4405
4558
  return count;
4406
4559
  }
4407
- /**
4408
- * Process all tracked elements
4409
- * Enforce computed styles to inline for all elements with viewport units
4410
- */
4411
- function processAll(options = {}) {
4412
- if (!running$3 || !doc$1 || !win$1 || !config$2) {
4413
- logger$5.warn('Enforcer is not running. Call start() first.');
4560
+ function processAll(s, options = {}) {
4561
+ if (!s.running || !s.doc || !s.win || !s.config) {
4562
+ s.logger.warn('Enforcer is not running.');
4414
4563
  return 0;
4415
4564
  }
4416
4565
  let totalCount = 0;
4417
- elementsWithViewportUnits$1.forEach((element) => {
4418
- totalCount += processElement(element, options);
4566
+ s.elementsWithViewportUnits.forEach((element) => {
4567
+ totalCount += processElement(s, element, options);
4419
4568
  });
4420
- logger$5.log(`Enforced ${totalCount} computed styles for ${elementsWithViewportUnits$1.size} elements`);
4569
+ s.logger.log(`Enforced ${totalCount} computed styles for ${s.elementsWithViewportUnits.size} elements`);
4421
4570
  return totalCount;
4422
4571
  }
4572
+ function updateConfig$2(s, cfg) {
4573
+ if (!s.running || !s.config) {
4574
+ s.logger.warn('Enforcer is not running.');
4575
+ return;
4576
+ }
4577
+ s.config = { ...s.config, ...cfg };
4578
+ s.logger.log('Config updated:', cfg);
4579
+ }
4580
+
4581
+ /**
4582
+ * Computed Style Enforcer
4583
+ * Enforces computed CSS styles with viewport unit verification.
4584
+ */
4585
+ // ── Factory ───────────────────────────────────────────────────────────────────
4586
+ function createEnforcer() {
4587
+ const s = {
4588
+ logger: createLogger({ enabled: false, prefix: 'ComputedStyleEnforcer' }),
4589
+ doc: null,
4590
+ win: null,
4591
+ config: null,
4592
+ elementsWithViewportUnits: new Set(),
4593
+ originalValues: new WeakMap(),
4594
+ running: false,
4595
+ };
4596
+ return {
4597
+ start: (d, w, cfg, options) => start$3(s, d, w, cfg, options),
4598
+ stop: () => stop$3(s),
4599
+ reset: () => reset(s),
4600
+ trackElement: (element, propertyOriginalValues) => trackElement(s, element, propertyOriginalValues),
4601
+ processElement: (element, options) => processElement(s, element, options),
4602
+ processAll: (options) => processAll(s, options),
4603
+ updateConfig: (cfg) => updateConfig$2(s, cfg),
4604
+ getStateInfo: () => ({
4605
+ isRunning: s.running,
4606
+ trackedElementsCount: s.elementsWithViewportUnits.size,
4607
+ hasConfig: !!s.config,
4608
+ }),
4609
+ isRunning: () => s.running,
4610
+ };
4611
+ }
4612
+
4613
+ const registry$1 = [];
4614
+ /**
4615
+ * Register a global fix.
4616
+ * Fixes are run in registration order.
4617
+ */
4618
+ function register$1(fix) {
4619
+ registry$1.push(fix);
4620
+ }
4621
+ /**
4622
+ * Returns all fixes that are active for the given context.
4623
+ * A fix is active if it has no `shouldApply`, or `shouldApply` returns true.
4624
+ */
4625
+ function getActiveFixes(ctx) {
4626
+ return registry$1.filter((fix) => {
4627
+ try {
4628
+ return !fix.shouldApply || fix.shouldApply(ctx);
4629
+ }
4630
+ catch {
4631
+ return false;
4632
+ }
4633
+ });
4634
+ }
4423
4635
 
4424
4636
  /**
4425
4637
  * Core viewport unit replacement logic.
4426
4638
  * Converts vh/vw/svh/dvh/% to pixel values across all CSS in the iframe.
4427
4639
  */
4428
- const logger$4 = createLogger({ enabled: false, prefix: 'ViewportUnitReplacer' });
4640
+ const logger$1 = createLogger({ enabled: false, prefix: 'ViewportUnitReplacer' });
4429
4641
  // ─── Constants ────────────────────────────────────────────────────────────────
4430
4642
  const HEIGHT_RELATED_PROPERTIES = ['height', 'min-height', 'max-height', 'top', 'bottom'];
4431
4643
  // ─── Per-run tracking state (reset on each process() call) ───────────────────
@@ -4496,11 +4708,11 @@ function trackSelector(selector, propOriginals, ctx) {
4496
4708
  if (!originals.has(k))
4497
4709
  originals.set(k, v);
4498
4710
  });
4499
- trackElement(el, propOriginals);
4711
+ ctx.enforcer?.trackElement(el, propOriginals);
4500
4712
  });
4501
4713
  }
4502
4714
  catch {
4503
- logger$4.warn('Invalid selector, skipping:', selector);
4715
+ logger$1.warn('Invalid selector, skipping:', selector);
4504
4716
  }
4505
4717
  }
4506
4718
  // ─── CSS processing ───────────────────────────────────────────────────────────
@@ -4514,7 +4726,7 @@ function processInlineStyles(ctx) {
4514
4726
  count++;
4515
4727
  }
4516
4728
  });
4517
- logger$4.log(`Replaced ${count} inline style elements`);
4729
+ logger$1.log(`Replaced ${count} inline style elements`);
4518
4730
  return count;
4519
4731
  }
4520
4732
  function processStyleTags(ctx) {
@@ -4526,7 +4738,7 @@ function processStyleTags(ctx) {
4526
4738
  count++;
4527
4739
  }
4528
4740
  });
4529
- logger$4.log(`Replaced ${count} <style> tags`);
4741
+ logger$1.log(`Replaced ${count} <style> tags`);
4530
4742
  return count;
4531
4743
  }
4532
4744
  function processRule(rule, ctx) {
@@ -4568,10 +4780,10 @@ function processStylesheets(ctx) {
4568
4780
  }
4569
4781
  }
4570
4782
  catch (e) {
4571
- logger$4.warn('Cannot read stylesheet (CORS?):', e.message);
4783
+ logger$1.warn('Cannot read stylesheet (CORS?):', e.message);
4572
4784
  }
4573
4785
  });
4574
- logger$4.log(`Replaced ${total} rules in inline stylesheets`);
4786
+ logger$1.log(`Replaced ${total} rules in inline stylesheets`);
4575
4787
  return total;
4576
4788
  }
4577
4789
  async function processLinkedStylesheets(ctx) {
@@ -4580,7 +4792,7 @@ async function processLinkedStylesheets(ctx) {
4580
4792
  for (const link of Array.from(links)) {
4581
4793
  // Skip cross-origin — already in browser CSSOM, handled via processStylesheets
4582
4794
  if (link.href && !link.href.startsWith(ctx.win.location.origin)) {
4583
- logger$4.log('Skipping cross-origin CSS:', link.href);
4795
+ logger$1.log('Skipping cross-origin CSS:', link.href);
4584
4796
  continue;
4585
4797
  }
4586
4798
  try {
@@ -4597,15 +4809,15 @@ async function processLinkedStylesheets(ctx) {
4597
4809
  }
4598
4810
  }
4599
4811
  catch (e) {
4600
- logger$4.warn('Cannot load CSS:', link.href, e);
4812
+ logger$1.warn('Cannot load CSS:', link.href, e);
4601
4813
  }
4602
4814
  }
4603
- logger$4.log(`Replaced ${count} linked CSS files`);
4815
+ logger$1.log(`Replaced ${count} linked CSS files`);
4604
4816
  return count;
4605
4817
  }
4606
4818
  // ─── Public entry point ───────────────────────────────────────────────────────
4607
4819
  async function process$1(ctx) {
4608
- logger$4.configure({ enabled: !!ctx.debug });
4820
+ logger$1.configure({ enabled: !!ctx.debug });
4609
4821
  // Reset tracking state from any previous run
4610
4822
  elementsWithViewportUnits = new Set();
4611
4823
  originalValues = new WeakMap();
@@ -4616,8 +4828,8 @@ async function process$1(ctx) {
4616
4828
  // Wait for browser to apply the replaced styles
4617
4829
  await new Promise((resolve) => requestAnimationFrame(resolve));
4618
4830
  // Enforce final computed styles to inline with !important
4619
- const count = processAll({ debug: !!ctx.debug });
4620
- logger$4.log(`Enforced ${count} computed styles for ${elementsWithViewportUnits.size} tracked elements`);
4831
+ const count = ctx.enforcer?.processAll({ debug: !!ctx.debug }) ?? 0;
4832
+ logger$1.log(`Enforced ${count} computed styles for ${elementsWithViewportUnits.size} tracked elements`);
4621
4833
  }
4622
4834
 
4623
4835
  /**
@@ -4713,6 +4925,9 @@ function getMaxWByDeviceType(deviceType) {
4713
4925
  // ─── Main fix ─────────────────────────────────────────────────────────────────
4714
4926
  function afterProcess$1({ doc, targetWidth, deviceType }) {
4715
4927
  doc.querySelectorAll(SLIDER_ITEM_SELECTOR).forEach((item) => {
4928
+ // When !gp-min-w-full is set, the item fills 100% width via Tailwind — skip manual width override
4929
+ if (item.classList.contains('!gp-min-w-full'))
4930
+ return;
4716
4931
  const originalWidth = parseFloat(item.style.minWidth) || parseFloat(item.style.maxWidth) || 0;
4717
4932
  if (!originalWidth)
4718
4933
  return;
@@ -4813,23 +5028,6 @@ register$1({
4813
5028
  afterProcess,
4814
5029
  });
4815
5030
 
4816
- const logger$3 = createLogger({ enabled: false, prefix: 'ViewportReplacer' });
4817
- let dimensionsListener = null;
4818
- function attach(debug) {
4819
- logger$3.configure({ enabled: !!debug });
4820
- dimensionsListener = (e) => {
4821
- const ev = e;
4822
- logger$3.log('Dimensions applied:', ev.detail);
4823
- };
4824
- window.addEventListener('iframe-dimensions-applied', dimensionsListener);
4825
- }
4826
- function detach() {
4827
- if (dimensionsListener) {
4828
- window.removeEventListener('iframe-dimensions-applied', dimensionsListener);
4829
- dimensionsListener = null;
4830
- }
4831
- }
4832
-
4833
5031
  /**
4834
5032
  * Default iframe dimension calculation.
4835
5033
  * Used as fallback when no fix overrides getDimensions().
@@ -4853,37 +5051,37 @@ function getFinalWidth(doc) {
4853
5051
  * Phase 3: afterProcess (shop → global)
4854
5052
  * Phase 4: getDimensions (shop → global → default)
4855
5053
  */
4856
- const logger$2 = createLogger({ enabled: false, prefix: 'ViewportReplacer' });
5054
+ const logger = createLogger({ enabled: false, prefix: 'ViewportReplacer' });
4857
5055
  function configure(debug) {
4858
- logger$2.configure({ enabled: debug });
5056
+ logger.configure({ enabled: debug });
4859
5057
  }
4860
5058
  async function run$1(ctx, activeGlobal, shopFix) {
4861
5059
  // ── Phase 1: beforeProcess ────────────────────────────────────────────────
4862
5060
  for (const fix of activeGlobal) {
4863
5061
  if (fix.beforeProcess) {
4864
- logger$2.log(`[beforeProcess] ${fix.name}`);
5062
+ logger.log(`[beforeProcess] ${fix.name}`);
4865
5063
  await fix.beforeProcess(ctx);
4866
5064
  }
4867
5065
  }
4868
5066
  if (shopFix?.beforeProcess) {
4869
- logger$2.log('[beforeProcess] shop');
5067
+ logger.log('[beforeProcess] shop');
4870
5068
  await shopFix.beforeProcess(ctx);
4871
5069
  }
4872
5070
  // ── Phase 2: process ──────────────────────────────────────────────────────
4873
5071
  for (const fix of activeGlobal) {
4874
5072
  if (fix.process) {
4875
- logger$2.log(`[process] ${fix.name}`);
5073
+ logger.log(`[process] ${fix.name}`);
4876
5074
  await fix.process(ctx);
4877
5075
  }
4878
5076
  }
4879
5077
  // ── Phase 3: afterProcess ─────────────────────────────────────────────────
4880
5078
  if (shopFix?.afterProcess) {
4881
- logger$2.log('[afterProcess] shop');
5079
+ logger.log('[afterProcess] shop');
4882
5080
  await shopFix.afterProcess(ctx);
4883
5081
  }
4884
5082
  for (const fix of activeGlobal) {
4885
5083
  if (fix.afterProcess) {
4886
- logger$2.log(`[afterProcess] ${fix.name}`);
5084
+ logger.log(`[afterProcess] ${fix.name}`);
4887
5085
  await fix.afterProcess(ctx);
4888
5086
  }
4889
5087
  }
@@ -4895,14 +5093,14 @@ async function run$1(ctx, activeGlobal, shopFix) {
4895
5093
  if (shopFix?.getDimensions) {
4896
5094
  dimensions = shopFix.getDimensions(ctx);
4897
5095
  if (dimensions)
4898
- logger$2.log('Dimensions from shop fix:', dimensions);
5096
+ logger.log('Dimensions from shop fix:', dimensions);
4899
5097
  }
4900
5098
  if (!dimensions) {
4901
5099
  for (const fix of activeGlobal) {
4902
5100
  if (fix.getDimensions) {
4903
5101
  dimensions = fix.getDimensions(ctx);
4904
5102
  if (dimensions) {
4905
- logger$2.log(`Dimensions from global fix [${fix.name}]:`, dimensions);
5103
+ logger.log(`Dimensions from global fix [${fix.name}]:`, dimensions);
4906
5104
  break;
4907
5105
  }
4908
5106
  }
@@ -4911,7 +5109,7 @@ async function run$1(ctx, activeGlobal, shopFix) {
4911
5109
  if (!dimensions) {
4912
5110
  dimensions = { height: getFinalHeight(ctx.doc, ctx.win), width: getFinalWidth(ctx.doc) };
4913
5111
  }
4914
- logger$2.log('Final dimensions:', dimensions);
5112
+ logger.log('Final dimensions:', dimensions);
4915
5113
  resolve(dimensions);
4916
5114
  });
4917
5115
  });
@@ -4988,227 +5186,270 @@ register(`566240210141053597`, {
4988
5186
  afterProcess: restoreAndFixLayout,
4989
5187
  });
4990
5188
 
4991
- const logger$1 = createLogger({ enabled: false, prefix: 'ViewportReplacer' });
4992
- // ─── State ────────────────────────────────────────────────────────────────────
4993
- let doc = null;
4994
- let win = null;
4995
- let config$1 = null;
4996
- let shopFix = null;
4997
- let running$2 = false;
4998
- // ─── Public API ───────────────────────────────────────────────────────────────
4999
- function start$3(iframe, cfg) {
5000
- if (running$2) {
5001
- logger$1.warn('Already running. Call stop() first.');
5189
+ // ── Module-level functions ────────────────────────────────────────────────────
5190
+ function start$2(s, iframe, cfg) {
5191
+ if (s.running) {
5192
+ s.logger.warn('Already running. Call stop() first.');
5002
5193
  return;
5003
5194
  }
5004
5195
  if (!iframe.contentDocument || !iframe.contentWindow) {
5005
5196
  throw new Error('Iframe document or window not accessible');
5006
5197
  }
5007
- doc = iframe.contentDocument;
5008
- win = iframe.contentWindow;
5009
- config$1 = cfg;
5010
- running$2 = true;
5011
- shopFix = cfg.shopId != null ? get(cfg.shopId) : null;
5012
- if (shopFix) {
5013
- logger$1.log(`Shop fix loaded for "${cfg.shopId}":`, shopFix.description ?? '(no description)');
5014
- }
5015
- logger$1.configure({ enabled: !!cfg.debug });
5198
+ s.doc = iframe.contentDocument;
5199
+ s.win = iframe.contentWindow;
5200
+ s.config = cfg;
5201
+ s.running = true;
5202
+ s.shopFix = cfg.shopId != null ? get(cfg.shopId) : null;
5203
+ if (s.shopFix)
5204
+ s.logger.log(`Shop fix loaded for "${cfg.shopId}":`, s.shopFix.description ?? '(no description)');
5205
+ s.logger.configure({ enabled: !!cfg.debug });
5016
5206
  configure(!!cfg.debug);
5017
- start$4(doc, win, cfg, { debug: !!cfg.debug });
5018
- attach(cfg.debug);
5019
- logger$1.log('Started');
5207
+ s.enforcer.start(s.doc, s.win, cfg, { debug: !!cfg.debug });
5208
+ s.listeners.attach(cfg.debug);
5209
+ s.logger.log('Started');
5020
5210
  }
5021
- function stop$3() {
5022
- if (!running$2)
5211
+ function stop$2(s) {
5212
+ if (!s.running)
5023
5213
  return;
5024
- stop$4();
5025
- detach();
5026
- doc = null;
5027
- win = null;
5028
- config$1 = null;
5029
- shopFix = null;
5030
- running$2 = false;
5031
- logger$1.log('Stopped');
5032
- }
5033
- async function run() {
5034
- if (!running$2 || !doc || !win || !config$1) {
5035
- logger$1.warn('Not running. Call start() first.');
5214
+ s.enforcer.stop();
5215
+ s.listeners.detach();
5216
+ s.doc = null;
5217
+ s.win = null;
5218
+ s.config = null;
5219
+ s.shopFix = null;
5220
+ s.running = false;
5221
+ s.logger.log('Stopped');
5222
+ }
5223
+ async function run(s) {
5224
+ if (!s.running || !s.doc || !s.win || !s.config) {
5225
+ s.logger.warn('Not running. Call start() first.');
5036
5226
  return { height: 1000, width: 1000 };
5037
5227
  }
5038
5228
  const ctx = {
5039
- doc,
5040
- win,
5041
- deviceType: config$1.deviceType,
5042
- targetWidth: config$1.targetWidth,
5043
- targetHeight: config$1.targetHeight,
5044
- debug: config$1.debug,
5229
+ doc: s.doc,
5230
+ win: s.win,
5231
+ deviceType: s.config.deviceType,
5232
+ targetWidth: s.config.targetWidth,
5233
+ targetHeight: s.config.targetHeight,
5234
+ debug: s.config.debug,
5235
+ enforcer: s.enforcer,
5045
5236
  };
5046
5237
  const activeGlobal = getActiveFixes(ctx);
5047
- if (activeGlobal.length > 0) {
5048
- logger$1.log(`Active global fixes: ${activeGlobal.map((f) => f.name).join(', ')}`);
5049
- }
5238
+ if (activeGlobal.length > 0)
5239
+ s.logger.log(`Active global fixes: ${activeGlobal.map((f) => f.name).join(', ')}`);
5050
5240
  try {
5051
- return await run$1(ctx, activeGlobal, shopFix);
5241
+ return await run$1(ctx, activeGlobal, s.shopFix);
5052
5242
  }
5053
5243
  catch (err) {
5054
- logger$1.error('Critical error:', err);
5055
- return { height: doc.body?.scrollHeight || 1000, width: doc.body?.scrollWidth || 1000 };
5244
+ s.logger.error('Critical error:', err);
5245
+ return { height: s.doc.body?.scrollHeight || 1000, width: s.doc.body?.scrollWidth || 1000 };
5056
5246
  }
5057
5247
  }
5058
-
5059
- const logger = createLogger({
5060
- enabled: false,
5061
- prefix: 'IframeFixer',
5062
- });
5063
- // ============================================================================
5064
- // State
5065
- // ============================================================================
5066
- let iframe = null;
5067
- let config = null;
5068
- let running$1 = false;
5069
- let loadListener = null;
5070
- // ============================================================================
5071
- // Core API Functions
5072
- // ============================================================================
5073
- function start$2(cfg) {
5074
- if (running$1) {
5075
- logger.warn('Fixer is already running. Call stop() first.');
5248
+ function updateConfig$1(s, cfg) {
5249
+ if (!s.running || !s.config) {
5250
+ s.logger.warn('Not running. Call start() first.');
5076
5251
  return;
5077
5252
  }
5078
- iframe = cfg.iframe;
5079
- config = cfg;
5080
- running$1 = true;
5081
- logger.configure({ enabled: !!cfg.debug });
5082
- logger.log('Iframe fixer started');
5083
- initialize();
5253
+ s.config = { ...s.config, ...cfg };
5254
+ if (cfg.shopId !== undefined)
5255
+ s.shopFix = cfg.shopId != null ? get(cfg.shopId) : null;
5256
+ s.enforcer.updateConfig(cfg);
5257
+ s.logger.log('Config updated');
5258
+ }
5259
+ // ── Factory ───────────────────────────────────────────────────────────────────
5260
+ function createViewportProcessor() {
5261
+ const s = {
5262
+ logger: createLogger({ enabled: false, prefix: 'ViewportReplacer' }),
5263
+ enforcer: createEnforcer(),
5264
+ listeners: createViewportListeners(),
5265
+ doc: null,
5266
+ win: null,
5267
+ config: null,
5268
+ shopFix: null,
5269
+ running: false,
5270
+ };
5271
+ return {
5272
+ start: (iframe, cfg) => start$2(s, iframe, cfg),
5273
+ stop: () => stop$2(s),
5274
+ run: () => run(s),
5275
+ updateConfig: (cfg) => updateConfig$1(s, cfg),
5276
+ isRunning: () => s.running,
5277
+ };
5278
+ }
5279
+
5280
+ // ── Module-level functions ────────────────────────────────────────────────────
5281
+ function dispatchDimensionsEvent(dimensions) {
5282
+ window.dispatchEvent(new CustomEvent('iframe-dimensions-applied', { detail: dimensions }));
5084
5283
  }
5085
- function stop$2() {
5086
- if (!running$1) {
5284
+ async function process(s) {
5285
+ if (!s.iframe || !s.config)
5087
5286
  return;
5088
- }
5089
- // Stop viewport replacer
5090
- stop$3();
5091
- stop$5();
5092
- // Remove load listener
5093
- if (iframe && loadListener) {
5094
- iframe.removeEventListener('load', loadListener);
5095
- loadListener = null;
5096
- }
5097
- iframe = null;
5098
- config = null;
5099
- running$1 = false;
5100
- logger.log('Iframe fixer stopped');
5101
- }
5102
- async function initialize() {
5103
- if (!iframe || !config) {
5104
- logger.error('iframe not found');
5105
- config?.onError?.(new Error('iframe not found'));
5287
+ if (!s.iframe.contentDocument || !s.iframe.contentWindow) {
5288
+ s.logger.error('Cannot access iframe document');
5289
+ s.config.onError?.(new Error('Cannot access iframe document'));
5106
5290
  return;
5107
5291
  }
5108
- // Wait for iframe to load completely
5109
- if (iframe.contentDocument?.readyState === 'complete') {
5110
- await process();
5292
+ try {
5293
+ s.logger.log('Processing viewport units...');
5294
+ s.viewportReplacer.start(s.iframe, s.config);
5295
+ s.navigationBlocker.start(s.iframe, { debug: s.config.debug });
5296
+ const result = await s.viewportReplacer.run();
5297
+ s.logger.log('Process completed:', result);
5298
+ s.config.onSuccess?.(result);
5299
+ dispatchDimensionsEvent(result);
5111
5300
  }
5112
- else {
5113
- loadListener = handleIframeLoad;
5114
- iframe.addEventListener('load', loadListener);
5301
+ catch (error) {
5302
+ s.logger.error('Failed to process:', error);
5303
+ s.config.onError?.(error);
5115
5304
  }
5116
5305
  }
5117
- async function process() {
5118
- if (!iframe || !config)
5119
- return;
5120
- if (!iframe.contentDocument || !iframe.contentWindow) {
5121
- logger.error('Cannot access iframe document');
5122
- config.onError?.(new Error('Cannot access iframe document'));
5306
+ async function initialize(s) {
5307
+ if (!s.iframe || !s.config) {
5308
+ s.logger.error('iframe not found');
5309
+ s.config?.onError?.(new Error('iframe not found'));
5123
5310
  return;
5124
5311
  }
5125
- try {
5126
- logger.log('Processing viewport units...');
5127
- start$3(iframe, config);
5128
- start$5(iframe, { debug: config.debug });
5129
- const result = await run();
5130
- logger.log('Process completed:', result);
5131
- config.onSuccess?.(result);
5132
- dispatchDimensionsEvent(result);
5133
- // Optionally setup height observer
5134
- // setupHeightObserver();
5312
+ if (s.iframe.contentDocument?.readyState === 'complete') {
5313
+ await process(s);
5135
5314
  }
5136
- catch (error) {
5137
- logger.error('Failed to process:', error);
5138
- config.onError?.(error);
5315
+ else {
5316
+ s.loadListener = () => process(s);
5317
+ s.iframe.addEventListener('load', s.loadListener);
5139
5318
  }
5140
5319
  }
5141
- // ============================================================================
5142
- // Helper Functions
5143
- // ============================================================================
5144
- function dispatchDimensionsEvent(dimensions) {
5145
- window.dispatchEvent(new CustomEvent('iframe-dimensions-applied', {
5146
- detail: dimensions,
5147
- }));
5320
+ function start$1(s, cfg) {
5321
+ if (s.running) {
5322
+ s.logger.warn('Fixer is already running. Call stop() first.');
5323
+ return;
5324
+ }
5325
+ s.iframe = cfg.iframe;
5326
+ s.config = cfg;
5327
+ s.running = true;
5328
+ s.logger.configure({ enabled: !!cfg.debug });
5329
+ s.logger.log('Iframe fixer started');
5330
+ initialize(s);
5148
5331
  }
5149
- function handleIframeLoad() {
5150
- process();
5332
+ function stop$1(s) {
5333
+ if (!s.running)
5334
+ return;
5335
+ s.viewportReplacer.stop();
5336
+ s.heightObserver.stop();
5337
+ s.navigationBlocker.stop();
5338
+ if (s.iframe && s.loadListener) {
5339
+ s.iframe.removeEventListener('load', s.loadListener);
5340
+ s.loadListener = null;
5341
+ }
5342
+ s.iframe = null;
5343
+ s.config = null;
5344
+ s.running = false;
5345
+ s.logger.log('Iframe fixer stopped');
5346
+ }
5347
+ async function recalculate$1(s) {
5348
+ if (!s.running) {
5349
+ s.logger.warn('Fixer is not running.');
5350
+ return;
5351
+ }
5352
+ s.logger.log('Recalculating...');
5353
+ await process(s);
5151
5354
  }
5152
- /**
5153
- * Enable navigation blocking
5154
- */
5155
- function enableNavigationBlocking$2() {
5156
- if (!running$1) {
5157
- logger.warn('Fixer is not running. Call start() first.');
5355
+ function updateConfig(s, cfg) {
5356
+ if (!s.running || !s.config) {
5357
+ s.logger.warn('Fixer is not running.');
5158
5358
  return;
5159
5359
  }
5160
- enable();
5360
+ s.config = { ...s.config, ...cfg };
5361
+ s.viewportReplacer.updateConfig(cfg);
5362
+ s.logger.log('Config updated');
5363
+ }
5364
+ // ── Factory ───────────────────────────────────────────────────────────────────
5365
+ function createOrchestrator() {
5366
+ const s = {
5367
+ logger: createLogger({ enabled: false, prefix: 'IframeFixer' }),
5368
+ viewportReplacer: createViewportProcessor(),
5369
+ navigationBlocker: createNavigationBlocker(),
5370
+ heightObserver: createHeightObserver(),
5371
+ iframe: null,
5372
+ config: null,
5373
+ running: false,
5374
+ loadListener: null,
5375
+ };
5376
+ return {
5377
+ start: (cfg) => start$1(s, cfg),
5378
+ stop: () => stop$1(s),
5379
+ recalculate: () => recalculate$1(s),
5380
+ updateConfig: (cfg) => updateConfig(s, cfg),
5381
+ enableNavigationBlocking: () => s.navigationBlocker.enable(),
5382
+ enableNavigationBlockingMessage: () => s.navigationBlocker.enableMessage(),
5383
+ disableNavigationBlocking: () => s.navigationBlocker.disable(),
5384
+ disableNavigationBlockingMessage: () => s.navigationBlocker.disableMessage(),
5385
+ isRunning: () => s.running,
5386
+ getStateInfo: () => ({
5387
+ isRunning: s.running,
5388
+ hasIframe: !!s.iframe,
5389
+ hasConfig: !!s.config,
5390
+ hasNavigationBlocker: s.navigationBlocker.isRunning(),
5391
+ hasHeightObserver: s.heightObserver.isRunning(),
5392
+ viewportReplacerRunning: s.viewportReplacer.isRunning(),
5393
+ }),
5394
+ };
5161
5395
  }
5162
5396
 
5163
5397
  /**
5164
- * Iframe Helper Starter Module
5165
- * @module start
5398
+ * Iframe Helper factory entry point.
5399
+ *
5400
+ * Each call to `createIframeHelper()` returns a fully isolated instance
5401
+ * with its own processor state. Use one instance per iframe.
5166
5402
  */
5167
- // ============================================================================
5168
- // State
5169
- // ============================================================================
5170
- let running = false;
5171
- // ============================================================================
5172
- // Public API
5173
- // ============================================================================
5174
- function start$1(config) {
5175
- if (running) {
5176
- console.warn('[IframeHelperStarter] Already running. Call stop() first.');
5403
+ // ── Module-level functions ────────────────────────────────────────────────────
5404
+ function start(s, config) {
5405
+ if (s.running) {
5406
+ console.warn('[IframeHelper] Already running. Call stop() first.');
5177
5407
  return;
5178
5408
  }
5179
- start$2(config);
5180
- running = true;
5409
+ s.fixer.start(config);
5410
+ s.running = true;
5181
5411
  }
5182
- function stop$1() {
5183
- if (!running) {
5412
+ function stop(s) {
5413
+ if (!s.running)
5184
5414
  return;
5185
- }
5186
- stop$2();
5187
- running = false;
5415
+ s.fixer.stop();
5416
+ s.running = false;
5188
5417
  }
5189
- function enableNavigationBlocking$1() {
5190
- if (!running) {
5191
- console.warn('[IframeHelperStarter] Not running. Call start() first.');
5418
+ async function recalculate(s) {
5419
+ if (!s.running) {
5420
+ console.warn('[IframeHelper] Not running. Call start() first.');
5192
5421
  return;
5193
5422
  }
5194
- enableNavigationBlocking$2();
5195
- }
5196
-
5197
- function start(config) {
5198
- start$1(config);
5423
+ await s.fixer.recalculate();
5199
5424
  }
5200
- function stop() {
5201
- stop$1();
5425
+ function enableNavigationBlocking(s) {
5426
+ if (!s.running) {
5427
+ console.warn('[IframeHelper] Not running. Call start() first.');
5428
+ return;
5429
+ }
5430
+ s.fixer.enableNavigationBlocking();
5202
5431
  }
5203
- function enableNavigationBlocking() {
5204
- enableNavigationBlocking$1();
5432
+ // ── Factory ───────────────────────────────────────────────────────────────────
5433
+ function createIframeHelper() {
5434
+ const s = {
5435
+ fixer: createOrchestrator(),
5436
+ running: false,
5437
+ };
5438
+ return {
5439
+ start: (config) => start(s, config),
5440
+ stop: () => stop(s),
5441
+ recalculate: () => recalculate(s),
5442
+ enableNavigationBlocking: () => enableNavigationBlocking(s),
5443
+ isRunning: () => s.running,
5444
+ };
5205
5445
  }
5206
5446
 
5447
+ const iframeHelper = createIframeHelper();
5207
5448
  function useVizLiveRender() {
5208
5449
  const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
5209
5450
  const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
5210
5451
  const wrapperWidth = useHeatmapVizRectContext((s) => s.wrapperWidth);
5211
- const setIsRenderViz = useHeatmapVizContext((s) => s.setIsRenderViz);
5452
+ const setIsRenderedViz = useHeatmapVizContext((s) => s.setIsRenderedViz);
5212
5453
  const htmlContent = useHeatmapLiveStore((s) => s.htmlContent);
5213
5454
  const targetUrl = useHeatmapLiveStore((s) => s.targetUrl);
5214
5455
  const deviceType = useHeatmapSettingContext((s) => s.deviceType);
@@ -5254,10 +5495,10 @@ function useVizLiveRender() {
5254
5495
  const hasContent = (renderMode === 'portal' && targetUrl) || (renderMode === 'inline' && htmlContent);
5255
5496
  if (!iframe || !hasContent)
5256
5497
  return;
5257
- setIsRenderViz(true);
5258
- initIframeHelper$1(iframe, deviceType, { width: wrapperWidth, height: wrapperHeight }, (height) => {
5498
+ setIsRenderedViz(true);
5499
+ startIframe$1(iframe, deviceType, { width: wrapperWidth, height: wrapperHeight }, (height) => {
5259
5500
  height && setIframeHeight(height);
5260
- setIsRenderViz(true);
5501
+ setIsRenderedViz(true);
5261
5502
  });
5262
5503
  return () => { };
5263
5504
  }, [
@@ -5269,7 +5510,7 @@ function useVizLiveRender() {
5269
5510
  targetUrl,
5270
5511
  htmlContent,
5271
5512
  iframeRef,
5272
- setIsRenderViz,
5513
+ setIsRenderedViz,
5273
5514
  setIframeHeight,
5274
5515
  ]);
5275
5516
  return {
@@ -5288,9 +5529,9 @@ function buildPortalUrl(targetUrl, storefrontPassword) {
5288
5529
  const portalServiceUrl = getPortalServiceUrl();
5289
5530
  return `${portalServiceUrl}/?${params.toString()}`;
5290
5531
  }
5291
- function initIframeHelper$1(iframe, deviceType = EDeviceType.Desktop, rect, onSuccess) {
5292
- stop();
5293
- start({
5532
+ function startIframe$1(iframe, deviceType = EDeviceType.Desktop, rect, onSuccess) {
5533
+ iframeHelper.stop();
5534
+ iframeHelper.start({
5294
5535
  deviceType: deviceType,
5295
5536
  targetWidth: rect.width,
5296
5537
  targetHeight: rect.height,
@@ -5301,7 +5542,7 @@ function initIframeHelper$1(iframe, deviceType = EDeviceType.Desktop, rect, onSu
5301
5542
  },
5302
5543
  });
5303
5544
  // fixer.recalculate();
5304
- enableNavigationBlocking();
5545
+ iframeHelper.enableNavigationBlocking();
5305
5546
  }
5306
5547
 
5307
5548
  const CANVAS_ID = 'clarity-heatmap-canvas';
@@ -5557,11 +5798,12 @@ const useHeatmapRender = () => {
5557
5798
  const vizRef = useHeatmapVizRectContext((s) => s.vizRef);
5558
5799
  const setVizRef = useHeatmapVizRectContext((s) => s.setVizRef);
5559
5800
  const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
5560
- const setIsRenderViz = useHeatmapVizContext((s) => s.setIsRenderViz);
5801
+ const setIsRenderedViz = useHeatmapVizContext((s) => s.setIsRenderedViz);
5561
5802
  const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
5562
5803
  const contentWidth = useHeatmapWidthByDevice();
5563
5804
  const deviceType = useHeatmapSettingContext((s) => s.deviceType);
5564
5805
  const iframeRef = useRef(null);
5806
+ const helperRef = useRef(null);
5565
5807
  const renderHeatmap = useCallback(async (payloads) => {
5566
5808
  if (contentWidth === 0 || wrapperHeight === 0)
5567
5809
  return;
@@ -5570,17 +5812,22 @@ const useHeatmapRender = () => {
5570
5812
  const visualizer = vizRef ?? new GXVisualizer();
5571
5813
  if (!vizRef)
5572
5814
  setVizRef(visualizer);
5573
- setIsRenderViz(false);
5815
+ setIsRenderedViz(false);
5574
5816
  const iframe = iframeRef.current;
5575
5817
  if (!iframe?.contentWindow)
5576
5818
  return;
5577
5819
  await visualizer.html(payloads, iframe.contentWindow, viewId);
5578
- const size = { width: contentWidth, height: wrapperHeight };
5579
- initIframeHelper(iframe, deviceType, size, (height) => {
5580
- height && setIframeHeight(height);
5581
- setIsRenderViz(true);
5820
+ startIframe({
5821
+ helperRef,
5822
+ iframe,
5823
+ deviceType,
5824
+ size: { width: contentWidth, height: wrapperHeight },
5825
+ onSuccess: (height) => {
5826
+ if (height)
5827
+ setIframeHeight(height);
5828
+ setIsRenderedViz(true);
5829
+ },
5582
5830
  });
5583
- // setIsRenderViz(true);
5584
5831
  }, [wrapperHeight, contentWidth, deviceType]);
5585
5832
  useEffect(() => {
5586
5833
  if (!data || data.length === 0)
@@ -5591,33 +5838,41 @@ const useHeatmapRender = () => {
5591
5838
  setVizRef(null);
5592
5839
  };
5593
5840
  }, [data, renderHeatmap, setVizRef]);
5841
+ // Stop the helper when the component unmounts
5842
+ useEffect(() => {
5843
+ return () => {
5844
+ helperRef.current?.stop();
5845
+ helperRef.current = null;
5846
+ };
5847
+ }, []);
5594
5848
  return {
5595
5849
  iframeRef,
5596
5850
  };
5597
5851
  };
5598
- function initIframeHelper(iframe, deviceType = EDeviceType.Desktop, size, onSuccess) {
5852
+ function startIframe({ helperRef, iframe, deviceType = EDeviceType.Desktop, size, onSuccess }) {
5599
5853
  const docWidth = size.width ?? 0;
5600
5854
  const docHeight = size.height ?? 0;
5601
5855
  if (docHeight === 0)
5602
5856
  return;
5603
- stop();
5604
- start({
5605
- deviceType: deviceType,
5857
+ helperRef.current?.stop();
5858
+ const helper = createIframeHelper();
5859
+ helperRef.current = helper;
5860
+ helper.start({
5861
+ deviceType,
5606
5862
  targetWidth: docWidth,
5607
5863
  targetHeight: docHeight,
5608
- iframe: iframe,
5864
+ iframe,
5609
5865
  debug: true,
5610
5866
  onSuccess: (data) => {
5611
5867
  iframe.style.height = `${data.height}px`;
5612
5868
  onSuccess(data.height);
5613
5869
  },
5614
5870
  });
5615
- // fixer.recalculate();
5616
5871
  }
5617
5872
 
5618
5873
  const useReplayRender = () => {
5619
5874
  const data = useHeatmapDataContext((s) => s.data);
5620
- const setIsRenderViz = useHeatmapVizContext((s) => s.setIsRenderViz);
5875
+ const setIsRenderedViz = useHeatmapVizContext((s) => s.setIsRenderedViz);
5621
5876
  const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
5622
5877
  const visualizerRef = useRef(null);
5623
5878
  const iframeRef = useRef(null);
@@ -5637,7 +5892,7 @@ const useReplayRender = () => {
5637
5892
  version: envelope.version,
5638
5893
  onresize: (height) => {
5639
5894
  height && setIframeHeight(height);
5640
- setIsRenderViz(true);
5895
+ setIsRenderedViz(true);
5641
5896
  },
5642
5897
  mobile,
5643
5898
  vNext: true,
@@ -5793,7 +6048,7 @@ const useContentDimensions = ({ iframeRef }) => {
5793
6048
  const useObserveIframeHeight = (props) => {
5794
6049
  const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
5795
6050
  const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
5796
- const isRenderViz = useHeatmapVizContext((s) => s.isRenderViz);
6051
+ const isRenderedViz = useHeatmapVizContext((s) => s.isRenderedViz);
5797
6052
  const wrapperHeight = useHeatmapVizRectContext((s) => s.wrapperHeight);
5798
6053
  const { iframeRef } = props;
5799
6054
  const resizeObserverRef = useRef(null);
@@ -5854,7 +6109,7 @@ const useObserveIframeHeight = (props) => {
5854
6109
  }, [updateIframeHeight]);
5855
6110
  useEffect(() => {
5856
6111
  const iframe = iframeRef.current;
5857
- if (!iframe || !iframeHeight || !isRenderViz)
6112
+ if (!iframe || !iframeHeight || !isRenderedViz)
5858
6113
  return;
5859
6114
  const setupObservers = () => {
5860
6115
  try {
@@ -5916,7 +6171,7 @@ const useObserveIframeHeight = (props) => {
5916
6171
  }
5917
6172
  iframe.removeEventListener('load', setupObservers);
5918
6173
  };
5919
- }, [iframeRef, iframeHeight, isRenderViz]);
6174
+ }, [iframeRef, iframeHeight, isRenderedViz]);
5920
6175
  return {};
5921
6176
  };
5922
6177
 
@@ -6215,10 +6470,10 @@ const useScrollmapZones = (options) => {
6215
6470
  const newZones = createZones(scrollmap);
6216
6471
  setZones(newZones);
6217
6472
  setIsReady(true);
6218
- logger$9.log(`[useScrollmap] Created ${newZones.length} zones in ${mode} mode`);
6473
+ logger$4.log(`[useScrollmap] Created ${newZones.length} zones in ${mode} mode`);
6219
6474
  }
6220
6475
  catch (error) {
6221
- logger$9.error('[useScrollmap] Error:', error);
6476
+ logger$4.error('[useScrollmap] Error:', error);
6222
6477
  setIsReady(false);
6223
6478
  }
6224
6479
  }, [enabled, scrollmap, mode, createZones]);
@@ -7048,11 +7303,11 @@ const AutoScrollHandler = ({ visualRef }) => {
7048
7303
  };
7049
7304
 
7050
7305
  const PortalAreaRenderer = ({ iframeRef, visualRef, shadowRoot, onAreaCreated, onAreaClick, }) => {
7051
- const isRenderViz = useHeatmapVizContext((s) => s.isRenderViz);
7306
+ const isRenderedViz = useHeatmapVizContext((s) => s.isRenderedViz);
7052
7307
  const iframeDocument = iframeRef.current?.contentDocument || undefined;
7053
7308
  const { shadowContainer, isReady } = useAreaRendererContainer(iframeDocument, shadowRoot);
7054
- useAreaRectSync({ iframeDocument, shadowRoot, enabled: isReady && isRenderViz });
7055
- useAreaPositionsUpdater({ iframeRef, visualRef, enabled: isReady && isRenderViz });
7309
+ useAreaRectSync({ iframeDocument, shadowRoot, enabled: isReady && isRenderedViz });
7310
+ useAreaPositionsUpdater({ iframeRef, visualRef, enabled: isReady && isRenderedViz });
7056
7311
  if (!shadowContainer || !isReady)
7057
7312
  return null;
7058
7313
  return (jsxs(Fragment$1, { children: [jsx(AutoScrollHandler, { visualRef: visualRef }), jsx(AreasPortal, { shadowContainer: shadowContainer, onAreaClick: onAreaClick }), jsx(AreaEditHighlightPortal, { shadowContainer: shadowContainer, iframeRef: iframeRef, customShadowRoot: shadowRoot, onAreaCreated: onAreaCreated })] }));
@@ -7061,7 +7316,7 @@ const PortalAreaRenderer = ({ iframeRef, visualRef, shadowRoot, onAreaCreated, o
7061
7316
  const VizAreaClick = ({ iframeRef, visualRef, shadowRoot, autoCreateTopN = 10, enableOverlapResolution = true, onAreaClick, }) => {
7062
7317
  const clickAreas = useHeatmapDataContext((s) => s.clickAreas);
7063
7318
  const resetView = useHeatmapAreaClickContext((s) => s.resetView);
7064
- const isRenderViz = useHeatmapVizContext((s) => s.isRenderViz);
7319
+ const isRenderedViz = useHeatmapVizContext((s) => s.isRenderedViz);
7065
7320
  useAreaTopAutoDetect({ autoCreateTopN, shadowRoot, disabled: !!clickAreas?.length });
7066
7321
  useAreaFilterVisible({ iframeRef, enableOverlapResolution });
7067
7322
  useAreaHydration({ shadowRoot });
@@ -7070,7 +7325,7 @@ const VizAreaClick = ({ iframeRef, visualRef, shadowRoot, autoCreateTopN = 10, e
7070
7325
  resetView();
7071
7326
  };
7072
7327
  }, []);
7073
- if (!iframeRef.current || !isRenderViz)
7328
+ if (!iframeRef.current || !isRenderedViz)
7074
7329
  return null;
7075
7330
  return (jsx(Fragment, { children: jsx(PortalAreaRenderer, { iframeRef: iframeRef, visualRef: visualRef, shadowRoot: shadowRoot, onAreaClick: onAreaClick }) }));
7076
7331
  };
@@ -7784,7 +8039,7 @@ const VizDomHeatmap = () => {
7784
8039
  const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
7785
8040
  const setIframeHeight = useHeatmapVizRectContext((s) => s.setIframeHeight);
7786
8041
  const setVizRef = useHeatmapVizRectContext((s) => s.setVizRef);
7787
- const setIsRenderViz = useHeatmapVizContext((s) => s.setIsRenderViz);
8042
+ const setIsRenderedViz = useHeatmapVizContext((s) => s.setIsRenderedViz);
7788
8043
  const setSelectedElement = useHeatmapClickContext((s) => s.setSelectedElement);
7789
8044
  const setHoveredElement = useHeatmapHoverContext((s) => s.setHoveredElement);
7790
8045
  // const setSelectedArea = useHeatmapAreaClickContext((s) => s.setSelectedArea);
@@ -7794,7 +8049,7 @@ const VizDomHeatmap = () => {
7794
8049
  const cleanUp = () => {
7795
8050
  setVizRef(null);
7796
8051
  setIframeHeight(0);
7797
- setIsRenderViz(false);
8052
+ setIsRenderedViz(false);
7798
8053
  setSelectedElement(null);
7799
8054
  setHoveredElement(null);
7800
8055
  // setSelectedArea(null);