@gemx-dev/heatmap-react 3.5.92-dev.29 → 3.5.92-dev.30

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.
@@ -1 +1 @@
1
- {"version":3,"file":"useElementCalloutVisible.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-elm/useElementCalloutVisible.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C,UAAU,MAAM;IACd,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,GAAG,CAAC;IAC3B,YAAY,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,wBAAwB,GAAI,sCAAsC,MAAM,OAuCpF,CAAC"}
1
+ {"version":3,"file":"useElementCalloutVisible.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-elm/useElementCalloutVisible.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO/C,UAAU,MAAM;IACd,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,GAAG,CAAC;IAC3B,YAAY,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,wBAAwB,GAAI,sCAAsC,MAAM,OAyCpF,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { IHeatmapRef } from '../../types';
1
+ import type { IHeatmapInfo, IHeatmapRef } from '../../types';
2
2
  interface Params {
3
3
  iframeRef: IHeatmapRef['Iframe'];
4
4
  getRect: (el?: any) => any;
@@ -12,5 +12,6 @@ export declare const convertViewportToIframeCoords: (clientX: number, clientY: n
12
12
  x: number;
13
13
  y: number;
14
14
  };
15
+ export declare const isElmInDataInfo: (hash: string | null, heatmapInfo?: IHeatmapInfo) => boolean;
15
16
  export {};
16
17
  //# sourceMappingURL=useHoveredElement.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useHoveredElement.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-elm/useHoveredElement.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,aAAa,CAAC;AAe7D,UAAU,MAAM;IACd,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,GAAG,CAAC;CAC5B;AAED,eAAO,MAAM,iBAAiB,GAAI,wBAAwB,MAAM;uEAiDpD,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC;;0BA4B/B,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,SAAS,MAAM;CA6B3D,CAAC;AAiBF,eAAO,MAAM,6BAA6B,GACxC,SAAS,MAAM,EACf,SAAS,MAAM,EACf,YAAY,OAAO,EACnB,OAAO,MAAM,KACZ;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAUxB,CAAC"}
1
+ {"version":3,"file":"useHoveredElement.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-elm/useHoveredElement.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAe7D,UAAU,MAAM;IACd,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,GAAG,CAAC;CAC5B;AAED,eAAO,MAAM,iBAAiB,GAAI,wBAAwB,MAAM;uEA8CpD,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC;;0BA4B/B,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,SAAS,MAAM;CA6B3D,CAAC;AAiBF,eAAO,MAAM,6BAA6B,GACxC,SAAS,MAAM,EACf,SAAS,MAAM,EACf,YAAY,OAAO,EACnB,OAAO,MAAM,KACZ;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAUxB,CAAC;AAsCF,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,GAAG,IAAI,EAAE,cAAc,YAAY,KAAG,OAKjF,CAAC"}
package/dist/esm/index.js CHANGED
@@ -1793,6 +1793,8 @@ const getElementAtPoint = (doc, x, y) => {
1793
1793
  return element;
1794
1794
  };
1795
1795
  function getElementHash(element) {
1796
+ if (!element)
1797
+ return null;
1796
1798
  return element.getAttribute('data-clarity-hashbeta') || element.getAttribute('data-clarity-hashalpha');
1797
1799
  }
1798
1800
 
@@ -3692,104 +3694,6 @@ const useClickedElement = ({ visualRef, getRect }) => {
3692
3694
  return { clickedElement, showMissingElement, shouldShowCallout };
3693
3695
  };
3694
3696
 
3695
- const useElementCalloutVisible = ({ visualRef, getRect, positionMode }) => {
3696
- const selectedElement = useHeatmapClickContext((s) => s.selectedElement);
3697
- const setShouldShowCallout = useHeatmapClickContext((s) => s.setShouldShowCallout);
3698
- const widthScale = useHeatmapVizContext((s) => s.widthScale);
3699
- const dataInfo = useHeatmapDataContext((s) => s.dataInfo);
3700
- useEffect(() => {
3701
- const isAbsolute = positionMode === 'absolute';
3702
- if (isAbsolute)
3703
- return;
3704
- const hash = selectedElement?.hash;
3705
- if (!hash)
3706
- return;
3707
- const elementIsInViewportFn = () => {
3708
- const elementInfo = dataInfo?.clickMapMetrics?.[hash];
3709
- if (!elementInfo)
3710
- return;
3711
- const rect = getRect({ hash, selector: elementInfo.selector });
3712
- const isInViewport = isElementInViewport(rect, visualRef, widthScale);
3713
- setShouldShowCallout(isInViewport);
3714
- };
3715
- elementIsInViewportFn();
3716
- const handleUpdate = () => {
3717
- requestAnimationFrame(elementIsInViewportFn);
3718
- };
3719
- window.addEventListener('scroll', handleUpdate, true);
3720
- window.addEventListener('resize', handleUpdate);
3721
- visualRef?.current?.addEventListener('scroll', handleUpdate);
3722
- return () => {
3723
- window.removeEventListener('scroll', handleUpdate, true);
3724
- window.removeEventListener('resize', handleUpdate);
3725
- visualRef?.current?.removeEventListener('scroll', handleUpdate);
3726
- };
3727
- }, [selectedElement?.hash, visualRef, widthScale, dataInfo, getRect, setShouldShowCallout, positionMode]);
3728
- return {};
3729
- };
3730
-
3731
- const useHeatmapEffects = ({ isVisible }) => {
3732
- // const selectedElement = useHeatmapClickContext((s) => s.selectedElement);
3733
- // const setShouldShowCallout = useHeatmapClickContext((s) => s.setShouldShowCallout);
3734
- const resetAll = () => {
3735
- // setShouldShowCallout(false);
3736
- };
3737
- // Reset khi ẩn
3738
- useEffect(() => {
3739
- }, [isVisible, resetAll]);
3740
- // Ẩn callout khi sidebar mở
3741
- // useEffect(() => {
3742
- // if (isElementSidebarOpen && selectedElement) {
3743
- // setShouldShowCallout(false);
3744
- // } else if (!isElementSidebarOpen && selectedElement) {
3745
- // setShouldShowCallout(true);
3746
- // }
3747
- // }, [isElementSidebarOpen, selectedElement]);
3748
- };
3749
-
3750
- const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
3751
- const viewport = useHeatmapViewportByDevice();
3752
- const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
3753
- const widthScale = useHeatmapVizContext((s) => s.widthScale);
3754
- const getRect = useCallback((element) => {
3755
- const hash = element?.hash;
3756
- if (!iframeRef.current?.contentDocument || !hash || !visualizer)
3757
- return null;
3758
- let domElement = null;
3759
- try {
3760
- domElement = visualizer.get(hash);
3761
- }
3762
- catch (error) {
3763
- console.error('Visualizer error:', { hash, error });
3764
- return null;
3765
- }
3766
- if (!domElement)
3767
- return null;
3768
- const layout = getElementLayout(domElement);
3769
- if (!layout)
3770
- return null;
3771
- const parentEl = wrapperRef.current;
3772
- if (!parentEl)
3773
- return null;
3774
- const scrollOffset = parentEl.scrollTop / widthScale;
3775
- const adjustedTop = layout.top + scrollOffset;
3776
- const outOfBounds = adjustedTop < 0 ||
3777
- adjustedTop > (iframeHeight || Infinity) ||
3778
- layout.left < 0 ||
3779
- (typeof viewport.width === 'number' && layout.left > viewport.width);
3780
- if (outOfBounds)
3781
- return null;
3782
- return {
3783
- left: layout.left,
3784
- top: adjustedTop,
3785
- width: Math.min(layout.width, viewport.width || layout.width),
3786
- height: layout.height,
3787
- outOfBounds,
3788
- };
3789
- }, [iframeRef, wrapperRef, visualizer, viewport, iframeHeight, widthScale]);
3790
- return { getRect };
3791
- };
3792
-
3793
3697
  function getBoundingBox(element) {
3794
3698
  if (typeof element.getBoundingClientRect !== 'function') {
3795
3699
  return null;
@@ -3904,15 +3808,12 @@ const useHoveredElement = ({ iframeRef, getRect }) => {
3904
3808
  const iframeRect = iframe.getBoundingClientRect();
3905
3809
  const { x, y } = convertViewportToIframeCoords(event.clientX, event.clientY, iframeRect, widthScale);
3906
3810
  const targetElement = findTargetElement(doc, x, y, dataInfo);
3907
- if (!targetElement || !isValidElement(targetElement, dataInfo)) {
3811
+ const hash = getElementHash(targetElement);
3812
+ if (!targetElement || !hash || !isElmInDataInfo(hash, dataInfo)) {
3908
3813
  reset();
3909
3814
  return;
3910
3815
  }
3911
- const hash = getElementHash(targetElement);
3912
- if (hash)
3913
- return hash;
3914
- reset();
3915
- return;
3816
+ return hash;
3916
3817
  }, [dataInfo, iframeRef, widthScale, reset]);
3917
3818
  const onHandleMouseMove = useCallback((event) => {
3918
3819
  if (isLoadingCanvas)
@@ -3924,7 +3825,7 @@ const useHoveredElement = ({ iframeRef, getRect }) => {
3924
3825
  }
3925
3826
  if (isHoveredElement(hash))
3926
3827
  return;
3927
- const selector = dataInfo?.clickMapMetrics?.[hash];
3828
+ const selector = dataInfo.clickMapMetrics?.[hash];
3928
3829
  const rect = getRect({ hash, selector });
3929
3830
  const elementInfo = buildElementInfo(hash, rect, dataInfo);
3930
3831
  if (!elementInfo) {
@@ -4012,13 +3913,111 @@ const findTargetElement = (doc, x, y, heatmapInfo) => {
4012
3913
  const isIframeReady = (iframeRef, heatmapInfo) => {
4013
3914
  return !!(iframeRef.current?.contentDocument && heatmapInfo?.clickMapMetrics);
4014
3915
  };
4015
- const isValidElement = (element, heatmapInfo) => {
4016
- if (!element)
4017
- return false;
4018
- const hash = getElementHash(element);
3916
+ const isElmInDataInfo = (hash, heatmapInfo) => {
4019
3917
  if (!hash)
4020
3918
  return false;
4021
- return !!heatmapInfo?.clickMapMetrics?.[hash];
3919
+ const isInSortedElements = heatmapInfo?.sortedElements?.some((item) => item.hash === hash);
3920
+ return !!isInSortedElements && !!heatmapInfo?.clickMapMetrics?.[hash];
3921
+ };
3922
+
3923
+ const useElementCalloutVisible = ({ visualRef, getRect, positionMode }) => {
3924
+ const selectedElement = useHeatmapClickContext((s) => s.selectedElement);
3925
+ const setShouldShowCallout = useHeatmapClickContext((s) => s.setShouldShowCallout);
3926
+ const widthScale = useHeatmapVizContext((s) => s.widthScale);
3927
+ const dataInfo = useHeatmapDataContext((s) => s.dataInfo);
3928
+ useEffect(() => {
3929
+ const isAbsolute = positionMode === 'absolute';
3930
+ if (isAbsolute)
3931
+ return;
3932
+ const hash = selectedElement?.hash;
3933
+ if (!hash)
3934
+ return;
3935
+ const elementIsInViewportFn = () => {
3936
+ if (!isElmInDataInfo(hash, dataInfo))
3937
+ return;
3938
+ const elementInfo = dataInfo?.clickMapMetrics?.[hash];
3939
+ if (!elementInfo)
3940
+ return;
3941
+ const rect = getRect({ hash, selector: elementInfo.selector });
3942
+ const isInViewport = isElementInViewport(rect, visualRef, widthScale);
3943
+ setShouldShowCallout(isInViewport);
3944
+ };
3945
+ elementIsInViewportFn();
3946
+ const handleUpdate = () => {
3947
+ requestAnimationFrame(elementIsInViewportFn);
3948
+ };
3949
+ window.addEventListener('scroll', handleUpdate, true);
3950
+ window.addEventListener('resize', handleUpdate);
3951
+ visualRef?.current?.addEventListener('scroll', handleUpdate);
3952
+ return () => {
3953
+ window.removeEventListener('scroll', handleUpdate, true);
3954
+ window.removeEventListener('resize', handleUpdate);
3955
+ visualRef?.current?.removeEventListener('scroll', handleUpdate);
3956
+ };
3957
+ }, [selectedElement?.hash, visualRef, widthScale, dataInfo, getRect, setShouldShowCallout, positionMode]);
3958
+ return {};
3959
+ };
3960
+
3961
+ const useHeatmapEffects = ({ isVisible }) => {
3962
+ // const selectedElement = useHeatmapClickContext((s) => s.selectedElement);
3963
+ // const setShouldShowCallout = useHeatmapClickContext((s) => s.setShouldShowCallout);
3964
+ const resetAll = () => {
3965
+ // setShouldShowCallout(false);
3966
+ };
3967
+ // Reset khi ẩn
3968
+ useEffect(() => {
3969
+ }, [isVisible, resetAll]);
3970
+ // Ẩn callout khi sidebar mở
3971
+ // useEffect(() => {
3972
+ // if (isElementSidebarOpen && selectedElement) {
3973
+ // setShouldShowCallout(false);
3974
+ // } else if (!isElementSidebarOpen && selectedElement) {
3975
+ // setShouldShowCallout(true);
3976
+ // }
3977
+ // }, [isElementSidebarOpen, selectedElement]);
3978
+ };
3979
+
3980
+ const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
3981
+ const viewport = useHeatmapViewportByDevice();
3982
+ const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
3983
+ const widthScale = useHeatmapVizContext((s) => s.widthScale);
3984
+ const getRect = useCallback((element) => {
3985
+ const hash = element?.hash;
3986
+ if (!iframeRef.current?.contentDocument || !hash || !visualizer)
3987
+ return null;
3988
+ let domElement = null;
3989
+ try {
3990
+ domElement = visualizer.get(hash);
3991
+ }
3992
+ catch (error) {
3993
+ console.error('Visualizer error:', { hash, error });
3994
+ return null;
3995
+ }
3996
+ if (!domElement)
3997
+ return null;
3998
+ const layout = getElementLayout(domElement);
3999
+ if (!layout)
4000
+ return null;
4001
+ const parentEl = wrapperRef.current;
4002
+ if (!parentEl)
4003
+ return null;
4004
+ const scrollOffset = parentEl.scrollTop / widthScale;
4005
+ const adjustedTop = layout.top + scrollOffset;
4006
+ const outOfBounds = adjustedTop < 0 ||
4007
+ adjustedTop > (iframeHeight || Infinity) ||
4008
+ layout.left < 0 ||
4009
+ (typeof viewport.width === 'number' && layout.left > viewport.width);
4010
+ if (outOfBounds)
4011
+ return null;
4012
+ return {
4013
+ left: layout.left,
4014
+ top: adjustedTop,
4015
+ width: Math.min(layout.width, viewport.width || layout.width),
4016
+ height: layout.height,
4017
+ outOfBounds,
4018
+ };
4019
+ }, [iframeRef, wrapperRef, visualizer, viewport, iframeHeight, widthScale]);
4020
+ return { getRect };
4022
4021
  };
4023
4022
 
4024
4023
  /**
@@ -8959,4 +8958,4 @@ const HeatmapLayout = ({ shopId, data, clickmap, clickAreas, scrollmap, attentio
8959
8958
  }
8960
8959
  };
8961
8960
 
8962
- 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, getMetricsByViewId, getPerformanceReportJSON, getScrollGradientColor, 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 };
8961
+ 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, 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 };
@@ -1793,6 +1793,8 @@ const getElementAtPoint = (doc, x, y) => {
1793
1793
  return element;
1794
1794
  };
1795
1795
  function getElementHash(element) {
1796
+ if (!element)
1797
+ return null;
1796
1798
  return element.getAttribute('data-clarity-hashbeta') || element.getAttribute('data-clarity-hashalpha');
1797
1799
  }
1798
1800
 
@@ -3692,104 +3694,6 @@ const useClickedElement = ({ visualRef, getRect }) => {
3692
3694
  return { clickedElement, showMissingElement, shouldShowCallout };
3693
3695
  };
3694
3696
 
3695
- const useElementCalloutVisible = ({ visualRef, getRect, positionMode }) => {
3696
- const selectedElement = useHeatmapClickContext((s) => s.selectedElement);
3697
- const setShouldShowCallout = useHeatmapClickContext((s) => s.setShouldShowCallout);
3698
- const widthScale = useHeatmapVizContext((s) => s.widthScale);
3699
- const dataInfo = useHeatmapDataContext((s) => s.dataInfo);
3700
- useEffect(() => {
3701
- const isAbsolute = positionMode === 'absolute';
3702
- if (isAbsolute)
3703
- return;
3704
- const hash = selectedElement?.hash;
3705
- if (!hash)
3706
- return;
3707
- const elementIsInViewportFn = () => {
3708
- const elementInfo = dataInfo?.clickMapMetrics?.[hash];
3709
- if (!elementInfo)
3710
- return;
3711
- const rect = getRect({ hash, selector: elementInfo.selector });
3712
- const isInViewport = isElementInViewport(rect, visualRef, widthScale);
3713
- setShouldShowCallout(isInViewport);
3714
- };
3715
- elementIsInViewportFn();
3716
- const handleUpdate = () => {
3717
- requestAnimationFrame(elementIsInViewportFn);
3718
- };
3719
- window.addEventListener('scroll', handleUpdate, true);
3720
- window.addEventListener('resize', handleUpdate);
3721
- visualRef?.current?.addEventListener('scroll', handleUpdate);
3722
- return () => {
3723
- window.removeEventListener('scroll', handleUpdate, true);
3724
- window.removeEventListener('resize', handleUpdate);
3725
- visualRef?.current?.removeEventListener('scroll', handleUpdate);
3726
- };
3727
- }, [selectedElement?.hash, visualRef, widthScale, dataInfo, getRect, setShouldShowCallout, positionMode]);
3728
- return {};
3729
- };
3730
-
3731
- const useHeatmapEffects = ({ isVisible }) => {
3732
- // const selectedElement = useHeatmapClickContext((s) => s.selectedElement);
3733
- // const setShouldShowCallout = useHeatmapClickContext((s) => s.setShouldShowCallout);
3734
- const resetAll = () => {
3735
- // setShouldShowCallout(false);
3736
- };
3737
- // Reset khi ẩn
3738
- useEffect(() => {
3739
- }, [isVisible, resetAll]);
3740
- // Ẩn callout khi sidebar mở
3741
- // useEffect(() => {
3742
- // if (isElementSidebarOpen && selectedElement) {
3743
- // setShouldShowCallout(false);
3744
- // } else if (!isElementSidebarOpen && selectedElement) {
3745
- // setShouldShowCallout(true);
3746
- // }
3747
- // }, [isElementSidebarOpen, selectedElement]);
3748
- };
3749
-
3750
- const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
3751
- const viewport = useHeatmapViewportByDevice();
3752
- const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
3753
- const widthScale = useHeatmapVizContext((s) => s.widthScale);
3754
- const getRect = useCallback((element) => {
3755
- const hash = element?.hash;
3756
- if (!iframeRef.current?.contentDocument || !hash || !visualizer)
3757
- return null;
3758
- let domElement = null;
3759
- try {
3760
- domElement = visualizer.get(hash);
3761
- }
3762
- catch (error) {
3763
- console.error('Visualizer error:', { hash, error });
3764
- return null;
3765
- }
3766
- if (!domElement)
3767
- return null;
3768
- const layout = getElementLayout(domElement);
3769
- if (!layout)
3770
- return null;
3771
- const parentEl = wrapperRef.current;
3772
- if (!parentEl)
3773
- return null;
3774
- const scrollOffset = parentEl.scrollTop / widthScale;
3775
- const adjustedTop = layout.top + scrollOffset;
3776
- const outOfBounds = adjustedTop < 0 ||
3777
- adjustedTop > (iframeHeight || Infinity) ||
3778
- layout.left < 0 ||
3779
- (typeof viewport.width === 'number' && layout.left > viewport.width);
3780
- if (outOfBounds)
3781
- return null;
3782
- return {
3783
- left: layout.left,
3784
- top: adjustedTop,
3785
- width: Math.min(layout.width, viewport.width || layout.width),
3786
- height: layout.height,
3787
- outOfBounds,
3788
- };
3789
- }, [iframeRef, wrapperRef, visualizer, viewport, iframeHeight, widthScale]);
3790
- return { getRect };
3791
- };
3792
-
3793
3697
  function getBoundingBox(element) {
3794
3698
  if (typeof element.getBoundingClientRect !== 'function') {
3795
3699
  return null;
@@ -3904,15 +3808,12 @@ const useHoveredElement = ({ iframeRef, getRect }) => {
3904
3808
  const iframeRect = iframe.getBoundingClientRect();
3905
3809
  const { x, y } = convertViewportToIframeCoords(event.clientX, event.clientY, iframeRect, widthScale);
3906
3810
  const targetElement = findTargetElement(doc, x, y, dataInfo);
3907
- if (!targetElement || !isValidElement(targetElement, dataInfo)) {
3811
+ const hash = getElementHash(targetElement);
3812
+ if (!targetElement || !hash || !isElmInDataInfo(hash, dataInfo)) {
3908
3813
  reset();
3909
3814
  return;
3910
3815
  }
3911
- const hash = getElementHash(targetElement);
3912
- if (hash)
3913
- return hash;
3914
- reset();
3915
- return;
3816
+ return hash;
3916
3817
  }, [dataInfo, iframeRef, widthScale, reset]);
3917
3818
  const onHandleMouseMove = useCallback((event) => {
3918
3819
  if (isLoadingCanvas)
@@ -3924,7 +3825,7 @@ const useHoveredElement = ({ iframeRef, getRect }) => {
3924
3825
  }
3925
3826
  if (isHoveredElement(hash))
3926
3827
  return;
3927
- const selector = dataInfo?.clickMapMetrics?.[hash];
3828
+ const selector = dataInfo.clickMapMetrics?.[hash];
3928
3829
  const rect = getRect({ hash, selector });
3929
3830
  const elementInfo = buildElementInfo(hash, rect, dataInfo);
3930
3831
  if (!elementInfo) {
@@ -4012,13 +3913,111 @@ const findTargetElement = (doc, x, y, heatmapInfo) => {
4012
3913
  const isIframeReady = (iframeRef, heatmapInfo) => {
4013
3914
  return !!(iframeRef.current?.contentDocument && heatmapInfo?.clickMapMetrics);
4014
3915
  };
4015
- const isValidElement = (element, heatmapInfo) => {
4016
- if (!element)
4017
- return false;
4018
- const hash = getElementHash(element);
3916
+ const isElmInDataInfo = (hash, heatmapInfo) => {
4019
3917
  if (!hash)
4020
3918
  return false;
4021
- return !!heatmapInfo?.clickMapMetrics?.[hash];
3919
+ const isInSortedElements = heatmapInfo?.sortedElements?.some((item) => item.hash === hash);
3920
+ return !!isInSortedElements && !!heatmapInfo?.clickMapMetrics?.[hash];
3921
+ };
3922
+
3923
+ const useElementCalloutVisible = ({ visualRef, getRect, positionMode }) => {
3924
+ const selectedElement = useHeatmapClickContext((s) => s.selectedElement);
3925
+ const setShouldShowCallout = useHeatmapClickContext((s) => s.setShouldShowCallout);
3926
+ const widthScale = useHeatmapVizContext((s) => s.widthScale);
3927
+ const dataInfo = useHeatmapDataContext((s) => s.dataInfo);
3928
+ useEffect(() => {
3929
+ const isAbsolute = positionMode === 'absolute';
3930
+ if (isAbsolute)
3931
+ return;
3932
+ const hash = selectedElement?.hash;
3933
+ if (!hash)
3934
+ return;
3935
+ const elementIsInViewportFn = () => {
3936
+ if (!isElmInDataInfo(hash, dataInfo))
3937
+ return;
3938
+ const elementInfo = dataInfo?.clickMapMetrics?.[hash];
3939
+ if (!elementInfo)
3940
+ return;
3941
+ const rect = getRect({ hash, selector: elementInfo.selector });
3942
+ const isInViewport = isElementInViewport(rect, visualRef, widthScale);
3943
+ setShouldShowCallout(isInViewport);
3944
+ };
3945
+ elementIsInViewportFn();
3946
+ const handleUpdate = () => {
3947
+ requestAnimationFrame(elementIsInViewportFn);
3948
+ };
3949
+ window.addEventListener('scroll', handleUpdate, true);
3950
+ window.addEventListener('resize', handleUpdate);
3951
+ visualRef?.current?.addEventListener('scroll', handleUpdate);
3952
+ return () => {
3953
+ window.removeEventListener('scroll', handleUpdate, true);
3954
+ window.removeEventListener('resize', handleUpdate);
3955
+ visualRef?.current?.removeEventListener('scroll', handleUpdate);
3956
+ };
3957
+ }, [selectedElement?.hash, visualRef, widthScale, dataInfo, getRect, setShouldShowCallout, positionMode]);
3958
+ return {};
3959
+ };
3960
+
3961
+ const useHeatmapEffects = ({ isVisible }) => {
3962
+ // const selectedElement = useHeatmapClickContext((s) => s.selectedElement);
3963
+ // const setShouldShowCallout = useHeatmapClickContext((s) => s.setShouldShowCallout);
3964
+ const resetAll = () => {
3965
+ // setShouldShowCallout(false);
3966
+ };
3967
+ // Reset khi ẩn
3968
+ useEffect(() => {
3969
+ }, [isVisible, resetAll]);
3970
+ // Ẩn callout khi sidebar mở
3971
+ // useEffect(() => {
3972
+ // if (isElementSidebarOpen && selectedElement) {
3973
+ // setShouldShowCallout(false);
3974
+ // } else if (!isElementSidebarOpen && selectedElement) {
3975
+ // setShouldShowCallout(true);
3976
+ // }
3977
+ // }, [isElementSidebarOpen, selectedElement]);
3978
+ };
3979
+
3980
+ const useHeatmapElementPosition = ({ iframeRef, wrapperRef, visualizer }) => {
3981
+ const viewport = useHeatmapViewportByDevice();
3982
+ const iframeHeight = useHeatmapVizRectContext((s) => s.iframeHeight);
3983
+ const widthScale = useHeatmapVizContext((s) => s.widthScale);
3984
+ const getRect = useCallback((element) => {
3985
+ const hash = element?.hash;
3986
+ if (!iframeRef.current?.contentDocument || !hash || !visualizer)
3987
+ return null;
3988
+ let domElement = null;
3989
+ try {
3990
+ domElement = visualizer.get(hash);
3991
+ }
3992
+ catch (error) {
3993
+ console.error('Visualizer error:', { hash, error });
3994
+ return null;
3995
+ }
3996
+ if (!domElement)
3997
+ return null;
3998
+ const layout = getElementLayout(domElement);
3999
+ if (!layout)
4000
+ return null;
4001
+ const parentEl = wrapperRef.current;
4002
+ if (!parentEl)
4003
+ return null;
4004
+ const scrollOffset = parentEl.scrollTop / widthScale;
4005
+ const adjustedTop = layout.top + scrollOffset;
4006
+ const outOfBounds = adjustedTop < 0 ||
4007
+ adjustedTop > (iframeHeight || Infinity) ||
4008
+ layout.left < 0 ||
4009
+ (typeof viewport.width === 'number' && layout.left > viewport.width);
4010
+ if (outOfBounds)
4011
+ return null;
4012
+ return {
4013
+ left: layout.left,
4014
+ top: adjustedTop,
4015
+ width: Math.min(layout.width, viewport.width || layout.width),
4016
+ height: layout.height,
4017
+ outOfBounds,
4018
+ };
4019
+ }, [iframeRef, wrapperRef, visualizer, viewport, iframeHeight, widthScale]);
4020
+ return { getRect };
4022
4021
  };
4023
4022
 
4024
4023
  /**
@@ -8959,4 +8958,4 @@ const HeatmapLayout = ({ shopId, data, clickmap, clickAreas, scrollmap, attentio
8959
8958
  }
8960
8959
  };
8961
8960
 
8962
- 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, getMetricsByViewId, getPerformanceReportJSON, getScrollGradientColor, 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 };
8961
+ 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, 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 };
@@ -25,5 +25,5 @@ export declare function getElementsAtPoint<T = Element>(doc: Document | ShadowRo
25
25
  * Get the element at a specific point (x, y)
26
26
  */
27
27
  export declare const getElementAtPoint: (doc: Document, x: number, y: number) => HTMLElement | null;
28
- export declare function getElementHash(element: HTMLElement): string | null;
28
+ export declare function getElementHash(element: HTMLElement | null): string | null;
29
29
  //# sourceMappingURL=dom.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/utils/dom.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IAEnE;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAC5C,GAAG,EAAE,QAAQ,GAAG,UAAU,EAC1B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,GAAE,0BAA+B,GACvC,CAAC,EAAE,CA2BL;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,KAAK,QAAQ,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,WAAW,GAAG,IAcrF,CAAC;AAEF,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAElE"}
1
+ {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/utils/dom.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IAEnE;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAC5C,GAAG,EAAE,QAAQ,GAAG,UAAU,EAC1B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,GAAE,0BAA+B,GACvC,CAAC,EAAE,CA2BL;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,KAAK,QAAQ,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,WAAW,GAAG,IAcrF,CAAC;AAEF,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAGzE"}
@@ -1 +1 @@
1
- {"version":3,"file":"useElementCalloutVisible.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-elm/useElementCalloutVisible.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C,UAAU,MAAM;IACd,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,GAAG,CAAC;IAC3B,YAAY,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,wBAAwB,GAAI,sCAAsC,MAAM,OAuCpF,CAAC"}
1
+ {"version":3,"file":"useElementCalloutVisible.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-elm/useElementCalloutVisible.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO/C,UAAU,MAAM;IACd,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,GAAG,CAAC;IAC3B,YAAY,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,wBAAwB,GAAI,sCAAsC,MAAM,OAyCpF,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { IHeatmapRef } from '../../types';
1
+ import type { IHeatmapInfo, IHeatmapRef } from '../../types';
2
2
  interface Params {
3
3
  iframeRef: IHeatmapRef['Iframe'];
4
4
  getRect: (el?: any) => any;
@@ -12,5 +12,6 @@ export declare const convertViewportToIframeCoords: (clientX: number, clientY: n
12
12
  x: number;
13
13
  y: number;
14
14
  };
15
+ export declare const isElmInDataInfo: (hash: string | null, heatmapInfo?: IHeatmapInfo) => boolean;
15
16
  export {};
16
17
  //# sourceMappingURL=useHoveredElement.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useHoveredElement.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-elm/useHoveredElement.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,aAAa,CAAC;AAe7D,UAAU,MAAM;IACd,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,GAAG,CAAC;CAC5B;AAED,eAAO,MAAM,iBAAiB,GAAI,wBAAwB,MAAM;uEAiDpD,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC;;0BA4B/B,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,SAAS,MAAM;CA6B3D,CAAC;AAiBF,eAAO,MAAM,6BAA6B,GACxC,SAAS,MAAM,EACf,SAAS,MAAM,EACf,YAAY,OAAO,EACnB,OAAO,MAAM,KACZ;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAUxB,CAAC"}
1
+ {"version":3,"file":"useHoveredElement.d.ts","sourceRoot":"","sources":["../../../src/hooks/viz-elm/useHoveredElement.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAe7D,UAAU,MAAM;IACd,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,GAAG,CAAC;CAC5B;AAED,eAAO,MAAM,iBAAiB,GAAI,wBAAwB,MAAM;uEA8CpD,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC;;0BA4B/B,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,SAAS,MAAM;CA6B3D,CAAC;AAiBF,eAAO,MAAM,6BAA6B,GACxC,SAAS,MAAM,EACf,SAAS,MAAM,EACf,YAAY,OAAO,EACnB,OAAO,MAAM,KACZ;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAUxB,CAAC;AAsCF,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,GAAG,IAAI,EAAE,cAAc,YAAY,KAAG,OAKjF,CAAC"}