@gemx-dev/heatmap-react 3.5.92-dev.23 → 3.5.92-dev.25

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 (94) hide show
  1. package/dist/esm/components/VizElement/ElementCallout.d.ts +2 -2
  2. package/dist/esm/components/VizElement/ElementCallout.d.ts.map +1 -1
  3. package/dist/esm/components/VizElement/ElementCalloutClicked.d.ts +2 -2
  4. package/dist/esm/components/VizElement/ElementCalloutClicked.d.ts.map +1 -1
  5. package/dist/esm/components/VizElement/ElementCalloutHovered.d.ts +2 -1
  6. package/dist/esm/components/VizElement/ElementCalloutHovered.d.ts.map +1 -1
  7. package/dist/esm/components/VizElement/ElementMissing.d.ts +2 -1
  8. package/dist/esm/components/VizElement/ElementMissing.d.ts.map +1 -1
  9. package/dist/esm/components/VizElement/HeatmapElements.d.ts +4 -4
  10. package/dist/esm/components/VizElement/HeatmapElements.d.ts.map +1 -1
  11. package/dist/esm/components/VizElement/VizElements.d.ts +4 -3
  12. package/dist/esm/components/VizElement/VizElements.d.ts.map +1 -1
  13. package/dist/esm/components/VizScrollmap/HoverZones.d.ts +3 -3
  14. package/dist/esm/components/VizScrollmap/HoverZones.d.ts.map +1 -1
  15. package/dist/esm/components/VizScrollmap/Minimap.d.ts +3 -3
  16. package/dist/esm/components/VizScrollmap/Minimap.d.ts.map +1 -1
  17. package/dist/esm/helpers/canvas-backdrop.d.ts.map +1 -1
  18. package/dist/esm/helpers/viewport/element.d.ts +2 -2
  19. package/dist/esm/helpers/viewport/element.d.ts.map +1 -1
  20. package/dist/esm/helpers/viz-elm-callout/viz-elm.d.ts.map +1 -1
  21. package/dist/esm/hooks/viz-canvas/useHeatmapCanvas.d.ts.map +1 -1
  22. package/dist/esm/hooks/viz-elm/useClickedElement.d.ts +2 -2
  23. package/dist/esm/hooks/viz-elm/useClickedElement.d.ts.map +1 -1
  24. package/dist/esm/hooks/viz-elm/useElementCalloutVisible.d.ts +2 -1
  25. package/dist/esm/hooks/viz-elm/useElementCalloutVisible.d.ts.map +1 -1
  26. package/dist/esm/hooks/viz-elm/useHeatmapElementPosition.d.ts +3 -3
  27. package/dist/esm/hooks/viz-elm/useHeatmapElementPosition.d.ts.map +1 -1
  28. package/dist/esm/hooks/viz-elm/useHoveredElement.d.ts +2 -1
  29. package/dist/esm/hooks/viz-elm/useHoveredElement.d.ts.map +1 -1
  30. package/dist/esm/hooks/viz-render/useHeatmapIframeProcessor.d.ts.map +1 -1
  31. package/dist/esm/index.js +180 -156
  32. package/dist/esm/index.mjs +180 -156
  33. package/dist/esm/libs/iframe-processor/lifecycle.d.ts +1 -0
  34. package/dist/esm/libs/iframe-processor/lifecycle.d.ts.map +1 -1
  35. package/dist/esm/libs/iframe-processor/orchestrator.d.ts +1 -0
  36. package/dist/esm/libs/iframe-processor/orchestrator.d.ts.map +1 -1
  37. package/dist/esm/libs/iframe-processor/processors/height-observer/index.d.ts.map +1 -1
  38. package/dist/esm/libs/iframe-processor/processors/height-observer/types.d.ts +4 -0
  39. package/dist/esm/libs/iframe-processor/processors/height-observer/types.d.ts.map +1 -1
  40. package/dist/esm/libs/iframe-processor/shared/iframe-types.d.ts +2 -0
  41. package/dist/esm/libs/iframe-processor/shared/iframe-types.d.ts.map +1 -1
  42. package/dist/esm/types/viz-elm-callout.d.ts +2 -1
  43. package/dist/esm/types/viz-elm-callout.d.ts.map +1 -1
  44. package/dist/umd/components/VizElement/ElementCallout.d.ts +2 -2
  45. package/dist/umd/components/VizElement/ElementCallout.d.ts.map +1 -1
  46. package/dist/umd/components/VizElement/ElementCalloutClicked.d.ts +2 -2
  47. package/dist/umd/components/VizElement/ElementCalloutClicked.d.ts.map +1 -1
  48. package/dist/umd/components/VizElement/ElementCalloutHovered.d.ts +2 -1
  49. package/dist/umd/components/VizElement/ElementCalloutHovered.d.ts.map +1 -1
  50. package/dist/umd/components/VizElement/ElementMissing.d.ts +2 -1
  51. package/dist/umd/components/VizElement/ElementMissing.d.ts.map +1 -1
  52. package/dist/umd/components/VizElement/HeatmapElements.d.ts +4 -4
  53. package/dist/umd/components/VizElement/HeatmapElements.d.ts.map +1 -1
  54. package/dist/umd/components/VizElement/VizElements.d.ts +4 -3
  55. package/dist/umd/components/VizElement/VizElements.d.ts.map +1 -1
  56. package/dist/umd/components/VizScrollmap/HoverZones.d.ts +3 -3
  57. package/dist/umd/components/VizScrollmap/HoverZones.d.ts.map +1 -1
  58. package/dist/umd/components/VizScrollmap/Minimap.d.ts +3 -3
  59. package/dist/umd/components/VizScrollmap/Minimap.d.ts.map +1 -1
  60. package/dist/umd/helpers/canvas-backdrop.d.ts.map +1 -1
  61. package/dist/umd/helpers/viewport/element.d.ts +2 -2
  62. package/dist/umd/helpers/viewport/element.d.ts.map +1 -1
  63. package/dist/umd/helpers/viz-elm-callout/viz-elm.d.ts.map +1 -1
  64. package/dist/umd/hooks/viz-canvas/useHeatmapCanvas.d.ts.map +1 -1
  65. package/dist/umd/hooks/viz-elm/useClickedElement.d.ts +2 -2
  66. package/dist/umd/hooks/viz-elm/useClickedElement.d.ts.map +1 -1
  67. package/dist/umd/hooks/viz-elm/useElementCalloutVisible.d.ts +2 -1
  68. package/dist/umd/hooks/viz-elm/useElementCalloutVisible.d.ts.map +1 -1
  69. package/dist/umd/hooks/viz-elm/useHeatmapElementPosition.d.ts +3 -3
  70. package/dist/umd/hooks/viz-elm/useHeatmapElementPosition.d.ts.map +1 -1
  71. package/dist/umd/hooks/viz-elm/useHoveredElement.d.ts +2 -1
  72. package/dist/umd/hooks/viz-elm/useHoveredElement.d.ts.map +1 -1
  73. package/dist/umd/hooks/viz-render/useHeatmapIframeProcessor.d.ts.map +1 -1
  74. package/dist/umd/index.js +2 -2
  75. package/dist/umd/libs/iframe-processor/lifecycle.d.ts +1 -0
  76. package/dist/umd/libs/iframe-processor/lifecycle.d.ts.map +1 -1
  77. package/dist/umd/libs/iframe-processor/orchestrator.d.ts +1 -0
  78. package/dist/umd/libs/iframe-processor/orchestrator.d.ts.map +1 -1
  79. package/dist/umd/libs/iframe-processor/processors/height-observer/index.d.ts.map +1 -1
  80. package/dist/umd/libs/iframe-processor/processors/height-observer/types.d.ts +4 -0
  81. package/dist/umd/libs/iframe-processor/processors/height-observer/types.d.ts.map +1 -1
  82. package/dist/umd/libs/iframe-processor/shared/iframe-types.d.ts +2 -0
  83. package/dist/umd/libs/iframe-processor/shared/iframe-types.d.ts.map +1 -1
  84. package/dist/umd/types/viz-elm-callout.d.ts +2 -1
  85. package/dist/umd/types/viz-elm-callout.d.ts.map +1 -1
  86. package/package.json +1 -1
  87. package/dist/esm/hooks/viz-canvas/useAreamap.d.ts +0 -14
  88. package/dist/esm/hooks/viz-canvas/useAreamap.d.ts.map +0 -1
  89. package/dist/esm/hooks/viz-canvas/useAttentionMap.d.ts +0 -9
  90. package/dist/esm/hooks/viz-canvas/useAttentionMap.d.ts.map +0 -1
  91. package/dist/umd/hooks/viz-canvas/useAreamap.d.ts +0 -14
  92. package/dist/umd/hooks/viz-canvas/useAreamap.d.ts.map +0 -1
  93. package/dist/umd/hooks/viz-canvas/useAttentionMap.d.ts +0 -9
  94. package/dist/umd/hooks/viz-canvas/useAttentionMap.d.ts.map +0 -1
package/dist/esm/index.js CHANGED
@@ -1677,30 +1677,15 @@ const drawBackdropWithCutout = (options) => {
1677
1677
  const height = Math.min(canvasHeight - top, activeRect.height + cutoutExpansion * 2);
1678
1678
  // Clear previous drawing
1679
1679
  ctx.clearRect(0, 0, canvasWidth, canvasHeight);
1680
- // Set backdrop style
1680
+ // Draw backdrop as a single path with a cutout hole using evenodd fill rule.
1681
+ // This avoids seam artifacts that appear when using 4 separate rectangles
1682
+ // with fractional coordinates (sub-pixel gaps at rect boundaries).
1681
1683
  ctx.fillStyle = backdropColor;
1682
1684
  ctx.globalAlpha = backdropOpacity;
1683
- // Draw backdrop in 4 rectangles around the active element
1684
- // This creates a cutout effect
1685
- // Top rectangle (above active element)
1686
- if (top > 0) {
1687
- ctx.fillRect(0, 0, canvasWidth, top);
1688
- }
1689
- // Bottom rectangle (below active element)
1690
- const bottomY = top + height;
1691
- if (bottomY < canvasHeight) {
1692
- ctx.fillRect(0, bottomY, canvasWidth, canvasHeight - bottomY);
1693
- }
1694
- // Left rectangle (left of active element)
1695
- if (left > 0) {
1696
- ctx.fillRect(0, top, left, height);
1697
- }
1698
- // Right rectangle (right of active element)
1699
- const rightX = left + width;
1700
- if (rightX < canvasWidth) {
1701
- ctx.fillRect(rightX, top, canvasWidth - rightX, height);
1702
- }
1703
- // Reset alpha
1685
+ ctx.beginPath();
1686
+ ctx.rect(0, 0, canvasWidth, canvasHeight); // outer (full canvas)
1687
+ ctx.rect(left, top, width, height); // inner (cutout hole)
1688
+ ctx.fill('evenodd');
1704
1689
  ctx.globalAlpha = 1.0;
1705
1690
  };
1706
1691
  /**
@@ -3221,7 +3206,7 @@ function useAreaEditMode({ iframeRef, onAreaCreatedElement, enabled = false, })
3221
3206
  }
3222
3207
  iframeDocument.addEventListener('mousemove', handleMouseMove);
3223
3208
  iframeDocument.addEventListener('scroll', handleMouseLeave);
3224
- iframeDocument.removeEventListener('mouseleave', handleMouseLeave);
3209
+ iframeDocument.addEventListener('mouseleave', handleMouseLeave);
3225
3210
  iframeDocument.addEventListener('click', handleClick);
3226
3211
  return () => {
3227
3212
  iframeDocument.removeEventListener('mousemove', handleMouseMove);
@@ -3596,6 +3581,7 @@ const useHeatmapCanvas = () => {
3596
3581
  const heatmapType = useHeatmapSettingContext((state) => state.heatmapType);
3597
3582
  const clickMode = useHeatmapSettingContext((state) => state.clickMode);
3598
3583
  const scrollType = useHeatmapSettingContext((state) => state.scrollType);
3584
+ const setSelectedElement = useHeatmapClickContext((s) => s.setSelectedElement);
3599
3585
  const { start: startClickmap } = useClickmap();
3600
3586
  const { start: startAreaClickmap } = useAreaClickmap();
3601
3587
  const { start: startScrollmap } = useScrollmap();
@@ -3614,7 +3600,10 @@ const useHeatmapCanvas = () => {
3614
3600
  startScrollmap();
3615
3601
  break;
3616
3602
  }
3617
- }, [heatmapType, clickMode, startClickmap, startAreaClickmap, startScrollmap, scrollType]);
3603
+ return () => {
3604
+ setSelectedElement(null);
3605
+ };
3606
+ }, [heatmapType, clickMode, startClickmap, startAreaClickmap, startScrollmap, scrollType]); // eslint-disable-line react-hooks/exhaustive-deps
3618
3607
  };
3619
3608
 
3620
3609
  const scrollToElementIfNeeded = (visualRef, rect, scale, onScrollComplete) => {
@@ -4235,6 +4224,30 @@ function createPerfTimer(config) {
4235
4224
  };
4236
4225
  }
4237
4226
 
4227
+ /**
4228
+ * Default iframe dimension calculation.
4229
+ * Used as fallback when no fix overrides getDimensions().
4230
+ */
4231
+ function getFinalHeight(doc, win) {
4232
+ void doc.body.offsetHeight; // trigger reflow
4233
+ // const bodyMinHeight = parseFloat(win.getComputedStyle(doc.body).minHeight) || 0;
4234
+ // const htmlMinHeight = parseFloat(win.getComputedStyle(doc.documentElement).minHeight) || 0;
4235
+ return Math.max(
4236
+ // doc.body?.scrollHeight || 0,
4237
+ // doc.body?.offsetHeight || 0,
4238
+ // doc.documentElement?.scrollHeight || 0,
4239
+ // doc.documentElement?.offsetHeight || 0,
4240
+ doc.documentElement?.clientHeight || 0);
4241
+ }
4242
+ function getFinalWidth(doc) {
4243
+ return Math.max(
4244
+ // doc.body?.scrollWidth || 0,
4245
+ // doc.body?.offsetWidth || 0,
4246
+ // doc.documentElement?.scrollWidth || 0,
4247
+ // doc.documentElement?.offsetWidth || 0,
4248
+ doc.documentElement?.clientWidth || 0);
4249
+ }
4250
+
4238
4251
  /**
4239
4252
  * DOM observation setup — ResizeObserver + MutationObserver.
4240
4253
  * Returns a cleanup function that disconnects both observers.
@@ -4259,36 +4272,74 @@ function setup(doc, onChange) {
4259
4272
  };
4260
4273
  }
4261
4274
 
4275
+ // cspell:ignore cooldown
4262
4276
  /**
4263
4277
  * Height Observer Processor
4264
4278
  * Background observer — watches for iframe content height changes.
4265
4279
  */
4266
- // ── Module-level functions ────────────────────────────────────────────────────
4267
- function clearTimers(s) {
4268
- if (s.throttleTimeout) {
4269
- clearTimeout(s.throttleTimeout);
4270
- s.throttleTimeout = null;
4280
+ // ── Helpers ───────────────────────────────────────────────────────────────────
4281
+ function readCurrentHeight(s) {
4282
+ if (!s.iframe?.contentDocument || !s.iframe?.contentWindow)
4283
+ return 0;
4284
+ const height = getFinalHeight(s.iframe.contentDocument, s.iframe.contentWindow);
4285
+ s.logger.log('Height:', height);
4286
+ return height;
4287
+ }
4288
+ function isBlocked(s) {
4289
+ return s.isProcessing || s.isCoolingDown || s.throttleTimeout !== null;
4290
+ }
4291
+ function hasHeightChanged(s, height) {
4292
+ return height !== s.lastHeight;
4293
+ }
4294
+ // ── Cooldown ──────────────────────────────────────────────────────────────────
4295
+ function startCooldown(s) {
4296
+ s.isCoolingDown = true;
4297
+ s.cooldownTimeout = setTimeout(() => {
4298
+ s.cooldownTimeout = null;
4299
+ s.isCoolingDown = false;
4300
+ }, s.cooldownMs);
4301
+ }
4302
+ function stopCooldown(s) {
4303
+ if (s.cooldownTimeout) {
4304
+ clearTimeout(s.cooldownTimeout);
4305
+ s.cooldownTimeout = null;
4271
4306
  }
4307
+ s.isCoolingDown = false;
4308
+ }
4309
+ // ── Debounce ──────────────────────────────────────────────────────────────────
4310
+ function cancelPendingDebounce(s) {
4272
4311
  if (s.debounceTimeout) {
4273
4312
  clearTimeout(s.debounceTimeout);
4274
4313
  s.debounceTimeout = null;
4275
4314
  }
4276
4315
  }
4277
- function getActualHeight(s) {
4278
- if (!s.iframe?.contentDocument)
4279
- return 0;
4280
- const { documentElement: docEl, body } = s.iframe.contentDocument;
4281
- const heights = [docEl.scrollHeight, docEl.offsetHeight, body.scrollHeight, body.offsetHeight];
4282
- const maxHeight = Math.max(...heights.filter((h) => h > 0));
4283
- s.logger.log('Height sources:', {
4284
- 'documentElement.scrollHeight': docEl.scrollHeight,
4285
- 'documentElement.offsetHeight': docEl.offsetHeight,
4286
- 'body.scrollHeight': body.scrollHeight,
4287
- 'body.offsetHeight': body.offsetHeight,
4288
- maxHeight,
4289
- });
4290
- return maxHeight;
4316
+ function processCurrentHeightIfChanged(s) {
4317
+ const height = readCurrentHeight(s);
4318
+ if (hasHeightChanged(s, height)) {
4319
+ processHeightChange(s, height);
4320
+ }
4291
4321
  }
4322
+ function scheduleDebounce(s) {
4323
+ cancelPendingDebounce(s);
4324
+ s.debounceTimeout = setTimeout(() => {
4325
+ s.debounceTimeout = null;
4326
+ processCurrentHeightIfChanged(s);
4327
+ }, s.debounceMs);
4328
+ }
4329
+ // ── Throttle ──────────────────────────────────────────────────────────────────
4330
+ function scheduleThrottledCheck(s) {
4331
+ s.throttleTimeout = setTimeout(() => {
4332
+ s.throttleTimeout = null;
4333
+ const height = readCurrentHeight(s);
4334
+ if (!hasHeightChanged(s, height)) {
4335
+ cancelPendingDebounce(s);
4336
+ return;
4337
+ }
4338
+ s.logger.log(`Height changed: ${s.lastHeight}px -> ${height}px`);
4339
+ scheduleDebounce(s);
4340
+ }, s.throttleMs);
4341
+ }
4342
+ // ── Core ──────────────────────────────────────────────────────────────────────
4292
4343
  async function processHeightChange(s, newHeight) {
4293
4344
  if (!s.iframe || !s.config)
4294
4345
  return;
@@ -4300,7 +4351,6 @@ async function processHeightChange(s, newHeight) {
4300
4351
  width: s.iframe.contentWindow?.innerWidth ?? 0,
4301
4352
  };
4302
4353
  s.lastHeight = newHeight;
4303
- s.logger.log('Height change processed:', result);
4304
4354
  s.config.onHeightChange?.(result);
4305
4355
  window.dispatchEvent(new CustomEvent('iframe-dimensions-applied', { detail: result }));
4306
4356
  }
@@ -4310,46 +4360,59 @@ async function processHeightChange(s, newHeight) {
4310
4360
  }
4311
4361
  finally {
4312
4362
  s.isProcessing = false;
4363
+ if (s.cooldownMs > 0)
4364
+ startCooldown(s);
4313
4365
  }
4314
4366
  }
4315
4367
  function handleHeightChange(s) {
4316
- if (s.isProcessing || s.throttleTimeout)
4368
+ if (isBlocked(s))
4317
4369
  return;
4318
- s.throttleTimeout = setTimeout(() => {
4319
- s.throttleTimeout = null;
4320
- const currentHeight = getActualHeight(s);
4321
- if (currentHeight === s.lastHeight) {
4322
- // Height returned to known state — cancel any stale pending debounce
4323
- // to prevent it from firing with an outdated height and corrupting lastHeight.
4324
- if (s.debounceTimeout) {
4325
- clearTimeout(s.debounceTimeout);
4326
- s.debounceTimeout = null;
4327
- }
4328
- return;
4329
- }
4330
- s.logger.log(`Height changed: ${s.lastHeight}px -> ${currentHeight}px`);
4331
- if (s.debounceTimeout)
4332
- clearTimeout(s.debounceTimeout);
4333
- s.debounceTimeout = setTimeout(() => {
4334
- s.debounceTimeout = null;
4335
- // Re-read height at dispatch time to avoid using a stale closure value.
4336
- const finalHeight = getActualHeight(s);
4337
- if (finalHeight !== s.lastHeight) {
4338
- processHeightChange(s, finalHeight);
4339
- }
4340
- }, s.debounceMs);
4341
- }, s.throttleMs);
4370
+ scheduleThrottledCheck(s);
4342
4371
  }
4343
- function observe(s) {
4372
+ function attachObserver(s) {
4344
4373
  if (!s.iframe?.contentDocument?.body) {
4345
4374
  s.logger.warn('Cannot observe height changes: iframe body not found');
4346
4375
  return;
4347
4376
  }
4348
4377
  s.observerCleanup?.();
4349
- s.lastHeight = getActualHeight(s);
4378
+ s.lastHeight = readCurrentHeight(s);
4350
4379
  s.logger.log('Initial height:', s.lastHeight);
4351
4380
  s.observerCleanup = setup(s.iframe.contentDocument, () => handleHeightChange(s));
4352
4381
  }
4382
+ function detachObserver(s) {
4383
+ s.observerCleanup?.();
4384
+ s.observerCleanup = null;
4385
+ }
4386
+ function clearAllTimers(s) {
4387
+ if (s.throttleTimeout) {
4388
+ clearTimeout(s.throttleTimeout);
4389
+ s.throttleTimeout = null;
4390
+ }
4391
+ if (s.debounceTimeout) {
4392
+ clearTimeout(s.debounceTimeout);
4393
+ s.debounceTimeout = null;
4394
+ }
4395
+ if (s.startDelayTimeout) {
4396
+ clearTimeout(s.startDelayTimeout);
4397
+ s.startDelayTimeout = null;
4398
+ }
4399
+ stopCooldown(s);
4400
+ }
4401
+ // ── Lifecycle ─────────────────────────────────────────────────────────────────
4402
+ function observeImmediately(s) {
4403
+ attachObserver(s);
4404
+ s.logger.log('Height observer started');
4405
+ }
4406
+ function observeAfterDelay(s, delayMs) {
4407
+ s.logger.log(`Height observer will start in ${delayMs}ms`);
4408
+ s.startDelayTimeout = setTimeout(() => {
4409
+ s.startDelayTimeout = null;
4410
+ if (!s.running)
4411
+ return;
4412
+ attachObserver(s);
4413
+ s.logger.log('Height observer started (after delay)');
4414
+ }, delayMs);
4415
+ }
4353
4416
  function start$5(s, iframe, cfg) {
4354
4417
  if (s.running) {
4355
4418
  s.logger.warn('Observer is already running. Call stop() first.');
@@ -4359,27 +4422,32 @@ function start$5(s, iframe, cfg) {
4359
4422
  s.config = cfg;
4360
4423
  s.throttleMs = cfg.throttleMs ?? 25;
4361
4424
  s.debounceMs = cfg.debounceMs ?? 500;
4425
+ s.cooldownMs = cfg.cooldownMs ?? 0;
4362
4426
  s.running = true;
4363
- observe(s);
4364
- s.logger.log('Height observer started');
4427
+ const startDelayMs = cfg.startDelayMs ?? 0;
4428
+ if (startDelayMs > 0) {
4429
+ observeAfterDelay(s, startDelayMs);
4430
+ }
4431
+ else {
4432
+ observeImmediately(s);
4433
+ }
4365
4434
  }
4366
4435
  function stop$5(s) {
4367
4436
  if (!s.running)
4368
4437
  return;
4369
- s.observerCleanup?.();
4370
- s.observerCleanup = null;
4371
- clearTimers(s);
4438
+ detachObserver(s);
4439
+ clearAllTimers(s);
4372
4440
  s.iframe = null;
4373
4441
  s.config = null;
4374
4442
  s.lastHeight = 0;
4375
4443
  s.isProcessing = false;
4444
+ s.isCoolingDown = false;
4376
4445
  s.running = false;
4377
4446
  s.logger.log('Height observer stopped');
4378
4447
  }
4379
4448
  function clear(s) {
4380
- s.observerCleanup?.();
4381
- s.observerCleanup = null;
4382
- clearTimers(s);
4449
+ detachObserver(s);
4450
+ clearAllTimers(s);
4383
4451
  s.lastHeight = 0;
4384
4452
  s.isProcessing = false;
4385
4453
  }
@@ -4393,6 +4461,8 @@ function updateConfig$3(s, cfg) {
4393
4461
  s.throttleMs = cfg.throttleMs;
4394
4462
  if (cfg.debounceMs !== undefined)
4395
4463
  s.debounceMs = cfg.debounceMs;
4464
+ if (cfg.cooldownMs !== undefined)
4465
+ s.cooldownMs = cfg.cooldownMs;
4396
4466
  s.logger.configure({ enabled: !!s.config.debug });
4397
4467
  s.logger.log('Config updated');
4398
4468
  }
@@ -4406,15 +4476,19 @@ function createHeightObserver() {
4406
4476
  lastHeight: 0,
4407
4477
  throttleTimeout: null,
4408
4478
  debounceTimeout: null,
4479
+ startDelayTimeout: null,
4480
+ cooldownTimeout: null,
4409
4481
  isProcessing: false,
4482
+ isCoolingDown: false,
4410
4483
  throttleMs: 25,
4411
4484
  debounceMs: 500,
4485
+ cooldownMs: 0,
4412
4486
  running: false,
4413
4487
  };
4414
4488
  return {
4415
4489
  start: (iframe, cfg) => start$5(s, iframe, cfg),
4416
4490
  stop: () => stop$5(s),
4417
- observe: () => observe(s),
4491
+ observe: () => attachObserver(s),
4418
4492
  clear: () => clear(s),
4419
4493
  updateConfig: (cfg) => updateConfig$3(s, cfg),
4420
4494
  getCurrentHeight: () => s.lastHeight,
@@ -5161,20 +5235,6 @@ register$1({
5161
5235
  afterProcess,
5162
5236
  });
5163
5237
 
5164
- /**
5165
- * Default iframe dimension calculation.
5166
- * Used as fallback when no fix overrides getDimensions().
5167
- */
5168
- function getFinalHeight(doc, win) {
5169
- void doc.body.offsetHeight; // trigger reflow
5170
- const bodyMinHeight = parseFloat(win.getComputedStyle(doc.body).minHeight) || 0;
5171
- const htmlMinHeight = parseFloat(win.getComputedStyle(doc.documentElement).minHeight) || 0;
5172
- return Math.max(doc.body?.scrollHeight || 0, doc.body?.offsetHeight || 0, doc.documentElement?.scrollHeight || 0, doc.documentElement?.offsetHeight || 0, doc.documentElement?.clientHeight || 0, bodyMinHeight, htmlMinHeight);
5173
- }
5174
- function getFinalWidth(doc) {
5175
- return Math.max(doc.body?.scrollWidth || 0, doc.body?.offsetWidth || 0, doc.documentElement?.scrollWidth || 0, doc.documentElement?.offsetWidth || 0, doc.documentElement?.clientWidth || 0);
5176
- }
5177
-
5178
5238
  /**
5179
5239
  * Viewport fix pipeline runner.
5180
5240
  *
@@ -5456,20 +5516,6 @@ async function process(s) {
5456
5516
  perf$3.endSession();
5457
5517
  s.logger.groupEnd();
5458
5518
  s.logger.log('Process completed:', result);
5459
- s.heightObserver.stop();
5460
- s.heightObserver.start(s.iframe, {
5461
- iframe: s.iframe,
5462
- debug: s.config.debug,
5463
- throttleMs: 25,
5464
- debounceMs: 500,
5465
- onHeightChange: (result) => {
5466
- s.config?.onSuccess?.(result);
5467
- dispatchDimensionsEvent(result);
5468
- },
5469
- onError: (error) => {
5470
- s.config?.onError?.(error);
5471
- },
5472
- });
5473
5519
  s.config.onSuccess?.(result);
5474
5520
  dispatchDimensionsEvent(result);
5475
5521
  }
@@ -5521,6 +5567,26 @@ function stop$1(s) {
5521
5567
  s.running = false;
5522
5568
  s.logger.log('Stopped');
5523
5569
  }
5570
+ function startHeightObserver(s) {
5571
+ if (!s.iframe || !s.config)
5572
+ return;
5573
+ s.heightObserver.stop();
5574
+ s.heightObserver.start(s.iframe, {
5575
+ iframe: s.iframe,
5576
+ debug: s.config.debug,
5577
+ throttleMs: 25,
5578
+ debounceMs: 500,
5579
+ cooldownMs: 1000,
5580
+ startDelayMs: s.config.heightObserverStartDelayMs,
5581
+ onHeightChange: (result) => {
5582
+ s.config?.onSuccess?.(result);
5583
+ dispatchDimensionsEvent(result);
5584
+ },
5585
+ onError: (error) => {
5586
+ s.config?.onError?.(error);
5587
+ },
5588
+ });
5589
+ }
5524
5590
  async function recalculate$1(s) {
5525
5591
  if (!s.running) {
5526
5592
  s.logger.warn('Fixer is not running.');
@@ -5559,6 +5625,7 @@ function createOrchestrator() {
5559
5625
  enableNavigationBlockingMessage: () => s.navigationBlocker.enableMessage(),
5560
5626
  disableNavigationBlocking: () => s.navigationBlocker.disable(),
5561
5627
  disableNavigationBlockingMessage: () => s.navigationBlocker.disableMessage(),
5628
+ startHeightObserver: () => startHeightObserver(s),
5562
5629
  isRunning: () => s.running,
5563
5630
  getStateInfo: () => ({
5564
5631
  isRunning: s.running,
@@ -5617,6 +5684,7 @@ function createIframeHelper() {
5617
5684
  stop: () => stop(s),
5618
5685
  recalculate: () => recalculate(s),
5619
5686
  enableNavigationBlocking: () => enableNavigationBlocking(s),
5687
+ startHeightObserver: () => s.fixer.startHeightObserver(),
5620
5688
  isRunning: () => s.running,
5621
5689
  };
5622
5690
  }
@@ -6648,6 +6716,7 @@ const useHeatmapIframeProcessor = () => {
6648
6716
  if (height)
6649
6717
  setIframeHeight(height);
6650
6718
  setIsDomLoaded(true);
6719
+ helperRef.current?.startHeightObserver();
6651
6720
  },
6652
6721
  });
6653
6722
  }, [deviceType]);
@@ -6674,6 +6743,7 @@ const useHeatmapIframeProcessor = () => {
6674
6743
  if (height)
6675
6744
  setIframeHeight(height);
6676
6745
  setIsDomLoaded(true);
6746
+ helperRef.current?.startHeightObserver();
6677
6747
  },
6678
6748
  });
6679
6749
  }, [viewport]); // eslint-disable-line react-hooks/exhaustive-deps
@@ -6702,6 +6772,7 @@ function startIframe({ helperRef, iframe, shopId, deviceType = EDeviceType.Deskt
6702
6772
  iframe,
6703
6773
  debug: true,
6704
6774
  shopId,
6775
+ heightObserverStartDelayMs: 1000,
6705
6776
  onSuccess: (data) => {
6706
6777
  perf$1.measure('IframeHelper processing', tHelper);
6707
6778
  perf$1.measure('Total render', t0);
@@ -8490,45 +8561,6 @@ const VizClickmap = ({ iframeRef, visualRef, wrapperRef }) => {
8490
8561
  }
8491
8562
  };
8492
8563
 
8493
- const IS_ENABLE_MINIMAP = false;
8494
- const Minimap = ({ zones, maxUsers }) => {
8495
- const scrollType = useHeatmapSettingContext((s) => s.scrollType);
8496
- const showMinimap = useHeatmapScrollContext((s) => s.showMinimap);
8497
- const isScrollType = [EScrollType.Attention].includes(scrollType ?? EScrollType.Depth);
8498
- if (!showMinimap || !isScrollType || !IS_ENABLE_MINIMAP)
8499
- return null;
8500
- return (jsx("div", { style: {
8501
- position: 'fixed',
8502
- left: '20px',
8503
- top: '50%',
8504
- transform: 'translateY(-50%)',
8505
- width: '60px',
8506
- height: '400px',
8507
- backgroundColor: 'white',
8508
- borderRadius: '8px',
8509
- boxShadow: '0 4px 16px rgba(0,0,0,0.15)',
8510
- zIndex: 10002,
8511
- padding: '8px',
8512
- boxSizing: 'border-box',
8513
- }, children: jsx("div", { style: {
8514
- width: '100%',
8515
- height: '100%',
8516
- borderRadius: '4px',
8517
- overflow: 'hidden',
8518
- display: 'flex',
8519
- flexDirection: 'column',
8520
- }, children: zones.map((zone) => {
8521
- const normalized = maxUsers > 0 ? zone.percUsers / maxUsers : 0;
8522
- const color = getScrollGradientColor(normalized);
8523
- return (jsx("div", { title: `${zone.label}: ${zone.percUsers.toFixed(2)}%`, style: {
8524
- width: '100%',
8525
- flex: `${zone.endY - zone.startY}`,
8526
- backgroundColor: color,
8527
- borderBottom: '1px solid rgba(255,255,255,0.2)',
8528
- } }, zone.id));
8529
- }) }) }));
8530
- };
8531
-
8532
8564
  const ScrollZoneTooltip = ({ zone, position, currentScrollPercent, scrollmap, }) => {
8533
8565
  const CompScrollZoneTooltip = useHeatmapControlStore((state) => state.controls.ScrollZoneTooltip);
8534
8566
  const tooltipRef = useRef(null);
@@ -8554,17 +8586,9 @@ const ScrollZoneTooltip = ({ zone, position, currentScrollPercent, scrollmap, })
8554
8586
 
8555
8587
  const HoverZones = ({ iframeRef, wrapperRef, position, currentScrollPercent }) => {
8556
8588
  const scrollmap = useHeatmapDataContext((s) => s.scrollmap);
8557
- // const hoveredZone = useHeatmapVizScrollStore((state) => state.hoveredZone);
8558
- // const setHoveredZone = useHeatmapVizScrollStore((state) => state.setHoveredZone);
8559
- const { zones, isReady, maxUsers } = useScrollmapZones({
8560
- iframeRef,
8561
- wrapperRef,
8562
- });
8563
- if (!isReady || !zones.length)
8564
- return null;
8565
8589
  if (!position)
8566
8590
  return null;
8567
- return (jsxs(Fragment, { children: [jsx(ScrollZoneTooltip, { position: position, currentScrollPercent: currentScrollPercent, scrollmap: scrollmap || [] }), jsx(Minimap, { zones: zones, maxUsers: maxUsers })] }));
8591
+ return (jsx(Fragment, { children: jsx(ScrollZoneTooltip, { position: position, currentScrollPercent: currentScrollPercent, scrollmap: scrollmap || [] }) }));
8568
8592
  };
8569
8593
 
8570
8594
  const ScrollOverlay = ({ wrapperRef, iframeRef }) => {