@gemx-dev/heatmap-react 3.5.92-dev.35 → 3.5.92-dev.37

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 (46) hide show
  1. package/dist/esm/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
  2. package/dist/esm/hooks/viz-render/useHeatmapIframeProcessor.d.ts.map +1 -1
  3. package/dist/esm/hooks/viz-render/useHeatmapRenderDom.d.ts.map +1 -1
  4. package/dist/esm/index.d.ts +1 -1
  5. package/dist/esm/index.d.ts.map +1 -1
  6. package/dist/esm/index.js +83 -66
  7. package/dist/esm/index.mjs +83 -66
  8. package/dist/esm/libs/visualizer/GXVisualizer.d.ts +3 -3
  9. package/dist/esm/libs/visualizer/GXVisualizer.d.ts.map +1 -1
  10. package/dist/esm/libs/visualizer/index.d.ts +1 -1
  11. package/dist/esm/libs/visualizer/index.d.ts.map +1 -1
  12. package/dist/esm/libs/visualizer/renderers/ScrollBucketRenderer.d.ts +3 -23
  13. package/dist/esm/libs/visualizer/renderers/ScrollBucketRenderer.d.ts.map +1 -1
  14. package/dist/esm/libs/visualizer/renderers/index.d.ts +1 -1
  15. package/dist/esm/libs/visualizer/renderers/index.d.ts.map +1 -1
  16. package/dist/esm/libs/visualizer/shadow-dom/extractor.d.ts +26 -15
  17. package/dist/esm/libs/visualizer/shadow-dom/extractor.d.ts.map +1 -1
  18. package/dist/esm/types/viz-scrollmap.d.ts +8 -0
  19. package/dist/esm/types/viz-scrollmap.d.ts.map +1 -1
  20. package/dist/esm/utils/index.d.ts +1 -0
  21. package/dist/esm/utils/index.d.ts.map +1 -1
  22. package/dist/esm/utils/scrollmap.d.ts +11 -0
  23. package/dist/esm/utils/scrollmap.d.ts.map +1 -0
  24. package/dist/umd/hooks/viz-canvas/useScrollmap.d.ts.map +1 -1
  25. package/dist/umd/hooks/viz-render/useHeatmapIframeProcessor.d.ts.map +1 -1
  26. package/dist/umd/hooks/viz-render/useHeatmapRenderDom.d.ts.map +1 -1
  27. package/dist/umd/index.d.ts +1 -1
  28. package/dist/umd/index.d.ts.map +1 -1
  29. package/dist/umd/index.js +1 -1
  30. package/dist/umd/libs/visualizer/GXVisualizer.d.ts +3 -3
  31. package/dist/umd/libs/visualizer/GXVisualizer.d.ts.map +1 -1
  32. package/dist/umd/libs/visualizer/index.d.ts +1 -1
  33. package/dist/umd/libs/visualizer/index.d.ts.map +1 -1
  34. package/dist/umd/libs/visualizer/renderers/ScrollBucketRenderer.d.ts +3 -23
  35. package/dist/umd/libs/visualizer/renderers/ScrollBucketRenderer.d.ts.map +1 -1
  36. package/dist/umd/libs/visualizer/renderers/index.d.ts +1 -1
  37. package/dist/umd/libs/visualizer/renderers/index.d.ts.map +1 -1
  38. package/dist/umd/libs/visualizer/shadow-dom/extractor.d.ts +26 -15
  39. package/dist/umd/libs/visualizer/shadow-dom/extractor.d.ts.map +1 -1
  40. package/dist/umd/types/viz-scrollmap.d.ts +8 -0
  41. package/dist/umd/types/viz-scrollmap.d.ts.map +1 -1
  42. package/dist/umd/utils/index.d.ts +1 -0
  43. package/dist/umd/utils/index.d.ts.map +1 -1
  44. package/dist/umd/utils/scrollmap.d.ts +11 -0
  45. package/dist/umd/utils/scrollmap.d.ts.map +1 -0
  46. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useScrollmap.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-canvas/useScrollmap.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,YAAY;;CAuDxB,CAAC"}
1
+ {"version":3,"file":"useScrollmap.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-canvas/useScrollmap.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,YAAY;;CAwDxB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useHeatmapIframeProcessor.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-render/useHeatmapIframeProcessor.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,6BAA6B;IAC5C,GAAG,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7E,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,yBAAyB,QAAO,6BAwE5C,CAAC"}
1
+ {"version":3,"file":"useHeatmapIframeProcessor.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-render/useHeatmapIframeProcessor.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,6BAA6B;IAC5C,GAAG,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7E,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,yBAAyB,QAAO,6BA2E5C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useHeatmapRenderDom.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-render/useHeatmapRenderDom.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACtD;AAED,eAAO,MAAM,mBAAmB,QAAO,uBA0EtC,CAAC"}
1
+ {"version":3,"file":"useHeatmapRenderDom.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-render/useHeatmapRenderDom.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACtD;AAED,eAAO,MAAM,mBAAmB,QAAO,uBAwFtC,CAAC"}
@@ -5,6 +5,6 @@ export * from './hooks';
5
5
  export * from './types';
6
6
  export { decodeArrayClarity, decodeClarity, serializeAreas } from './helpers';
7
7
  export { useHeatmapCompareStore, useHeatmapConfigStore } from './stores';
8
- export { getElementAtPoint, getElementHash } from './utils';
8
+ export { buildBuckets, getElementAtPoint, getElementHash } from './utils';
9
9
  export * from './performance';
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AAExB,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE5D,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AAExB,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE1E,cAAc,eAAe,CAAC"}
package/dist/esm/index.js CHANGED
@@ -1971,6 +1971,21 @@ function createObservable(initialValue) {
1971
1971
  return observable;
1972
1972
  }
1973
1973
 
1974
+ /**
1975
+ * Given a list of items where each item represents the START of a bucket,
1976
+ * returns each item enriched with `startY` (= position) and `endY` (= next position, or 100 for the last bucket).
1977
+ *
1978
+ * Works for any scroll data shape (depth, attention, revenue).
1979
+ */
1980
+ function buildBuckets(items, getPosition) {
1981
+ const sorted = [...items].sort((a, b) => getPosition(a) - getPosition(b));
1982
+ return sorted.map((item, i) => ({
1983
+ ...item,
1984
+ startY: getPosition(item),
1985
+ endY: sorted[i + 1] !== undefined ? getPosition(sorted[i + 1]) : 100,
1986
+ }));
1987
+ }
1988
+
1974
1989
  function sortEvents(a, b) {
1975
1990
  return a.time - b.time;
1976
1991
  }
@@ -3550,10 +3565,11 @@ const useScrollmap = () => {
3550
3565
  const renderScrollBucket = useCallback(() => {
3551
3566
  if (!vizRef || !scrollmap || scrollmap.length === 0 || !isDomLoaded)
3552
3567
  return;
3553
- const bucketData = scrollmap.map((point) => ({
3554
- position: point.scrollReachY,
3555
- value: point.cumulativeSum,
3556
- percent: point.percUsers,
3568
+ const bucketData = buildBuckets(scrollmap, (p) => p.scrollReachY).map((b) => ({
3569
+ startY: b.startY,
3570
+ endY: b.endY,
3571
+ value: b.cumulativeSum,
3572
+ percent: b.percUsers,
3557
3573
  }));
3558
3574
  try {
3559
3575
  requestIdleCallback(() => vizRef?.scrollBucket?.(bucketData), { timeout: 300 });
@@ -4415,7 +4431,7 @@ async function processHeightChange(ctx, newHeight) {
4415
4431
  }
4416
4432
  }
4417
4433
  function handleHeightChange(ctx) {
4418
- if (!ctx.running || isBlocked(ctx))
4434
+ if (!ctx.running || !ctx.observerCleanup || isBlocked(ctx))
4419
4435
  return;
4420
4436
  scheduleThrottledCheck(ctx);
4421
4437
  }
@@ -6256,23 +6272,9 @@ class ScrollBucketRenderer {
6256
6272
  context.fillStyle = gradient;
6257
6273
  context.fillRect(0, 0, canvas.width, canvas.height);
6258
6274
  };
6259
- /**
6260
- * Convert flat position markers → structured buckets with startY/endY.
6261
- *
6262
- * Input positions: [0, 5, 10, 15, ..., 95]
6263
- * position=0 → { startY: 0, endY: 5 }
6264
- * position=5 → { startY: 5, endY: 10 }
6265
- * position=95 → { startY: 95, endY: 100 }
6266
- * Each position is the START of its bucket; end = next position (or 100 for last).
6267
- */
6268
6275
  mapToBuckets = (data) => {
6269
- const sorted = [...data].sort((a, b) => a.position - b.position);
6270
- return sorted.map((current, i) => ({
6271
- startY: current.position,
6272
- endY: sorted[i + 1]?.position ?? 100,
6273
- value: current.value,
6274
- percent: current.percent,
6275
- }));
6276
+ // Implement
6277
+ return data;
6276
6278
  };
6277
6279
  }
6278
6280
 
@@ -6434,29 +6436,32 @@ var ShortCircuitStrategy;
6434
6436
  function isShadowDomNode(tag) {
6435
6437
  return tag === Constant.ShadowDomTag || tag === Constant.PolyfillShadowDomTag;
6436
6438
  }
6437
- /** Scan the rendered DOM (including nested shadow roots) to collect tag names of shadow host elements. */
6438
- function collectShadowHostTags(root, tags = new Set()) {
6439
- root.querySelectorAll('*').forEach((el) => {
6440
- if (el.shadowRoot) {
6441
- tags.add(el.tagName);
6442
- collectShadowHostTags(el.shadowRoot, tags);
6443
- }
6444
- });
6445
- return tags;
6446
- }
6447
- /** Build a shadow subtree ID set from all DOM events.
6448
- * Two-pass cascade to handle any event ordering:
6449
- * Pass 1 — seed *S/*P node IDs.
6450
- * Pass 2 — cascade: any node whose parent is in the set is also in the set (repeat until stable). */
6451
- function buildShadowSubtreeIds(allDomEvents) {
6439
+ /**
6440
+ * Two-step collection of all shadow-related node IDs across dom + mutation events.
6441
+ *
6442
+ * Step 1 — scan dom + all mutations to find *S/*P nodes and their direct host parents.
6443
+ * Step 2 — cascade: any node whose parent is already in subtreeIds is also included.
6444
+ *
6445
+ * Using IDs (not tag names) makes host detection precise and avoids false positives
6446
+ * from elements that share a tag name with a shadow host but aren't one.
6447
+ */
6448
+ function collectShadowNodeIds(dom, events) {
6449
+ const mutationEvents = events.filter((e) => e.event === Event.Mutation);
6450
+ const allDomEvents = [dom, ...mutationEvents];
6452
6451
  const subtreeIds = new Set();
6452
+ const hostIds = new Set();
6453
+ // Step 1: seed *S/*P node IDs and collect their direct host parent IDs
6453
6454
  for (const e of allDomEvents) {
6454
6455
  const data = e.data;
6455
6456
  for (const node of data ?? []) {
6456
- if (isShadowDomNode(node.tag))
6457
+ if (isShadowDomNode(node.tag)) {
6457
6458
  subtreeIds.add(node.id);
6459
+ if (node.parent)
6460
+ hostIds.add(node.parent);
6461
+ }
6458
6462
  }
6459
6463
  }
6464
+ // Step 2: cascade — descendants of shadow nodes are also part of the shadow subtree
6460
6465
  let changed = true;
6461
6466
  while (changed) {
6462
6467
  changed = false;
@@ -6470,29 +6475,24 @@ function buildShadowSubtreeIds(allDomEvents) {
6470
6475
  }
6471
6476
  }
6472
6477
  }
6473
- return subtreeIds;
6478
+ return { subtreeIds, hostIds };
6474
6479
  }
6475
- function filterShadowNodes(data, subtreeIds, shadowHostTags) {
6476
- return (data?.filter((node) => {
6477
- if (isShadowDomNode(node.tag))
6478
- return true;
6479
- if (shadowHostTags.has(node.tag ?? ''))
6480
- return true;
6481
- return subtreeIds.has(node.id);
6482
- }) ?? []);
6480
+ function isShadowRelated(node, ids) {
6481
+ return ids.subtreeIds.has(node.id) || ids.hostIds.has(node.id);
6483
6482
  }
6484
- /** Extract shadow DOM nodes from merged.dom (initial Discover event, processed by setup()).
6485
- * Returns a filtered copy of the dom event, or null if no shadow DOM present. */
6486
- function extractSpecialDom(dom, events, shadowHostTags) {
6487
- const mutationEvents = events.filter((e) => e.event === Event.Mutation);
6488
- const subtreeIds = buildShadowSubtreeIds([dom, ...mutationEvents]);
6489
- const shadowNodes = filterShadowNodes(dom.data, subtreeIds, shadowHostTags);
6483
+ /**
6484
+ * Extract shadow DOM nodes from merged.dom (initial Discover event).
6485
+ * Includes both shadow host elements (hostIds) and shadow subtree nodes (subtreeIds).
6486
+ */
6487
+ function extractSpecialDom(dom, ids) {
6488
+ const shadowNodes = dom.data?.filter((node) => isShadowRelated(node, ids)) ?? [];
6490
6489
  return shadowNodes.length ? { ...dom, data: shadowNodes } : null;
6491
6490
  }
6492
- /** Extract shadow DOM mutations + StyleSheet + CustomElement events from merged.events. */
6493
- function extractSpecialEvents(events, dom, shadowHostTags) {
6494
- const mutationEvents = events.filter((e) => e.event === Event.Mutation);
6495
- const subtreeIds = buildShadowSubtreeIds([dom, ...mutationEvents]);
6491
+ /**
6492
+ * Extract shadow DOM mutations + StyleSheet + CustomElement events from merged.events.
6493
+ * Mutation events are filtered to only include shadow-related nodes.
6494
+ */
6495
+ function extractSpecialEvents(events, ids) {
6496
6496
  const result = [];
6497
6497
  for (const e of events) {
6498
6498
  const ev = e.event;
@@ -6503,7 +6503,7 @@ function extractSpecialEvents(events, dom, shadowHostTags) {
6503
6503
  continue;
6504
6504
  }
6505
6505
  if (ev === Event.Mutation) {
6506
- const shadowNodes = filterShadowNodes(e.data, subtreeIds, shadowHostTags);
6506
+ const shadowNodes = e.data?.filter((node) => isShadowRelated(node, ids)) ?? [];
6507
6507
  if (shadowNodes.length)
6508
6508
  result.push({ ...e, data: shadowNodes });
6509
6509
  }
@@ -6706,9 +6706,9 @@ class GXVisualizer extends Visualizer {
6706
6706
  const timestamp = Date.now();
6707
6707
  const version = decoded[0].envelope.version;
6708
6708
  const html = doc.documentElement.outerHTML;
6709
- const shadowHostTags = collectShadowHostTags(doc);
6710
- const specialDom = extractSpecialDom(merged.dom, merged.events, shadowHostTags);
6711
- const specialEvents = extractSpecialEvents(merged.events, merged.dom, shadowHostTags);
6709
+ const shadowNodeIds = collectShadowNodeIds(merged.dom, merged.events);
6710
+ const specialDom = extractSpecialDom(merged.dom, shadowNodeIds);
6711
+ const specialEvents = extractSpecialEvents(merged.events, shadowNodeIds);
6712
6712
  void htmlCache.set({ key: cacheKey, html, specialDom, specialEvents, version, timestamp });
6713
6713
  }
6714
6714
  catch (e) {
@@ -6768,8 +6768,10 @@ const useHeatmapIframeProcessor = () => {
6768
6768
  onHeightChange: (data) => {
6769
6769
  if (abort.signal.aborted)
6770
6770
  return;
6771
- if (data.height)
6771
+ if (data.height) {
6772
6772
  setIframeHeight(data.height);
6773
+ iframe.style.height = `${data.height}px`;
6774
+ }
6773
6775
  },
6774
6776
  });
6775
6777
  },
@@ -6841,15 +6843,19 @@ const useHeatmapRenderDom = () => {
6841
6843
  const heatmapType = useHeatmapSettingContext((s) => s.heatmapType);
6842
6844
  const elementToShow = useHeatmapDataContext((s) => s.dataInfo?.elementToShow);
6843
6845
  const dataHash = useHeatmapDataContext((s) => s.dataHash);
6846
+ const isLoadingDom = useHeatmapSettingContext((state) => state.isLoadingDom);
6844
6847
  const iframeRef = useRef(null);
6845
6848
  const abortRef = useRef(null);
6846
6849
  const elementToShowRef = useRef(null);
6847
6850
  const dataHashRef = useRef(null);
6848
6851
  const heatmapTypeRef = useRef(heatmapType);
6852
+ const lastRenderKeyRef = useRef(null);
6849
6853
  elementToShowRef.current = elementToShow ?? null;
6850
6854
  dataHashRef.current = dataHash ?? null;
6851
6855
  heatmapTypeRef.current = heatmapType;
6852
6856
  const { run: runIframeSetup, reset: resetIframeSetup } = useHeatmapIframeProcessor();
6857
+ const runIframeSetupRef = useRef(runIframeSetup);
6858
+ runIframeSetupRef.current = runIframeSetup;
6853
6859
  const renderHeatmap = useCallback(async (payloads) => {
6854
6860
  if (!payloads || payloads.length === 0)
6855
6861
  return;
@@ -6881,13 +6887,24 @@ const useHeatmapRenderDom = () => {
6881
6887
  if (abort.signal.aborted)
6882
6888
  return;
6883
6889
  // Phase 2: iframe setup — deferred to useIframeSetup (handles dims dependency)
6884
- runIframeSetup(iframe, t0, abort);
6885
- }, [deviceType]);
6890
+ runIframeSetupRef.current(iframe, t0, abort);
6891
+ }, []);
6886
6892
  useEffect(() => {
6893
+ if (isLoadingDom)
6894
+ return;
6887
6895
  if (!data || data.length === 0)
6888
6896
  return;
6889
- renderHeatmap(decodeArrayClarity(data));
6890
- }, [data, renderHeatmap]);
6897
+ const renderKey = `${dataHash}-${deviceType}`;
6898
+ if (renderKey === lastRenderKeyRef.current)
6899
+ return;
6900
+ const timer = setTimeout(() => {
6901
+ if (renderKey !== `${dataHashRef.current}-${deviceType}`)
6902
+ return;
6903
+ lastRenderKeyRef.current = renderKey;
6904
+ renderHeatmap(decodeArrayClarity(data));
6905
+ }, 50);
6906
+ return () => clearTimeout(timer);
6907
+ }, [data, deviceType, isLoadingDom]); // eslint-disable-line react-hooks/exhaustive-deps
6891
6908
  return { iframeRef };
6892
6909
  };
6893
6910
 
@@ -9022,4 +9039,4 @@ const HeatmapLayout = ({ shopId, data, clickmap, clickAreas, scrollmap, attentio
9022
9039
  }
9023
9040
  };
9024
9041
 
9025
- export { BACKDROP_CONFIG, DEFAULT_SIDEBAR_WIDTH, DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO, EClickMode, EClickRankType, EClickType, EDeviceType, EHeatmapDataSource, EHeatmapMode, EHeatmapType, ELM_CALLOUT_CONFIG, EScrollType, GraphView, HEATMAP_CONFIG, HEATMAP_IFRAME, HEATMAP_STYLE, HeatmapLayout, ViewIdContext, Z_INDEX$1 as Z_INDEX, compareViewPerformance, convertViewportToIframeCoords, createStorePerformanceTracker, createViewContextHook, decodeArrayClarity, decodeClarity, downloadPerformanceReport, getCompareViewId, getElementAtPoint, getElementHash, getMetricsByViewId, getPerformanceReportJSON, getScrollGradientColor, isElmInDataInfo, performanceLogger, printPerformanceSummary, scrollToElementIfNeeded, sendPerformanceReport, serializeAreas, trackStoreAction, useAreaCreation, useAreaEditMode, useAreaFilterVisible, useAreaHydration, useAreaInteraction, useAreaPositionsUpdater, useAreaRectSync, useAreaRendererContainer, useAreaTopAutoDetect, useClickedElement, useDebounceCallback, useElementCalloutVisible, useHeatmapAreaClickContext, useHeatmapCanvas, useHeatmapClickContext, useHeatmapCompareStore, useHeatmapConfigStore, useHeatmapCopyView, useHeatmapDataContext, useHeatmapEffects, useHeatmapElementPosition, useHeatmapHoverContext, useHeatmapLiveContext, useHeatmapRenderByMode, useHeatmapScale, useHeatmapScroll, useHeatmapScrollContext, useHeatmapSettingContext, useHeatmapViewportByDevice, useHeatmapVizContext, useHeatmapVizRectContext, useHoveredElement, useMeasureFunction, useRegisterConfig, useRegisterControl, useRegisterData, useRegisterHeatmap, useRenderCount, useScrollmapZones, useTrackHookCall, useViewIdContext, useVizLiveRender, useWhyDidYouUpdate, useWrapperRefHeight, useZonePositions, withPerformanceTracking };
9042
+ export { BACKDROP_CONFIG, DEFAULT_SIDEBAR_WIDTH, DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO, EClickMode, EClickRankType, EClickType, EDeviceType, EHeatmapDataSource, EHeatmapMode, EHeatmapType, ELM_CALLOUT_CONFIG, EScrollType, GraphView, HEATMAP_CONFIG, HEATMAP_IFRAME, HEATMAP_STYLE, HeatmapLayout, ViewIdContext, Z_INDEX$1 as Z_INDEX, buildBuckets, compareViewPerformance, convertViewportToIframeCoords, createStorePerformanceTracker, createViewContextHook, decodeArrayClarity, decodeClarity, downloadPerformanceReport, getCompareViewId, getElementAtPoint, getElementHash, getMetricsByViewId, getPerformanceReportJSON, getScrollGradientColor, isElmInDataInfo, performanceLogger, printPerformanceSummary, scrollToElementIfNeeded, sendPerformanceReport, serializeAreas, trackStoreAction, useAreaCreation, useAreaEditMode, useAreaFilterVisible, useAreaHydration, useAreaInteraction, useAreaPositionsUpdater, useAreaRectSync, useAreaRendererContainer, useAreaTopAutoDetect, useClickedElement, useDebounceCallback, useElementCalloutVisible, useHeatmapAreaClickContext, useHeatmapCanvas, useHeatmapClickContext, useHeatmapCompareStore, useHeatmapConfigStore, useHeatmapCopyView, useHeatmapDataContext, useHeatmapEffects, useHeatmapElementPosition, useHeatmapHoverContext, useHeatmapLiveContext, useHeatmapRenderByMode, useHeatmapScale, useHeatmapScroll, useHeatmapScrollContext, useHeatmapSettingContext, useHeatmapViewportByDevice, useHeatmapVizContext, useHeatmapVizRectContext, useHoveredElement, useMeasureFunction, useRegisterConfig, useRegisterControl, useRegisterData, useRegisterHeatmap, useRenderCount, useScrollmapZones, useTrackHookCall, useViewIdContext, useVizLiveRender, useWhyDidYouUpdate, useWrapperRefHeight, useZonePositions, withPerformanceTracking };
@@ -1971,6 +1971,21 @@ function createObservable(initialValue) {
1971
1971
  return observable;
1972
1972
  }
1973
1973
 
1974
+ /**
1975
+ * Given a list of items where each item represents the START of a bucket,
1976
+ * returns each item enriched with `startY` (= position) and `endY` (= next position, or 100 for the last bucket).
1977
+ *
1978
+ * Works for any scroll data shape (depth, attention, revenue).
1979
+ */
1980
+ function buildBuckets(items, getPosition) {
1981
+ const sorted = [...items].sort((a, b) => getPosition(a) - getPosition(b));
1982
+ return sorted.map((item, i) => ({
1983
+ ...item,
1984
+ startY: getPosition(item),
1985
+ endY: sorted[i + 1] !== undefined ? getPosition(sorted[i + 1]) : 100,
1986
+ }));
1987
+ }
1988
+
1974
1989
  function sortEvents(a, b) {
1975
1990
  return a.time - b.time;
1976
1991
  }
@@ -3550,10 +3565,11 @@ const useScrollmap = () => {
3550
3565
  const renderScrollBucket = useCallback(() => {
3551
3566
  if (!vizRef || !scrollmap || scrollmap.length === 0 || !isDomLoaded)
3552
3567
  return;
3553
- const bucketData = scrollmap.map((point) => ({
3554
- position: point.scrollReachY,
3555
- value: point.cumulativeSum,
3556
- percent: point.percUsers,
3568
+ const bucketData = buildBuckets(scrollmap, (p) => p.scrollReachY).map((b) => ({
3569
+ startY: b.startY,
3570
+ endY: b.endY,
3571
+ value: b.cumulativeSum,
3572
+ percent: b.percUsers,
3557
3573
  }));
3558
3574
  try {
3559
3575
  requestIdleCallback(() => vizRef?.scrollBucket?.(bucketData), { timeout: 300 });
@@ -4415,7 +4431,7 @@ async function processHeightChange(ctx, newHeight) {
4415
4431
  }
4416
4432
  }
4417
4433
  function handleHeightChange(ctx) {
4418
- if (!ctx.running || isBlocked(ctx))
4434
+ if (!ctx.running || !ctx.observerCleanup || isBlocked(ctx))
4419
4435
  return;
4420
4436
  scheduleThrottledCheck(ctx);
4421
4437
  }
@@ -6256,23 +6272,9 @@ class ScrollBucketRenderer {
6256
6272
  context.fillStyle = gradient;
6257
6273
  context.fillRect(0, 0, canvas.width, canvas.height);
6258
6274
  };
6259
- /**
6260
- * Convert flat position markers → structured buckets with startY/endY.
6261
- *
6262
- * Input positions: [0, 5, 10, 15, ..., 95]
6263
- * position=0 → { startY: 0, endY: 5 }
6264
- * position=5 → { startY: 5, endY: 10 }
6265
- * position=95 → { startY: 95, endY: 100 }
6266
- * Each position is the START of its bucket; end = next position (or 100 for last).
6267
- */
6268
6275
  mapToBuckets = (data) => {
6269
- const sorted = [...data].sort((a, b) => a.position - b.position);
6270
- return sorted.map((current, i) => ({
6271
- startY: current.position,
6272
- endY: sorted[i + 1]?.position ?? 100,
6273
- value: current.value,
6274
- percent: current.percent,
6275
- }));
6276
+ // Implement
6277
+ return data;
6276
6278
  };
6277
6279
  }
6278
6280
 
@@ -6434,29 +6436,32 @@ var ShortCircuitStrategy;
6434
6436
  function isShadowDomNode(tag) {
6435
6437
  return tag === Constant.ShadowDomTag || tag === Constant.PolyfillShadowDomTag;
6436
6438
  }
6437
- /** Scan the rendered DOM (including nested shadow roots) to collect tag names of shadow host elements. */
6438
- function collectShadowHostTags(root, tags = new Set()) {
6439
- root.querySelectorAll('*').forEach((el) => {
6440
- if (el.shadowRoot) {
6441
- tags.add(el.tagName);
6442
- collectShadowHostTags(el.shadowRoot, tags);
6443
- }
6444
- });
6445
- return tags;
6446
- }
6447
- /** Build a shadow subtree ID set from all DOM events.
6448
- * Two-pass cascade to handle any event ordering:
6449
- * Pass 1 — seed *S/*P node IDs.
6450
- * Pass 2 — cascade: any node whose parent is in the set is also in the set (repeat until stable). */
6451
- function buildShadowSubtreeIds(allDomEvents) {
6439
+ /**
6440
+ * Two-step collection of all shadow-related node IDs across dom + mutation events.
6441
+ *
6442
+ * Step 1 — scan dom + all mutations to find *S/*P nodes and their direct host parents.
6443
+ * Step 2 — cascade: any node whose parent is already in subtreeIds is also included.
6444
+ *
6445
+ * Using IDs (not tag names) makes host detection precise and avoids false positives
6446
+ * from elements that share a tag name with a shadow host but aren't one.
6447
+ */
6448
+ function collectShadowNodeIds(dom, events) {
6449
+ const mutationEvents = events.filter((e) => e.event === Event.Mutation);
6450
+ const allDomEvents = [dom, ...mutationEvents];
6452
6451
  const subtreeIds = new Set();
6452
+ const hostIds = new Set();
6453
+ // Step 1: seed *S/*P node IDs and collect their direct host parent IDs
6453
6454
  for (const e of allDomEvents) {
6454
6455
  const data = e.data;
6455
6456
  for (const node of data ?? []) {
6456
- if (isShadowDomNode(node.tag))
6457
+ if (isShadowDomNode(node.tag)) {
6457
6458
  subtreeIds.add(node.id);
6459
+ if (node.parent)
6460
+ hostIds.add(node.parent);
6461
+ }
6458
6462
  }
6459
6463
  }
6464
+ // Step 2: cascade — descendants of shadow nodes are also part of the shadow subtree
6460
6465
  let changed = true;
6461
6466
  while (changed) {
6462
6467
  changed = false;
@@ -6470,29 +6475,24 @@ function buildShadowSubtreeIds(allDomEvents) {
6470
6475
  }
6471
6476
  }
6472
6477
  }
6473
- return subtreeIds;
6478
+ return { subtreeIds, hostIds };
6474
6479
  }
6475
- function filterShadowNodes(data, subtreeIds, shadowHostTags) {
6476
- return (data?.filter((node) => {
6477
- if (isShadowDomNode(node.tag))
6478
- return true;
6479
- if (shadowHostTags.has(node.tag ?? ''))
6480
- return true;
6481
- return subtreeIds.has(node.id);
6482
- }) ?? []);
6480
+ function isShadowRelated(node, ids) {
6481
+ return ids.subtreeIds.has(node.id) || ids.hostIds.has(node.id);
6483
6482
  }
6484
- /** Extract shadow DOM nodes from merged.dom (initial Discover event, processed by setup()).
6485
- * Returns a filtered copy of the dom event, or null if no shadow DOM present. */
6486
- function extractSpecialDom(dom, events, shadowHostTags) {
6487
- const mutationEvents = events.filter((e) => e.event === Event.Mutation);
6488
- const subtreeIds = buildShadowSubtreeIds([dom, ...mutationEvents]);
6489
- const shadowNodes = filterShadowNodes(dom.data, subtreeIds, shadowHostTags);
6483
+ /**
6484
+ * Extract shadow DOM nodes from merged.dom (initial Discover event).
6485
+ * Includes both shadow host elements (hostIds) and shadow subtree nodes (subtreeIds).
6486
+ */
6487
+ function extractSpecialDom(dom, ids) {
6488
+ const shadowNodes = dom.data?.filter((node) => isShadowRelated(node, ids)) ?? [];
6490
6489
  return shadowNodes.length ? { ...dom, data: shadowNodes } : null;
6491
6490
  }
6492
- /** Extract shadow DOM mutations + StyleSheet + CustomElement events from merged.events. */
6493
- function extractSpecialEvents(events, dom, shadowHostTags) {
6494
- const mutationEvents = events.filter((e) => e.event === Event.Mutation);
6495
- const subtreeIds = buildShadowSubtreeIds([dom, ...mutationEvents]);
6491
+ /**
6492
+ * Extract shadow DOM mutations + StyleSheet + CustomElement events from merged.events.
6493
+ * Mutation events are filtered to only include shadow-related nodes.
6494
+ */
6495
+ function extractSpecialEvents(events, ids) {
6496
6496
  const result = [];
6497
6497
  for (const e of events) {
6498
6498
  const ev = e.event;
@@ -6503,7 +6503,7 @@ function extractSpecialEvents(events, dom, shadowHostTags) {
6503
6503
  continue;
6504
6504
  }
6505
6505
  if (ev === Event.Mutation) {
6506
- const shadowNodes = filterShadowNodes(e.data, subtreeIds, shadowHostTags);
6506
+ const shadowNodes = e.data?.filter((node) => isShadowRelated(node, ids)) ?? [];
6507
6507
  if (shadowNodes.length)
6508
6508
  result.push({ ...e, data: shadowNodes });
6509
6509
  }
@@ -6706,9 +6706,9 @@ class GXVisualizer extends Visualizer {
6706
6706
  const timestamp = Date.now();
6707
6707
  const version = decoded[0].envelope.version;
6708
6708
  const html = doc.documentElement.outerHTML;
6709
- const shadowHostTags = collectShadowHostTags(doc);
6710
- const specialDom = extractSpecialDom(merged.dom, merged.events, shadowHostTags);
6711
- const specialEvents = extractSpecialEvents(merged.events, merged.dom, shadowHostTags);
6709
+ const shadowNodeIds = collectShadowNodeIds(merged.dom, merged.events);
6710
+ const specialDom = extractSpecialDom(merged.dom, shadowNodeIds);
6711
+ const specialEvents = extractSpecialEvents(merged.events, shadowNodeIds);
6712
6712
  void htmlCache.set({ key: cacheKey, html, specialDom, specialEvents, version, timestamp });
6713
6713
  }
6714
6714
  catch (e) {
@@ -6768,8 +6768,10 @@ const useHeatmapIframeProcessor = () => {
6768
6768
  onHeightChange: (data) => {
6769
6769
  if (abort.signal.aborted)
6770
6770
  return;
6771
- if (data.height)
6771
+ if (data.height) {
6772
6772
  setIframeHeight(data.height);
6773
+ iframe.style.height = `${data.height}px`;
6774
+ }
6773
6775
  },
6774
6776
  });
6775
6777
  },
@@ -6841,15 +6843,19 @@ const useHeatmapRenderDom = () => {
6841
6843
  const heatmapType = useHeatmapSettingContext((s) => s.heatmapType);
6842
6844
  const elementToShow = useHeatmapDataContext((s) => s.dataInfo?.elementToShow);
6843
6845
  const dataHash = useHeatmapDataContext((s) => s.dataHash);
6846
+ const isLoadingDom = useHeatmapSettingContext((state) => state.isLoadingDom);
6844
6847
  const iframeRef = useRef(null);
6845
6848
  const abortRef = useRef(null);
6846
6849
  const elementToShowRef = useRef(null);
6847
6850
  const dataHashRef = useRef(null);
6848
6851
  const heatmapTypeRef = useRef(heatmapType);
6852
+ const lastRenderKeyRef = useRef(null);
6849
6853
  elementToShowRef.current = elementToShow ?? null;
6850
6854
  dataHashRef.current = dataHash ?? null;
6851
6855
  heatmapTypeRef.current = heatmapType;
6852
6856
  const { run: runIframeSetup, reset: resetIframeSetup } = useHeatmapIframeProcessor();
6857
+ const runIframeSetupRef = useRef(runIframeSetup);
6858
+ runIframeSetupRef.current = runIframeSetup;
6853
6859
  const renderHeatmap = useCallback(async (payloads) => {
6854
6860
  if (!payloads || payloads.length === 0)
6855
6861
  return;
@@ -6881,13 +6887,24 @@ const useHeatmapRenderDom = () => {
6881
6887
  if (abort.signal.aborted)
6882
6888
  return;
6883
6889
  // Phase 2: iframe setup — deferred to useIframeSetup (handles dims dependency)
6884
- runIframeSetup(iframe, t0, abort);
6885
- }, [deviceType]);
6890
+ runIframeSetupRef.current(iframe, t0, abort);
6891
+ }, []);
6886
6892
  useEffect(() => {
6893
+ if (isLoadingDom)
6894
+ return;
6887
6895
  if (!data || data.length === 0)
6888
6896
  return;
6889
- renderHeatmap(decodeArrayClarity(data));
6890
- }, [data, renderHeatmap]);
6897
+ const renderKey = `${dataHash}-${deviceType}`;
6898
+ if (renderKey === lastRenderKeyRef.current)
6899
+ return;
6900
+ const timer = setTimeout(() => {
6901
+ if (renderKey !== `${dataHashRef.current}-${deviceType}`)
6902
+ return;
6903
+ lastRenderKeyRef.current = renderKey;
6904
+ renderHeatmap(decodeArrayClarity(data));
6905
+ }, 50);
6906
+ return () => clearTimeout(timer);
6907
+ }, [data, deviceType, isLoadingDom]); // eslint-disable-line react-hooks/exhaustive-deps
6891
6908
  return { iframeRef };
6892
6909
  };
6893
6910
 
@@ -9022,4 +9039,4 @@ const HeatmapLayout = ({ shopId, data, clickmap, clickAreas, scrollmap, attentio
9022
9039
  }
9023
9040
  };
9024
9041
 
9025
- export { BACKDROP_CONFIG, DEFAULT_SIDEBAR_WIDTH, DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO, EClickMode, EClickRankType, EClickType, EDeviceType, EHeatmapDataSource, EHeatmapMode, EHeatmapType, ELM_CALLOUT_CONFIG, EScrollType, GraphView, HEATMAP_CONFIG, HEATMAP_IFRAME, HEATMAP_STYLE, HeatmapLayout, ViewIdContext, Z_INDEX$1 as Z_INDEX, compareViewPerformance, convertViewportToIframeCoords, createStorePerformanceTracker, createViewContextHook, decodeArrayClarity, decodeClarity, downloadPerformanceReport, getCompareViewId, getElementAtPoint, getElementHash, getMetricsByViewId, getPerformanceReportJSON, getScrollGradientColor, isElmInDataInfo, performanceLogger, printPerformanceSummary, scrollToElementIfNeeded, sendPerformanceReport, serializeAreas, trackStoreAction, useAreaCreation, useAreaEditMode, useAreaFilterVisible, useAreaHydration, useAreaInteraction, useAreaPositionsUpdater, useAreaRectSync, useAreaRendererContainer, useAreaTopAutoDetect, useClickedElement, useDebounceCallback, useElementCalloutVisible, useHeatmapAreaClickContext, useHeatmapCanvas, useHeatmapClickContext, useHeatmapCompareStore, useHeatmapConfigStore, useHeatmapCopyView, useHeatmapDataContext, useHeatmapEffects, useHeatmapElementPosition, useHeatmapHoverContext, useHeatmapLiveContext, useHeatmapRenderByMode, useHeatmapScale, useHeatmapScroll, useHeatmapScrollContext, useHeatmapSettingContext, useHeatmapViewportByDevice, useHeatmapVizContext, useHeatmapVizRectContext, useHoveredElement, useMeasureFunction, useRegisterConfig, useRegisterControl, useRegisterData, useRegisterHeatmap, useRenderCount, useScrollmapZones, useTrackHookCall, useViewIdContext, useVizLiveRender, useWhyDidYouUpdate, useWrapperRefHeight, useZonePositions, withPerformanceTracking };
9042
+ export { BACKDROP_CONFIG, DEFAULT_SIDEBAR_WIDTH, DEFAULT_VIEW_ID, DEFAULT_ZOOM_RATIO, EClickMode, EClickRankType, EClickType, EDeviceType, EHeatmapDataSource, EHeatmapMode, EHeatmapType, ELM_CALLOUT_CONFIG, EScrollType, GraphView, HEATMAP_CONFIG, HEATMAP_IFRAME, HEATMAP_STYLE, HeatmapLayout, ViewIdContext, Z_INDEX$1 as Z_INDEX, buildBuckets, compareViewPerformance, convertViewportToIframeCoords, createStorePerformanceTracker, createViewContextHook, decodeArrayClarity, decodeClarity, downloadPerformanceReport, getCompareViewId, getElementAtPoint, getElementHash, getMetricsByViewId, getPerformanceReportJSON, getScrollGradientColor, isElmInDataInfo, performanceLogger, printPerformanceSummary, scrollToElementIfNeeded, sendPerformanceReport, serializeAreas, trackStoreAction, useAreaCreation, useAreaEditMode, useAreaFilterVisible, useAreaHydration, useAreaInteraction, useAreaPositionsUpdater, useAreaRectSync, useAreaRendererContainer, useAreaTopAutoDetect, useClickedElement, useDebounceCallback, useElementCalloutVisible, useHeatmapAreaClickContext, useHeatmapCanvas, useHeatmapClickContext, useHeatmapCompareStore, useHeatmapConfigStore, useHeatmapCopyView, useHeatmapDataContext, useHeatmapEffects, useHeatmapElementPosition, useHeatmapHoverContext, useHeatmapLiveContext, useHeatmapRenderByMode, useHeatmapScale, useHeatmapScroll, useHeatmapScrollContext, useHeatmapSettingContext, useHeatmapViewportByDevice, useHeatmapVizContext, useHeatmapVizRectContext, useHoveredElement, useMeasureFunction, useRegisterConfig, useRegisterControl, useRegisterData, useRegisterHeatmap, useRenderCount, useScrollmapZones, useTrackHookCall, useViewIdContext, useVizLiveRender, useWhyDidYouUpdate, useWrapperRefHeight, useZonePositions, withPerformanceTracking };
@@ -1,11 +1,11 @@
1
- import type { AttentionData, ScrollBucketInput } from './renderers';
1
+ import type { AttentionData, IScrollBucket } from './renderers';
2
2
  import type { IRenderHtmlOptions } from './types';
3
3
  import { Visualizer } from '@gemx-dev/clarity-visualize';
4
4
  interface GXVisualizerInterface extends Visualizer {
5
5
  htmlRender: (props: IRenderHtmlOptions) => Promise<GXVisualizer>;
6
6
  htmlCached: (cacheKey: string, options: IRenderHtmlOptions) => Promise<GXVisualizer>;
7
7
  attention: (attentionData: AttentionData[], avgFold: number, isSecondary?: boolean) => void;
8
- scrollBucket: (data: ScrollBucketInput[]) => Promise<void>;
8
+ scrollBucket: (data: IScrollBucket[]) => Promise<void>;
9
9
  }
10
10
  export declare class GXVisualizer extends Visualizer implements GXVisualizerInterface {
11
11
  private attentionMap;
@@ -28,7 +28,7 @@ export declare class GXVisualizer extends Visualizer implements GXVisualizerInte
28
28
  * Render discrete color bands for scrollRevenue / scrollAttention data.
29
29
  * @param data - Array of bucket inputs with position markers (0, 5, 10, ..., 95) and percent values
30
30
  */
31
- scrollBucket: (data: ScrollBucketInput[]) => Promise<void>;
31
+ scrollBucket: (data: IScrollBucket[]) => Promise<void>;
32
32
  private scrollmapOverride;
33
33
  private clickmapOverride;
34
34
  private buildHtmlByCached;
@@ -1 +1 @@
1
- {"version":3,"file":"GXVisualizer.d.ts","sourceRoot":"","sources":["../../../src/libs/visualizer/GXVisualizer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAA0B,MAAM,SAAS,CAAC;AAG1E,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAmCzD,UAAU,qBAAsB,SAAQ,UAAU;IAChD,UAAU,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IACjE,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IACrF,SAAS,EAAE,CAAC,aAAa,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5F,YAAY,EAAE,CAAC,IAAI,EAAE,iBAAiB,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,qBAAa,YAAa,SAAQ,UAAW,YAAW,qBAAqB;IAC3E,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,gBAAgB,CAAyB;IACjD,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,gBAAgB,CAAyB;;IAkBjD,UAAU,GAAU,OAAO,kBAAkB,KAAG,OAAO,CAAC,YAAY,CAAC,CAcnE;IAEF,UAAU,GAAU,UAAU,MAAM,EAAE,SAAS,kBAAkB,KAAG,OAAO,CAAC,YAAY,CAAC,CAmBvF;IAEF;;;;;OAKG;IACH,SAAS,GAAI,eAAe,aAAa,EAAE,EAAE,SAAS,MAAM,EAAE,qBAAmB,KAAG,IAAI,CAGtF;IAEF;;;OAGG;IACH,YAAY,GAAU,MAAM,iBAAiB,EAAE,KAAG,OAAO,CAAC,IAAI,CAAC,CAG7D;IAEF,OAAO,CAAC,iBAAiB,CAGvB;IAEF,OAAO,CAAC,gBAAgB,CAGtB;IAEF,OAAO,CAAC,iBAAiB,CAgCvB;IAEF,OAAO,CAAC,iBAAiB,CA6BvB;IAEF,OAAO,CAAC,UAAU,CAEhB;IAEF,OAAO,CAAC,aAAa,CASnB;IAEF,OAAO,CAAC,gBAAgB,CAItB;CACH"}
1
+ {"version":3,"file":"GXVisualizer.d.ts","sourceRoot":"","sources":["../../../src/libs/visualizer/GXVisualizer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAA0B,MAAM,SAAS,CAAC;AAG1E,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAmCzD,UAAU,qBAAsB,SAAQ,UAAU;IAChD,UAAU,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IACjE,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IACrF,SAAS,EAAE,CAAC,aAAa,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5F,YAAY,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAED,qBAAa,YAAa,SAAQ,UAAW,YAAW,qBAAqB;IAC3E,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,gBAAgB,CAAyB;IACjD,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,gBAAgB,CAAyB;;IAkBjD,UAAU,GAAU,OAAO,kBAAkB,KAAG,OAAO,CAAC,YAAY,CAAC,CAcnE;IAEF,UAAU,GAAU,UAAU,MAAM,EAAE,SAAS,kBAAkB,KAAG,OAAO,CAAC,YAAY,CAAC,CAmBvF;IAEF;;;;;OAKG;IACH,SAAS,GAAI,eAAe,aAAa,EAAE,EAAE,SAAS,MAAM,EAAE,qBAAmB,KAAG,IAAI,CAGtF;IAEF;;;OAGG;IACH,YAAY,GAAU,MAAM,aAAa,EAAE,KAAG,OAAO,CAAC,IAAI,CAAC,CAGzD;IAEF,OAAO,CAAC,iBAAiB,CAGvB;IAEF,OAAO,CAAC,gBAAgB,CAGtB;IAEF,OAAO,CAAC,iBAAiB,CAgCvB;IAEF,OAAO,CAAC,iBAAiB,CA6BvB;IAEF,OAAO,CAAC,UAAU,CAEhB;IAEF,OAAO,CAAC,aAAa,CASnB;IAEF,OAAO,CAAC,gBAAgB,CAItB;CACH"}
@@ -1,4 +1,4 @@
1
+ export type { IScrollBucket } from './renderers';
1
2
  export { htmlCache } from './cache';
2
3
  export { GXVisualizer } from './GXVisualizer';
3
- export type { ScrollBucketInput } from './renderers';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/libs/visualizer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/libs/visualizer/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1,17 +1,6 @@
1
1
  import type { HeatmapHelper } from '@gemx-dev/clarity-visualize';
2
- export interface ScrollBucketInput {
3
- /** Position marker (0, 5, 10, ..., 95).
4
- * - position=0 → bucket range 0–5%
5
- * - position=10 → bucket range 5–10%
6
- * - position=15 → bucket range 10–15%
7
- * Each non-zero position is the END of its bucket; 0 is the special start marker.
8
- */
9
- position: number;
10
- /** Absolute value (e.g. revenue, attention time) */
11
- value: number;
12
- /** Relative percentage: value / total * 100. Used for color scale. */
13
- percent: number;
14
- }
2
+ import type { IScrollBucket } from '../../../types';
3
+ export type { IScrollBucket };
15
4
  export declare class ScrollBucketRenderer {
16
5
  private heatmap;
17
6
  private lastData;
@@ -29,17 +18,8 @@ export declare class ScrollBucketRenderer {
29
18
  * duplicate portal canvas management.
30
19
  * Stores data so the canvas can be redrawn when iframe height changes.
31
20
  */
32
- renderBucket: (data: ScrollBucketInput[]) => Promise<void>;
21
+ renderBucket: (data: IScrollBucket[]) => Promise<void>;
33
22
  private draw;
34
- /**
35
- * Convert flat position markers → structured buckets with startY/endY.
36
- *
37
- * Input positions: [0, 5, 10, 15, ..., 95]
38
- * position=0 → { startY: 0, endY: 5 }
39
- * position=5 → { startY: 5, endY: 10 }
40
- * position=95 → { startY: 95, endY: 100 }
41
- * Each position is the START of its bucket; end = next position (or 100 for last).
42
- */
43
23
  private mapToBuckets;
44
24
  }
45
25
  //# sourceMappingURL=ScrollBucketRenderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollBucketRenderer.d.ts","sourceRoot":"","sources":["../../../../src/libs/visualizer/renderers/ScrollBucketRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;CACjB;AAYD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,kBAAkB,CAAqC;IAC/D,OAAO,CAAC,aAAa,CAA8C;gBAEvD,OAAO,EAAE,aAAa,GAAG,IAAI;IAKzC,OAAO,CAAC,MAAM,CAIZ;IAEF,OAAO,CAAC,wBAAwB,CAI9B;IAEF,OAAO,CAAC,wBAAwB,CAS9B;IAEF,KAAK,QAAO,IAAI,CAEd;IAEF,KAAK,QAAO,IAAI,CAGd;IAEF;;;;;OAKG;IACH,YAAY,GAAU,MAAM,iBAAiB,EAAE,KAAG,OAAO,CAAC,IAAI,CAAC,CAQ7D;IAEF,OAAO,CAAC,IAAI,CAuDV;IAEF;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY,CASlB;CACH"}
1
+ {"version":3,"file":"ScrollBucketRenderer.d.ts","sourceRoot":"","sources":["../../../../src/libs/visualizer/renderers/ScrollBucketRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,YAAY,EAAE,aAAa,EAAE,CAAC;AAK9B,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,kBAAkB,CAAqC;IAC/D,OAAO,CAAC,aAAa,CAA8C;gBAEvD,OAAO,EAAE,aAAa,GAAG,IAAI;IAKzC,OAAO,CAAC,MAAM,CAIZ;IAEF,OAAO,CAAC,wBAAwB,CAI9B;IAEF,OAAO,CAAC,wBAAwB,CAS9B;IAEF,KAAK,QAAO,IAAI,CAEd;IAEF,KAAK,QAAO,IAAI,CAGd;IAEF;;;;;OAKG;IACH,YAAY,GAAU,MAAM,aAAa,EAAE,KAAG,OAAO,CAAC,IAAI,CAAC,CAQzD;IAEF,OAAO,CAAC,IAAI,CAuDV;IAEF,OAAO,CAAC,YAAY,CAGlB;CACH"}