@envive-ai/react-hooks 0.3.59 → 0.3.61
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.
- package/dist/application/utils/elementObserver.d.cts +2 -2
- package/dist/atoms/app/index.d.cts +7 -7
- package/dist/atoms/app/index.d.ts +7 -7
- package/dist/atoms/app/variant.d.ts +6 -6
- package/dist/atoms/chat/chatState.d.cts +19 -19
- package/dist/atoms/chat/chatState.d.ts +19 -19
- package/dist/atoms/chat/form.d.cts +2 -2
- package/dist/atoms/chat/form.d.ts +2 -2
- package/dist/atoms/chat/index.d.cts +2 -2
- package/dist/atoms/chat/index.d.ts +3 -3
- package/dist/atoms/chat/lastMessage.d.cts +2 -2
- package/dist/atoms/chat/lastMessage.d.ts +2 -2
- package/dist/atoms/chat/messageQueue.d.ts +7 -7
- package/dist/atoms/chat/performanceMetrics.d.ts +6 -6
- package/dist/atoms/chat/renderedWidgetRefs.d.ts +3 -3
- package/dist/atoms/chat/replies.d.cts +3 -3
- package/dist/atoms/chat/replies.d.ts +3 -3
- package/dist/atoms/chat/suggestions.d.cts +2 -2
- package/dist/atoms/chat/suggestions.d.ts +2 -2
- package/dist/atoms/envive/enviveConfig.d.cts +14 -14
- package/dist/atoms/envive/enviveConfig.d.ts +13 -13
- package/dist/atoms/globalSearch/globalSearch.d.cts +5 -5
- package/dist/atoms/globalSearch/globalSearch.d.ts +5 -5
- package/dist/atoms/org/customerService.d.cts +6 -6
- package/dist/atoms/org/customerService.d.ts +6 -6
- package/dist/atoms/org/graphqlConfig.d.cts +4 -4
- package/dist/atoms/org/graphqlConfig.d.ts +4 -4
- package/dist/atoms/org/newOrgConfigAtom.d.cts +2 -2
- package/dist/atoms/org/newOrgConfigAtom.d.ts +2 -2
- package/dist/atoms/org/orgAnalyticsConfig.d.cts +4 -4
- package/dist/atoms/org/orgAnalyticsConfig.d.ts +4 -4
- package/dist/atoms/search/chatSearch.d.cts +17 -17
- package/dist/atoms/search/chatSearch.d.ts +17 -17
- package/dist/atoms/search/searchAPI.d.cts +13 -13
- package/dist/atoms/search/searchAPI.d.ts +13 -13
- package/dist/atoms/widget/chatPreviewLoading.d.cts +2 -2
- package/dist/atoms/widget/chatPreviewLoading.d.ts +2 -2
- package/dist/contexts/systemSettingsContext/systemSettingsContext.d.cts +2 -2
- package/dist/contexts/types.d.ts +1 -1
- package/dist/contexts/typesV3.cjs +1 -1
- package/dist/contexts/typesV3.d.cts +8 -1
- package/dist/contexts/typesV3.d.ts +8 -1
- package/dist/contexts/typesV3.js +1 -1
- package/dist/hooks/GrabAndScroll/useGrabAndScroll.d.cts +2 -2
- package/dist/hooks/Intersection/index.cjs +3 -0
- package/dist/hooks/Intersection/index.d.cts +2 -2
- package/dist/hooks/Intersection/index.d.ts +2 -2
- package/dist/hooks/Intersection/index.js +2 -2
- package/dist/hooks/Intersection/useIntersection.cjs +48 -26
- package/dist/hooks/Intersection/useIntersection.d.cts +6 -3
- package/dist/hooks/Intersection/useIntersection.d.ts +6 -3
- package/dist/hooks/Intersection/useIntersection.js +46 -27
- package/dist/hooks/SystemSettingsContext/useSystemSettingsContext.d.cts +2 -2
- package/dist/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.cjs +2 -2
- package/dist/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.js +2 -2
- package/dist/hooks/utils.d.cts +1 -1
- package/dist/hooks/utils.d.ts +1 -1
- package/package.json +1 -1
- package/src/contexts/typesV3.ts +7 -0
- package/src/hooks/Intersection/__tests__/useIntersection.test.ts +226 -1
- package/src/hooks/Intersection/useIntersection.ts +112 -20
- package/src/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.ts +3 -1
|
@@ -28,7 +28,7 @@ const safeNow = () => {
|
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
30
|
const useTrackComponentVisibleEvent = (element, eventProps, rootMargin = "0px", enabled = true) => {
|
|
31
|
-
const isVisible = require_useIntersection.useIntersection(element, rootMargin);
|
|
31
|
+
const isVisible = require_useIntersection.useIntersection(element, rootMargin, eventProps);
|
|
32
32
|
const hasTrackedEvent = (0, react.useRef)(false);
|
|
33
33
|
const { trackEvent } = require_amplitudeContext.useAmplitude();
|
|
34
34
|
const variantInfo = (0, jotai.useAtomValue)(require_variant.pageVariantInfoAtom);
|
|
@@ -78,4 +78,4 @@ const useTrackComponentVisibleEvent = (element, eventProps, rootMargin = "0px",
|
|
|
78
78
|
|
|
79
79
|
//#endregion
|
|
80
80
|
exports.useTrackComponentVisibleEvent = useTrackComponentVisibleEvent;
|
|
81
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQuY2pzIiwibmFtZXMiOlsiTG9nZ2VyIiwidXNlSW50ZXJzZWN0aW9uIiwidXNlQW1wbGl0dWRlIiwicGFnZVZhcmlhbnRJbmZvQXRvbSIsIlNwaWZmeU1ldHJpY3NFdmVudE5hbWUiLCJFbnZpdmVNZXRyaWNzRXZlbnROYW1lIiwiZXh0cmFjdFBhZ2VDb250ZXh0Il0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2hvb2tzL1RyYWNrQ29tcG9uZW50VmlzaWJsZUV2ZW50L3VzZVRyYWNrQ29tcG9uZW50VmlzaWJsZUV2ZW50LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHVzZUF0b21WYWx1ZSB9IGZyb20gJ2pvdGFpJztcbmltcG9ydCB7IFJlZk9iamVjdCwgdXNlRWZmZWN0LCB1c2VSZWYgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgTG9nZ2VyIGZyb20gJ3NyYy9hcHBsaWNhdGlvbi9sb2dnaW5nL2xvZ2dlcic7XG5pbXBvcnQgeyBwYWdlVmFyaWFudEluZm9BdG9tIH0gZnJvbSAnc3JjL2F0b21zL2FwcCc7XG5pbXBvcnQgeyB1c2VBbXBsaXR1ZGUgfSBmcm9tICdzcmMvY29udGV4dHMvYW1wbGl0dWRlQ29udGV4dC9hbXBsaXR1ZGVDb250ZXh0JztcbmltcG9ydCB7IFBhZ2VWYXJpYW50SW5mbyB9IGZyb20gJ3NyYy9jb250ZXh0cy9wYWdlQ29udGV4dC90eXBlcyc7XG5pbXBvcnQgeyB1c2VJbnRlcnNlY3Rpb24gfSBmcm9tICdzcmMvaG9va3MvSW50ZXJzZWN0aW9uL3VzZUludGVyc2VjdGlvbic7XG5pbXBvcnQgeyBleHRyYWN0UGFnZUNvbnRleHQgfSBmcm9tICdzcmMvaG9va3MvV2lkZ2V0SW50ZXJhY3Rpb24vdXRpbHMnO1xuaW1wb3J0IHtcbiAgRW52aXZlTWV0cmljc0V2ZW50TmFtZSxcbiAgU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSxcbn0gZnJvbSAnc3JjL3NlcnZpY2VzL2FtcGxpdHVkZVNlcnZpY2UvYW1wbGl0dWRlU2VydmljZSc7XG5cbmNvbnN0IGxvZ2dlciA9IG5ldyBMb2dnZXIoJ3VzZVRyYWNrQ29tcG9uZW50VmlzaWJsZUV2ZW50Jyk7XG5cbi8qKlxuICogVHJhY2tzIGEgY29tcG9uZW50IGFuZCBsb2dzIGBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLkNoYXRDb21wb25lbnRWaXNpYmxlYCB3aGVuIHZpc2libGUuXG4gKlxuICogQHBhcmFtIGVsZW1lbnQgLSBUaGUgZWxlbWVudCB0byB0cmFjayB2aXNpYmlsaXR5IG9mLlxuICogQHBhcmFtIGV2ZW50UHJvcHMgLSBQcm9wZXJ0aWVzIHRvIGluY2x1ZGUgd2l0aCB0aGUgZXZlbnQuXG4gKiBAcGFyYW0gcm9vdE1hcmdpbiAtIFJvb3QgbWFyZ2luIGZvciB0aGUgaW50ZXJzZWN0aW9uIG9ic2VydmVyIChkZWZhdWx0cyB0byAwcHgpLlxuICogQHBhcmFtIGVuYWJsZWQgLSBXaGV0aGVyIHRyYWNraW5nIGlzIGVuYWJsZWQgKGRlZmF1bHRzIHRvIHRydWUpLlxuICovXG5jb25zdCBzYWZlTm93ID0gKCk6IG51bWJlciB8IHVuZGVmaW5lZCA9PiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93LnBlcmZvcm1hbmNlPy5ub3c/LigpIDogdW5kZWZpbmVkO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgdXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQgPSAoXG4gIGVsZW1lbnQ6IFJlZk9iamVjdDxIVE1MRWxlbWVudD4sXG4gIGV2ZW50UHJvcHM/
|
|
81
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQuY2pzIiwibmFtZXMiOlsiTG9nZ2VyIiwidXNlSW50ZXJzZWN0aW9uIiwidXNlQW1wbGl0dWRlIiwicGFnZVZhcmlhbnRJbmZvQXRvbSIsIlNwaWZmeU1ldHJpY3NFdmVudE5hbWUiLCJFbnZpdmVNZXRyaWNzRXZlbnROYW1lIiwiZXh0cmFjdFBhZ2VDb250ZXh0Il0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2hvb2tzL1RyYWNrQ29tcG9uZW50VmlzaWJsZUV2ZW50L3VzZVRyYWNrQ29tcG9uZW50VmlzaWJsZUV2ZW50LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHVzZUF0b21WYWx1ZSB9IGZyb20gJ2pvdGFpJztcbmltcG9ydCB7IFJlZk9iamVjdCwgdXNlRWZmZWN0LCB1c2VSZWYgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgTG9nZ2VyIGZyb20gJ3NyYy9hcHBsaWNhdGlvbi9sb2dnaW5nL2xvZ2dlcic7XG5pbXBvcnQgeyBwYWdlVmFyaWFudEluZm9BdG9tIH0gZnJvbSAnc3JjL2F0b21zL2FwcCc7XG5pbXBvcnQgeyB1c2VBbXBsaXR1ZGUgfSBmcm9tICdzcmMvY29udGV4dHMvYW1wbGl0dWRlQ29udGV4dC9hbXBsaXR1ZGVDb250ZXh0JztcbmltcG9ydCB7IFBhZ2VWYXJpYW50SW5mbyB9IGZyb20gJ3NyYy9jb250ZXh0cy9wYWdlQ29udGV4dC90eXBlcyc7XG5pbXBvcnQgeyB1c2VJbnRlcnNlY3Rpb24gfSBmcm9tICdzcmMvaG9va3MvSW50ZXJzZWN0aW9uL3VzZUludGVyc2VjdGlvbic7XG5pbXBvcnQgeyBleHRyYWN0UGFnZUNvbnRleHQgfSBmcm9tICdzcmMvaG9va3MvV2lkZ2V0SW50ZXJhY3Rpb24vdXRpbHMnO1xuaW1wb3J0IHtcbiAgRW52aXZlTWV0cmljc0V2ZW50TmFtZSxcbiAgU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSxcbn0gZnJvbSAnc3JjL3NlcnZpY2VzL2FtcGxpdHVkZVNlcnZpY2UvYW1wbGl0dWRlU2VydmljZSc7XG5cbmNvbnN0IGxvZ2dlciA9IG5ldyBMb2dnZXIoJ3VzZVRyYWNrQ29tcG9uZW50VmlzaWJsZUV2ZW50Jyk7XG5cbi8qKlxuICogVHJhY2tzIGEgY29tcG9uZW50IGFuZCBsb2dzIGBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLkNoYXRDb21wb25lbnRWaXNpYmxlYCB3aGVuIHZpc2libGUuXG4gKlxuICogQHBhcmFtIGVsZW1lbnQgLSBUaGUgZWxlbWVudCB0byB0cmFjayB2aXNpYmlsaXR5IG9mLlxuICogQHBhcmFtIGV2ZW50UHJvcHMgLSBQcm9wZXJ0aWVzIHRvIGluY2x1ZGUgd2l0aCB0aGUgZXZlbnQuXG4gKiBAcGFyYW0gcm9vdE1hcmdpbiAtIFJvb3QgbWFyZ2luIGZvciB0aGUgaW50ZXJzZWN0aW9uIG9ic2VydmVyIChkZWZhdWx0cyB0byAwcHgpLlxuICogQHBhcmFtIGVuYWJsZWQgLSBXaGV0aGVyIHRyYWNraW5nIGlzIGVuYWJsZWQgKGRlZmF1bHRzIHRvIHRydWUpLlxuICovXG5jb25zdCBzYWZlTm93ID0gKCk6IG51bWJlciB8IHVuZGVmaW5lZCA9PiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93LnBlcmZvcm1hbmNlPy5ub3c/LigpIDogdW5kZWZpbmVkO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgdXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQgPSAoXG4gIGVsZW1lbnQ6IFJlZk9iamVjdDxIVE1MRWxlbWVudD4sXG4gIGV2ZW50UHJvcHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgcm9vdE1hcmdpbjogc3RyaW5nID0gJzBweCcsXG4gIGVuYWJsZWQ6IGJvb2xlYW4gPSB0cnVlLFxuKTogeyBpc1Zpc2libGU6IGJvb2xlYW4gfSA9PiB7XG4gIC8vIGV2ZW50UHJvcHMgKHdpZGdldF9jb25maWdfaWQsIHdpZGdldF90eXBlLCDigKYpIGRvdWJsZSBhcyBsb2cgY29udGV4dCBzbyB0aGUgaG9vaydzXG4gIC8vIHZpc2liaWxpdHktZmFsbGJhY2sgZXJyb3IgaWRlbnRpZmllcyB3aGljaCB3aWRnZXQgaXQgcmVzY3VlZC5cbiAgY29uc3QgaXNWaXNpYmxlID0gdXNlSW50ZXJzZWN0aW9uKGVsZW1lbnQsIHJvb3RNYXJnaW4sIGV2ZW50UHJvcHMpO1xuICBjb25zdCBoYXNUcmFja2VkRXZlbnQgPSB1c2VSZWYoZmFsc2UpO1xuICBjb25zdCB7IHRyYWNrRXZlbnQgfSA9IHVzZUFtcGxpdHVkZSgpO1xuICBjb25zdCB2YXJpYW50SW5mbyA9IHVzZUF0b21WYWx1ZShwYWdlVmFyaWFudEluZm9BdG9tKTtcbiAgLy8gQ2FwdHVyZWQgb24gZmlyc3QgcmVuZGVyLCBub3Qgd2hlbiB0aGUgZXZlbnQgZmlyZXM6IFdpZGdldCBSZW5kZXJlZCBpc1xuICAvLyBlbWl0dGVkIGF0IHZpc2liaWxpdHksIHdoaWNoIGZvciBiZWxvdy10aGUtZm9sZCB3aWRnZXRzIGNhbiBiZSBsb25nXG4gIC8vIGFmdGVyIHRoZSB3aWRnZXQgYWN0dWFsbHkgcmVuZGVyZWQuIHBlcmZvcm1hbmNlLm5vdygpIGlzIHJlbGF0aXZlIHRvXG4gIC8vIG5hdmlnYXRpb24gc3RhcnQsIHNvIHRoaXMgcmVhZHMgYXMgXCJtcyBmcm9tIGluaXRpYWwgcGFnZSBsb2FkIHRvXG4gIC8vIHdpZGdldCByZW5kZXJcIi5cbiAgY29uc3QgcmVuZGVyT2Zmc2V0TXMgPSB1c2VSZWYoc2FmZU5vdygpKS5jdXJyZW50O1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgbG9nZ2VyLmxvZ0RlYnVnKCdlZmZlY3QgcmFuJywge1xuICAgICAgZW5hYmxlZCxcbiAgICAgIGlzVmlzaWJsZSxcbiAgICAgIGhhc1RyYWNrZWRFdmVudDogaGFzVHJhY2tlZEV2ZW50LmN1cnJlbnQsXG4gICAgICBldmVudFByb3BzLFxuICAgIH0pO1xuXG4gICAgaWYgKCFlbmFibGVkKSB7XG4gICAgICBsb2dnZXIubG9nRGVidWcoJ3NraXBwZWQg4oCUIGVuYWJsZWQgaXMgZmFsc2UnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGhhc1RyYWNrZWRFdmVudC5jdXJyZW50KSB7XG4gICAgICBsb2dnZXIubG9nRGVidWcoJ3NraXBwZWQg4oCUIGV2ZW50IGFscmVhZHkgdHJhY2tlZCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIWlzVmlzaWJsZSkge1xuICAgICAgbG9nZ2VyLmxvZ0RlYnVnKCdza2lwcGVkIOKAlCBlbGVtZW50IG5vdCB2aXNpYmxlJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbG9nZ2VyLmxvZ0RlYnVnKCdmaXJpbmcgdHJhY2tpbmcgZXZlbnRzJywgZXZlbnRQcm9wcyk7XG4gICAgdHJhY2tFdmVudCh7XG4gICAgICBldmVudE5hbWU6IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUuQ2hhdENvbXBvbmVudFZpc2libGUsXG4gICAgICBldmVudFByb3BzLFxuICAgIH0pO1xuICAgIHRyYWNrRXZlbnQoe1xuICAgICAgZXZlbnROYW1lOiBFbnZpdmVNZXRyaWNzRXZlbnROYW1lLldpZGdldFJlbmRlcmVkLFxuICAgICAgZXZlbnRQcm9wczoge1xuICAgICAgICAuLi5ldmVudFByb3BzLFxuICAgICAgICB0cmlnZ2VyOiB7XG4gICAgICAgICAgd2lkZ2V0OiBldmVudFByb3BzPy53aWRnZXRfdHlwZSxcbiAgICAgICAgfSxcbiAgICAgICAgY29udGV4dDogdmFyaWFudEluZm8gPyBleHRyYWN0UGFnZUNvbnRleHQodmFyaWFudEluZm8gYXMgUGFnZVZhcmlhbnRJbmZvKSA6IG51bGwsXG4gICAgICAgICdwZXJmb3JtYW5jZS5yZW5kZXJfb2Zmc2V0X21zJzogcmVuZGVyT2Zmc2V0TXMsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIGhhc1RyYWNrZWRFdmVudC5jdXJyZW50ID0gdHJ1ZTtcbiAgfSwgW2VuYWJsZWQsIGlzVmlzaWJsZSwgZXZlbnRQcm9wcywgdHJhY2tFdmVudF0pO1xuICByZXR1cm4geyBpc1Zpc2libGUgfTtcbn07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFhQSxNQUFNLFNBQVMsSUFBSUEsdUJBQU8sZ0NBQWdDOzs7Ozs7Ozs7QUFVMUQsTUFBTSxnQkFBb0M7QUFDeEMsS0FBSTtBQUNGLFNBQU8sT0FBTyxXQUFXLGNBQWMsT0FBTyxhQUFhLE9BQU8sR0FBRztTQUMvRDtBQUNOOzs7QUFJSixNQUFhLGlDQUNYLFNBQ0EsWUFDQSxhQUFxQixPQUNyQixVQUFtQixTQUNRO0NBRzNCLE1BQU0sWUFBWUMsd0NBQWdCLFNBQVMsWUFBWSxXQUFXO0NBQ2xFLE1BQU0sb0NBQXlCLE1BQU07Q0FDckMsTUFBTSxFQUFFLGVBQWVDLHVDQUFjO0NBQ3JDLE1BQU0sc0NBQTJCQyxvQ0FBb0I7Q0FNckQsTUFBTSxtQ0FBd0IsU0FBUyxDQUFDLENBQUM7QUFFekMsNEJBQWdCO0FBQ2QsU0FBTyxTQUFTLGNBQWM7R0FDNUI7R0FDQTtHQUNBLGlCQUFpQixnQkFBZ0I7R0FDakM7R0FDRCxDQUFDO0FBRUYsTUFBSSxDQUFDLFNBQVM7QUFDWixVQUFPLFNBQVMsNkJBQTZCO0FBQzdDOztBQUVGLE1BQUksZ0JBQWdCLFNBQVM7QUFDM0IsVUFBTyxTQUFTLGtDQUFrQztBQUNsRDs7QUFFRixNQUFJLENBQUMsV0FBVztBQUNkLFVBQU8sU0FBUyxnQ0FBZ0M7QUFDaEQ7O0FBR0YsU0FBTyxTQUFTLDBCQUEwQixXQUFXO0FBQ3JELGFBQVc7R0FDVCxXQUFXQywwQ0FBdUI7R0FDbEM7R0FDRCxDQUFDO0FBQ0YsYUFBVztHQUNULFdBQVdDLDBDQUF1QjtHQUNsQyxZQUFZO0lBQ1YsR0FBRztJQUNILFNBQVMsRUFDUCxRQUFRLFlBQVksYUFDckI7SUFDRCxTQUFTLGNBQWNDLHlEQUFtQixZQUErQixHQUFHO0lBQzVFLGdDQUFnQztJQUNqQztHQUNGLENBQUM7QUFDRixrQkFBZ0IsVUFBVTtJQUN6QjtFQUFDO0VBQVM7RUFBVztFQUFZO0VBQVcsQ0FBQztBQUNoRCxRQUFPLEVBQUUsV0FBVyJ9
|
|
@@ -27,7 +27,7 @@ const safeNow = () => {
|
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
const useTrackComponentVisibleEvent = (element, eventProps, rootMargin = "0px", enabled = true) => {
|
|
30
|
-
const isVisible = useIntersection(element, rootMargin);
|
|
30
|
+
const isVisible = useIntersection(element, rootMargin, eventProps);
|
|
31
31
|
const hasTrackedEvent = useRef(false);
|
|
32
32
|
const { trackEvent } = useAmplitude();
|
|
33
33
|
const variantInfo = useAtomValue(pageVariantInfoAtom);
|
|
@@ -77,4 +77,4 @@ const useTrackComponentVisibleEvent = (element, eventProps, rootMargin = "0px",
|
|
|
77
77
|
|
|
78
78
|
//#endregion
|
|
79
79
|
export { useTrackComponentVisibleEvent };
|
|
80
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQuanMiLCJuYW1lcyI6WyJMb2dnZXIiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaG9va3MvVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQvdXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdXNlQXRvbVZhbHVlIH0gZnJvbSAnam90YWknO1xuaW1wb3J0IHsgUmVmT2JqZWN0LCB1c2VFZmZlY3QsIHVzZVJlZiB9IGZyb20gJ3JlYWN0JztcbmltcG9ydCBMb2dnZXIgZnJvbSAnc3JjL2FwcGxpY2F0aW9uL2xvZ2dpbmcvbG9nZ2VyJztcbmltcG9ydCB7IHBhZ2VWYXJpYW50SW5mb0F0b20gfSBmcm9tICdzcmMvYXRvbXMvYXBwJztcbmltcG9ydCB7IHVzZUFtcGxpdHVkZSB9IGZyb20gJ3NyYy9jb250ZXh0cy9hbXBsaXR1ZGVDb250ZXh0L2FtcGxpdHVkZUNvbnRleHQnO1xuaW1wb3J0IHsgUGFnZVZhcmlhbnRJbmZvIH0gZnJvbSAnc3JjL2NvbnRleHRzL3BhZ2VDb250ZXh0L3R5cGVzJztcbmltcG9ydCB7IHVzZUludGVyc2VjdGlvbiB9IGZyb20gJ3NyYy9ob29rcy9JbnRlcnNlY3Rpb24vdXNlSW50ZXJzZWN0aW9uJztcbmltcG9ydCB7IGV4dHJhY3RQYWdlQ29udGV4dCB9IGZyb20gJ3NyYy9ob29rcy9XaWRnZXRJbnRlcmFjdGlvbi91dGlscyc7XG5pbXBvcnQge1xuICBFbnZpdmVNZXRyaWNzRXZlbnROYW1lLFxuICBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLFxufSBmcm9tICdzcmMvc2VydmljZXMvYW1wbGl0dWRlU2VydmljZS9hbXBsaXR1ZGVTZXJ2aWNlJztcblxuY29uc3QgbG9nZ2VyID0gbmV3IExvZ2dlcigndXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQnKTtcblxuLyoqXG4gKiBUcmFja3MgYSBjb21wb25lbnQgYW5kIGxvZ3MgYFNwaWZmeU1ldHJpY3NFdmVudE5hbWUuQ2hhdENvbXBvbmVudFZpc2libGVgIHdoZW4gdmlzaWJsZS5cbiAqXG4gKiBAcGFyYW0gZWxlbWVudCAtIFRoZSBlbGVtZW50IHRvIHRyYWNrIHZpc2liaWxpdHkgb2YuXG4gKiBAcGFyYW0gZXZlbnRQcm9wcyAtIFByb3BlcnRpZXMgdG8gaW5jbHVkZSB3aXRoIHRoZSBldmVudC5cbiAqIEBwYXJhbSByb290TWFyZ2luIC0gUm9vdCBtYXJnaW4gZm9yIHRoZSBpbnRlcnNlY3Rpb24gb2JzZXJ2ZXIgKGRlZmF1bHRzIHRvIDBweCkuXG4gKiBAcGFyYW0gZW5hYmxlZCAtIFdoZXRoZXIgdHJhY2tpbmcgaXMgZW5hYmxlZCAoZGVmYXVsdHMgdG8gdHJ1ZSkuXG4gKi9cbmNvbnN0IHNhZmVOb3cgPSAoKTogbnVtYmVyIHwgdW5kZWZpbmVkID0+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cucGVyZm9ybWFuY2U/Lm5vdz8uKCkgOiB1bmRlZmluZWQ7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCB1c2VUcmFja0NvbXBvbmVudFZpc2libGVFdmVudCA9IChcbiAgZWxlbWVudDogUmVmT2JqZWN0PEhUTUxFbGVtZW50PixcbiAgZXZlbnRQcm9wcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICByb290TWFyZ2luOiBzdHJpbmcgPSAnMHB4JyxcbiAgZW5hYmxlZDogYm9vbGVhbiA9IHRydWUsXG4pOiB7IGlzVmlzaWJsZTogYm9vbGVhbiB9ID0+
|
|
80
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQuanMiLCJuYW1lcyI6WyJMb2dnZXIiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaG9va3MvVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQvdXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdXNlQXRvbVZhbHVlIH0gZnJvbSAnam90YWknO1xuaW1wb3J0IHsgUmVmT2JqZWN0LCB1c2VFZmZlY3QsIHVzZVJlZiB9IGZyb20gJ3JlYWN0JztcbmltcG9ydCBMb2dnZXIgZnJvbSAnc3JjL2FwcGxpY2F0aW9uL2xvZ2dpbmcvbG9nZ2VyJztcbmltcG9ydCB7IHBhZ2VWYXJpYW50SW5mb0F0b20gfSBmcm9tICdzcmMvYXRvbXMvYXBwJztcbmltcG9ydCB7IHVzZUFtcGxpdHVkZSB9IGZyb20gJ3NyYy9jb250ZXh0cy9hbXBsaXR1ZGVDb250ZXh0L2FtcGxpdHVkZUNvbnRleHQnO1xuaW1wb3J0IHsgUGFnZVZhcmlhbnRJbmZvIH0gZnJvbSAnc3JjL2NvbnRleHRzL3BhZ2VDb250ZXh0L3R5cGVzJztcbmltcG9ydCB7IHVzZUludGVyc2VjdGlvbiB9IGZyb20gJ3NyYy9ob29rcy9JbnRlcnNlY3Rpb24vdXNlSW50ZXJzZWN0aW9uJztcbmltcG9ydCB7IGV4dHJhY3RQYWdlQ29udGV4dCB9IGZyb20gJ3NyYy9ob29rcy9XaWRnZXRJbnRlcmFjdGlvbi91dGlscyc7XG5pbXBvcnQge1xuICBFbnZpdmVNZXRyaWNzRXZlbnROYW1lLFxuICBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLFxufSBmcm9tICdzcmMvc2VydmljZXMvYW1wbGl0dWRlU2VydmljZS9hbXBsaXR1ZGVTZXJ2aWNlJztcblxuY29uc3QgbG9nZ2VyID0gbmV3IExvZ2dlcigndXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQnKTtcblxuLyoqXG4gKiBUcmFja3MgYSBjb21wb25lbnQgYW5kIGxvZ3MgYFNwaWZmeU1ldHJpY3NFdmVudE5hbWUuQ2hhdENvbXBvbmVudFZpc2libGVgIHdoZW4gdmlzaWJsZS5cbiAqXG4gKiBAcGFyYW0gZWxlbWVudCAtIFRoZSBlbGVtZW50IHRvIHRyYWNrIHZpc2liaWxpdHkgb2YuXG4gKiBAcGFyYW0gZXZlbnRQcm9wcyAtIFByb3BlcnRpZXMgdG8gaW5jbHVkZSB3aXRoIHRoZSBldmVudC5cbiAqIEBwYXJhbSByb290TWFyZ2luIC0gUm9vdCBtYXJnaW4gZm9yIHRoZSBpbnRlcnNlY3Rpb24gb2JzZXJ2ZXIgKGRlZmF1bHRzIHRvIDBweCkuXG4gKiBAcGFyYW0gZW5hYmxlZCAtIFdoZXRoZXIgdHJhY2tpbmcgaXMgZW5hYmxlZCAoZGVmYXVsdHMgdG8gdHJ1ZSkuXG4gKi9cbmNvbnN0IHNhZmVOb3cgPSAoKTogbnVtYmVyIHwgdW5kZWZpbmVkID0+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cucGVyZm9ybWFuY2U/Lm5vdz8uKCkgOiB1bmRlZmluZWQ7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCB1c2VUcmFja0NvbXBvbmVudFZpc2libGVFdmVudCA9IChcbiAgZWxlbWVudDogUmVmT2JqZWN0PEhUTUxFbGVtZW50PixcbiAgZXZlbnRQcm9wcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICByb290TWFyZ2luOiBzdHJpbmcgPSAnMHB4JyxcbiAgZW5hYmxlZDogYm9vbGVhbiA9IHRydWUsXG4pOiB7IGlzVmlzaWJsZTogYm9vbGVhbiB9ID0+IHtcbiAgLy8gZXZlbnRQcm9wcyAod2lkZ2V0X2NvbmZpZ19pZCwgd2lkZ2V0X3R5cGUsIOKApikgZG91YmxlIGFzIGxvZyBjb250ZXh0IHNvIHRoZSBob29rJ3NcbiAgLy8gdmlzaWJpbGl0eS1mYWxsYmFjayBlcnJvciBpZGVudGlmaWVzIHdoaWNoIHdpZGdldCBpdCByZXNjdWVkLlxuICBjb25zdCBpc1Zpc2libGUgPSB1c2VJbnRlcnNlY3Rpb24oZWxlbWVudCwgcm9vdE1hcmdpbiwgZXZlbnRQcm9wcyk7XG4gIGNvbnN0IGhhc1RyYWNrZWRFdmVudCA9IHVzZVJlZihmYWxzZSk7XG4gIGNvbnN0IHsgdHJhY2tFdmVudCB9ID0gdXNlQW1wbGl0dWRlKCk7XG4gIGNvbnN0IHZhcmlhbnRJbmZvID0gdXNlQXRvbVZhbHVlKHBhZ2VWYXJpYW50SW5mb0F0b20pO1xuICAvLyBDYXB0dXJlZCBvbiBmaXJzdCByZW5kZXIsIG5vdCB3aGVuIHRoZSBldmVudCBmaXJlczogV2lkZ2V0IFJlbmRlcmVkIGlzXG4gIC8vIGVtaXR0ZWQgYXQgdmlzaWJpbGl0eSwgd2hpY2ggZm9yIGJlbG93LXRoZS1mb2xkIHdpZGdldHMgY2FuIGJlIGxvbmdcbiAgLy8gYWZ0ZXIgdGhlIHdpZGdldCBhY3R1YWxseSByZW5kZXJlZC4gcGVyZm9ybWFuY2Uubm93KCkgaXMgcmVsYXRpdmUgdG9cbiAgLy8gbmF2aWdhdGlvbiBzdGFydCwgc28gdGhpcyByZWFkcyBhcyBcIm1zIGZyb20gaW5pdGlhbCBwYWdlIGxvYWQgdG9cbiAgLy8gd2lkZ2V0IHJlbmRlclwiLlxuICBjb25zdCByZW5kZXJPZmZzZXRNcyA9IHVzZVJlZihzYWZlTm93KCkpLmN1cnJlbnQ7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBsb2dnZXIubG9nRGVidWcoJ2VmZmVjdCByYW4nLCB7XG4gICAgICBlbmFibGVkLFxuICAgICAgaXNWaXNpYmxlLFxuICAgICAgaGFzVHJhY2tlZEV2ZW50OiBoYXNUcmFja2VkRXZlbnQuY3VycmVudCxcbiAgICAgIGV2ZW50UHJvcHMsXG4gICAgfSk7XG5cbiAgICBpZiAoIWVuYWJsZWQpIHtcbiAgICAgIGxvZ2dlci5sb2dEZWJ1Zygnc2tpcHBlZCDigJQgZW5hYmxlZCBpcyBmYWxzZScpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoaGFzVHJhY2tlZEV2ZW50LmN1cnJlbnQpIHtcbiAgICAgIGxvZ2dlci5sb2dEZWJ1Zygnc2tpcHBlZCDigJQgZXZlbnQgYWxyZWFkeSB0cmFja2VkJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghaXNWaXNpYmxlKSB7XG4gICAgICBsb2dnZXIubG9nRGVidWcoJ3NraXBwZWQg4oCUIGVsZW1lbnQgbm90IHZpc2libGUnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsb2dnZXIubG9nRGVidWcoJ2ZpcmluZyB0cmFja2luZyBldmVudHMnLCBldmVudFByb3BzKTtcbiAgICB0cmFja0V2ZW50KHtcbiAgICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5DaGF0Q29tcG9uZW50VmlzaWJsZSxcbiAgICAgIGV2ZW50UHJvcHMsXG4gICAgfSk7XG4gICAgdHJhY2tFdmVudCh7XG4gICAgICBldmVudE5hbWU6IEVudml2ZU1ldHJpY3NFdmVudE5hbWUuV2lkZ2V0UmVuZGVyZWQsXG4gICAgICBldmVudFByb3BzOiB7XG4gICAgICAgIC4uLmV2ZW50UHJvcHMsXG4gICAgICAgIHRyaWdnZXI6IHtcbiAgICAgICAgICB3aWRnZXQ6IGV2ZW50UHJvcHM/LndpZGdldF90eXBlLFxuICAgICAgICB9LFxuICAgICAgICBjb250ZXh0OiB2YXJpYW50SW5mbyA/IGV4dHJhY3RQYWdlQ29udGV4dCh2YXJpYW50SW5mbyBhcyBQYWdlVmFyaWFudEluZm8pIDogbnVsbCxcbiAgICAgICAgJ3BlcmZvcm1hbmNlLnJlbmRlcl9vZmZzZXRfbXMnOiByZW5kZXJPZmZzZXRNcyxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgaGFzVHJhY2tlZEV2ZW50LmN1cnJlbnQgPSB0cnVlO1xuICB9LCBbZW5hYmxlZCwgaXNWaXNpYmxlLCBldmVudFByb3BzLCB0cmFja0V2ZW50XSk7XG4gIHJldHVybiB7IGlzVmlzaWJsZSB9O1xufTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBYUEsTUFBTSxTQUFTLElBQUlBLGVBQU8sZ0NBQWdDOzs7Ozs7Ozs7QUFVMUQsTUFBTSxnQkFBb0M7QUFDeEMsS0FBSTtBQUNGLFNBQU8sT0FBTyxXQUFXLGNBQWMsT0FBTyxhQUFhLE9BQU8sR0FBRztTQUMvRDtBQUNOOzs7QUFJSixNQUFhLGlDQUNYLFNBQ0EsWUFDQSxhQUFxQixPQUNyQixVQUFtQixTQUNRO0NBRzNCLE1BQU0sWUFBWSxnQkFBZ0IsU0FBUyxZQUFZLFdBQVc7Q0FDbEUsTUFBTSxrQkFBa0IsT0FBTyxNQUFNO0NBQ3JDLE1BQU0sRUFBRSxlQUFlLGNBQWM7Q0FDckMsTUFBTSxjQUFjLGFBQWEsb0JBQW9CO0NBTXJELE1BQU0saUJBQWlCLE9BQU8sU0FBUyxDQUFDLENBQUM7QUFFekMsaUJBQWdCO0FBQ2QsU0FBTyxTQUFTLGNBQWM7R0FDNUI7R0FDQTtHQUNBLGlCQUFpQixnQkFBZ0I7R0FDakM7R0FDRCxDQUFDO0FBRUYsTUFBSSxDQUFDLFNBQVM7QUFDWixVQUFPLFNBQVMsNkJBQTZCO0FBQzdDOztBQUVGLE1BQUksZ0JBQWdCLFNBQVM7QUFDM0IsVUFBTyxTQUFTLGtDQUFrQztBQUNsRDs7QUFFRixNQUFJLENBQUMsV0FBVztBQUNkLFVBQU8sU0FBUyxnQ0FBZ0M7QUFDaEQ7O0FBR0YsU0FBTyxTQUFTLDBCQUEwQixXQUFXO0FBQ3JELGFBQVc7R0FDVCxXQUFXLHVCQUF1QjtHQUNsQztHQUNELENBQUM7QUFDRixhQUFXO0dBQ1QsV0FBVyx1QkFBdUI7R0FDbEMsWUFBWTtJQUNWLEdBQUc7SUFDSCxTQUFTLEVBQ1AsUUFBUSxZQUFZLGFBQ3JCO0lBQ0QsU0FBUyxjQUFjLG1CQUFtQixZQUErQixHQUFHO0lBQzVFLGdDQUFnQztJQUNqQztHQUNGLENBQUM7QUFDRixrQkFBZ0IsVUFBVTtJQUN6QjtFQUFDO0VBQVM7RUFBVztFQUFZO0VBQVcsQ0FBQztBQUNoRCxRQUFPLEVBQUUsV0FBVyJ9
|
package/dist/hooks/utils.d.cts
CHANGED
|
@@ -19,4 +19,4 @@ declare enum SearchResultsState {
|
|
|
19
19
|
declare const getSearchResultsState: (isLoadingSearch: boolean, searchData: SearchResult | null) => SearchResultsState;
|
|
20
20
|
//#endregion
|
|
21
21
|
export { SearchResultsState, createAppLoadedEvent, createVisitUserEvent, getSearchResultsState, isElementPartiallyVisible, isWithinBusinessHours };
|
|
22
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
22
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC5jdHMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2hvb2tzL3V0aWxzLmQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU2VhcmNoUmVzdWx0IH0gZnJvbSAnc3JjL2FwcGxpY2F0aW9uL21vZGVscy9hcGkvc2VhcmNoJztcbmltcG9ydCB7IFVzZXJFdmVudCwgVmFyaWFudEluZm8gfSBmcm9tICdzcmMvYXBwbGljYXRpb24vbW9kZWxzJztcbmV4cG9ydCBkZWNsYXJlIGNvbnN0IGlzRWxlbWVudFBhcnRpYWxseVZpc2libGU6IChlbD86IEhUTUxEaXZFbGVtZW50IHwgbnVsbCkgPT4gYm9vbGVhbjtcbmV4cG9ydCBkZWNsYXJlIGNvbnN0IGNyZWF0ZUFwcExvYWRlZEV2ZW50OiAoKSA9PiBVc2VyRXZlbnQ7XG5leHBvcnQgZGVjbGFyZSBjb25zdCBjcmVhdGVWaXNpdFVzZXJFdmVudDogKHsgdmFyaWFudEluZm8sIH06IHtcbiAgICB2YXJpYW50SW5mbzogVmFyaWFudEluZm87XG59KSA9PiBVc2VyRXZlbnQgfCB1bmRlZmluZWQ7XG5leHBvcnQgZGVjbGFyZSBjb25zdCBpc1dpdGhpbkJ1c2luZXNzSG91cnM6IChzdGFydFRpbWU6IHN0cmluZywgZW5kVGltZTogc3RyaW5nLCB0aW1lWm9uZTogc3RyaW5nKSA9PiBib29sZWFuO1xuZXhwb3J0IGRlY2xhcmUgZW51bSBTZWFyY2hSZXN1bHRzU3RhdGUge1xuICAgIExvYWRpbmcgPSAwLFxuICAgIFJlc3VsdHMgPSAxLFxuICAgIE5vUmVzdWx0cyA9IDJcbn1cbmV4cG9ydCBkZWNsYXJlIGNvbnN0IGdldFNlYXJjaFJlc3VsdHNTdGF0ZTogKGlzTG9hZGluZ1NlYXJjaDogYm9vbGVhbiwgc2VhcmNoRGF0YTogU2VhcmNoUmVzdWx0IHwgbnVsbCkgPT4gU2VhcmNoUmVzdWx0c1N0YXRlO1xuIl0sIm1hcHBpbmdzIjoiOzs7OztBQUVBLElBQVcsNEJBQTRCLENBQUMsV0FBVyxlQUFlO0FBQ2xFLElBQVcsdUJBQXVCLENBQUMsV0FBVyxVQUFVO0FBQ3hELElBQVcsdUJBQXVCO0NBQUM7T0FBVztPQUFnQjtPQUFBO0NBQUE7QUFDOUQsSUFBVyx3QkFBaUIsQ0FBQSxJQUFBO0FBQzVCLElBQVcscUJBQWdCLENBQUEsSUFBQTtBQUMzQixJQUFXLHdCQUF3QjtDQUFDO09BQVc7T0FBb0I7Q0FBbUIifQ==
|
package/dist/hooks/utils.d.ts
CHANGED
|
@@ -19,4 +19,4 @@ declare enum SearchResultsState {
|
|
|
19
19
|
declare const getSearchResultsState: (isLoadingSearch: boolean, searchData: SearchResult | null) => SearchResultsState;
|
|
20
20
|
//#endregion
|
|
21
21
|
export { SearchResultsState, createAppLoadedEvent, createVisitUserEvent, getSearchResultsState, isElementPartiallyVisible, isWithinBusinessHours };
|
|
22
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi9zcmMvaG9va3MvdXRpbHMuZC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTZWFyY2hSZXN1bHQgfSBmcm9tICdzcmMvYXBwbGljYXRpb24vbW9kZWxzL2FwaS9zZWFyY2gnO1xuaW1wb3J0IHsgVXNlckV2ZW50LCBWYXJpYW50SW5mbyB9IGZyb20gJ3NyYy9hcHBsaWNhdGlvbi9tb2RlbHMnO1xuZXhwb3J0IGRlY2xhcmUgY29uc3QgaXNFbGVtZW50UGFydGlhbGx5VmlzaWJsZTogKGVsPzogSFRNTERpdkVsZW1lbnQgfCBudWxsKSA9PiBib29sZWFuO1xuZXhwb3J0IGRlY2xhcmUgY29uc3QgY3JlYXRlQXBwTG9hZGVkRXZlbnQ6ICgpID0+IFVzZXJFdmVudDtcbmV4cG9ydCBkZWNsYXJlIGNvbnN0IGNyZWF0ZVZpc2l0VXNlckV2ZW50OiAoeyB2YXJpYW50SW5mbywgfToge1xuICAgIHZhcmlhbnRJbmZvOiBWYXJpYW50SW5mbztcbn0pID0+IFVzZXJFdmVudCB8IHVuZGVmaW5lZDtcbmV4cG9ydCBkZWNsYXJlIGNvbnN0IGlzV2l0aGluQnVzaW5lc3NIb3VyczogKHN0YXJ0VGltZTogc3RyaW5nLCBlbmRUaW1lOiBzdHJpbmcsIHRpbWVab25lOiBzdHJpbmcpID0+
|
|
22
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi9zcmMvaG9va3MvdXRpbHMuZC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTZWFyY2hSZXN1bHQgfSBmcm9tICdzcmMvYXBwbGljYXRpb24vbW9kZWxzL2FwaS9zZWFyY2gnO1xuaW1wb3J0IHsgVXNlckV2ZW50LCBWYXJpYW50SW5mbyB9IGZyb20gJ3NyYy9hcHBsaWNhdGlvbi9tb2RlbHMnO1xuZXhwb3J0IGRlY2xhcmUgY29uc3QgaXNFbGVtZW50UGFydGlhbGx5VmlzaWJsZTogKGVsPzogSFRNTERpdkVsZW1lbnQgfCBudWxsKSA9PiBib29sZWFuO1xuZXhwb3J0IGRlY2xhcmUgY29uc3QgY3JlYXRlQXBwTG9hZGVkRXZlbnQ6ICgpID0+IFVzZXJFdmVudDtcbmV4cG9ydCBkZWNsYXJlIGNvbnN0IGNyZWF0ZVZpc2l0VXNlckV2ZW50OiAoeyB2YXJpYW50SW5mbywgfToge1xuICAgIHZhcmlhbnRJbmZvOiBWYXJpYW50SW5mbztcbn0pID0+IFVzZXJFdmVudCB8IHVuZGVmaW5lZDtcbmV4cG9ydCBkZWNsYXJlIGNvbnN0IGlzV2l0aGluQnVzaW5lc3NIb3VyczogKHN0YXJ0VGltZTogc3RyaW5nLCBlbmRUaW1lOiBzdHJpbmcsIHRpbWVab25lOiBzdHJpbmcpID0+IGJvb2xlYW47XG5leHBvcnQgZGVjbGFyZSBlbnVtIFNlYXJjaFJlc3VsdHNTdGF0ZSB7XG4gICAgTG9hZGluZyA9IDAsXG4gICAgUmVzdWx0cyA9IDEsXG4gICAgTm9SZXN1bHRzID0gMlxufVxuZXhwb3J0IGRlY2xhcmUgY29uc3QgZ2V0U2VhcmNoUmVzdWx0c1N0YXRlOiAoaXNMb2FkaW5nU2VhcmNoOiBib29sZWFuLCBzZWFyY2hEYXRhOiBTZWFyY2hSZXN1bHQgfCBudWxsKSA9PiBTZWFyY2hSZXN1bHRzU3RhdGU7XG4iXSwibWFwcGluZ3MiOiI7Ozs7O0FBRUEsSUFBVyw0QkFBNEIsQ0FBQyxTQUFTLGVBQWU7QUFDaEUsSUFBVyx1QkFBdUIsQ0FBQyxTQUFTLFVBQVU7QUFDdEQsSUFBVyx1QkFBdUI7Q0FBQztPQUFTO09BQWtCO09BQUE7Q0FBQTtBQUM5RCxJQUFXLHdCQUFpQixDQUFBLEVBQUE7QUFDNUIsSUFBVyxxQkFBZ0IsQ0FBQSxFQUFBO0FBQzNCLElBQVcsd0JBQXdCO0NBQUM7T0FBUztPQUFvQjtDQUFtQiJ9
|
package/package.json
CHANGED
package/src/contexts/typesV3.ts
CHANGED
|
@@ -407,6 +407,13 @@ interface FullPageSalesAgentWidgetV3Config extends BaseWidgetConfig<WidgetTypeV3
|
|
|
407
407
|
chatBackgroundColor?: string;
|
|
408
408
|
suggestionButtonType?: PromptButtonVariant;
|
|
409
409
|
productCarouselLayout?: ProductCarouselLayoutV3;
|
|
410
|
+
/**
|
|
411
|
+
* When true (or unset), asking a question opens the conversation in a
|
|
412
|
+
* partial-height sheet that keeps the welcome overlay's product grid
|
|
413
|
+
* visible above it. Set to false to fall back to the full-screen takeover.
|
|
414
|
+
* Default true (undefined and true = partial view enabled).
|
|
415
|
+
*/
|
|
416
|
+
partialViewEnabled?: boolean;
|
|
410
417
|
}
|
|
411
418
|
|
|
412
419
|
type WidgetConfigV3 =
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { act, renderHook } from '@testing-library/react';
|
|
2
2
|
import { RefObject } from 'react';
|
|
3
|
-
import
|
|
3
|
+
import Logger from 'src/application/logging/logger';
|
|
4
|
+
import {
|
|
5
|
+
VISIBILITY_FALLBACK_GRACE_MS,
|
|
6
|
+
VISIBILITY_FALLBACK_INTERVAL_MS,
|
|
7
|
+
VISIBILITY_FOREGROUND_GRACE_MS,
|
|
8
|
+
useIntersection,
|
|
9
|
+
} from '../useIntersection';
|
|
4
10
|
|
|
5
11
|
class MockIntersectionObserver {
|
|
6
12
|
static instances: MockIntersectionObserver[] = [];
|
|
@@ -131,4 +137,223 @@ describe('useIntersection', () => {
|
|
|
131
137
|
|
|
132
138
|
expect(lastObserver().disconnected).toBe(true);
|
|
133
139
|
});
|
|
140
|
+
|
|
141
|
+
describe('visibility fallback', () => {
|
|
142
|
+
let logErrorSpy: ReturnType<typeof vi.spyOn>;
|
|
143
|
+
|
|
144
|
+
const rect = (partial: Partial<DOMRect>): DOMRect => {
|
|
145
|
+
const base = {
|
|
146
|
+
top: 0,
|
|
147
|
+
left: 0,
|
|
148
|
+
bottom: 0,
|
|
149
|
+
right: 0,
|
|
150
|
+
x: 0,
|
|
151
|
+
y: 0,
|
|
152
|
+
toJSON: () => ({}),
|
|
153
|
+
...partial,
|
|
154
|
+
};
|
|
155
|
+
// Derive area from the bounds like a real DOMRect, unless explicitly overridden, so
|
|
156
|
+
// the on-screen guard (width/height > 0) sees realistic geometry.
|
|
157
|
+
return {
|
|
158
|
+
...base,
|
|
159
|
+
width: partial.width ?? base.right - base.left,
|
|
160
|
+
height: partial.height ?? base.bottom - base.top,
|
|
161
|
+
} as DOMRect;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const connectedNode = (nodeRect: Partial<DOMRect>) => {
|
|
165
|
+
const node = document.createElement('span');
|
|
166
|
+
document.body.appendChild(node);
|
|
167
|
+
vi.spyOn(node, 'getBoundingClientRect').mockReturnValue(rect(nodeRect));
|
|
168
|
+
return node;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
beforeEach(() => {
|
|
172
|
+
vi.useFakeTimers();
|
|
173
|
+
logErrorSpy = vi.spyOn(Logger.prototype, 'logError').mockImplementation(() => {});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
afterEach(() => {
|
|
177
|
+
vi.useRealTimers();
|
|
178
|
+
logErrorSpy.mockRestore();
|
|
179
|
+
document.body.innerHTML = '';
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('reports visibility and logs an error when an on-screen element is never reported by the observer', () => {
|
|
183
|
+
const node = connectedNode({ top: 100, bottom: 300, left: 0, right: 200 });
|
|
184
|
+
const ref: RefObject<HTMLElement> = { current: node };
|
|
185
|
+
|
|
186
|
+
const { result } = renderHook(() =>
|
|
187
|
+
useIntersection(ref, '0px', { widget_type: 'ProductCardV3' }),
|
|
188
|
+
);
|
|
189
|
+
expect(result.current).toBe(false);
|
|
190
|
+
|
|
191
|
+
// First check happens after the grace window.
|
|
192
|
+
act(() => {
|
|
193
|
+
vi.advanceTimersByTime(VISIBILITY_FALLBACK_GRACE_MS);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
expect(result.current).toBe(true);
|
|
197
|
+
expect(logErrorSpy).toHaveBeenCalledTimes(1);
|
|
198
|
+
const [message, , context] = logErrorSpy.mock.calls[0];
|
|
199
|
+
expect(message).toContain('Visibility fallback engaged');
|
|
200
|
+
expect(context).toMatchObject({ widget_type: 'ProductCardV3' });
|
|
201
|
+
|
|
202
|
+
// Fires at most once — once visible, the reconciliation loop stops
|
|
203
|
+
act(() => {
|
|
204
|
+
vi.advanceTimersByTime(VISIBILITY_FALLBACK_INTERVAL_MS * 3);
|
|
205
|
+
});
|
|
206
|
+
expect(logErrorSpy).toHaveBeenCalledTimes(1);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('does not engage for an element that is genuinely off screen', () => {
|
|
210
|
+
const node = connectedNode({ top: 5000, bottom: 5200, left: 0, right: 200 });
|
|
211
|
+
const ref: RefObject<HTMLElement> = { current: node };
|
|
212
|
+
|
|
213
|
+
const { result } = renderHook(() => useIntersection(ref, '0px'));
|
|
214
|
+
|
|
215
|
+
act(() => {
|
|
216
|
+
vi.advanceTimersByTime(VISIBILITY_FALLBACK_GRACE_MS + VISIBILITY_FALLBACK_INTERVAL_MS * 4);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
expect(result.current).toBe(false);
|
|
220
|
+
expect(logErrorSpy).not.toHaveBeenCalled();
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('does not engage when the observer reports visibility first', () => {
|
|
224
|
+
const node = connectedNode({ top: 100, bottom: 300, left: 0, right: 200 });
|
|
225
|
+
const ref: RefObject<HTMLElement> = { current: node };
|
|
226
|
+
|
|
227
|
+
const { result } = renderHook(() => useIntersection(ref, '0px'));
|
|
228
|
+
act(() => {
|
|
229
|
+
lastObserver().fire(true, node);
|
|
230
|
+
});
|
|
231
|
+
expect(result.current).toBe(true);
|
|
232
|
+
|
|
233
|
+
act(() => {
|
|
234
|
+
vi.advanceTimersByTime(VISIBILITY_FALLBACK_GRACE_MS + VISIBILITY_FALLBACK_INTERVAL_MS * 4);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
expect(logErrorSpy).not.toHaveBeenCalled();
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('does not engage for a detached node', () => {
|
|
241
|
+
const node = document.createElement('span');
|
|
242
|
+
vi.spyOn(node, 'getBoundingClientRect').mockReturnValue(
|
|
243
|
+
rect({ top: 100, bottom: 300, left: 0, right: 200 }),
|
|
244
|
+
);
|
|
245
|
+
const ref: RefObject<HTMLElement> = { current: node };
|
|
246
|
+
|
|
247
|
+
const { result } = renderHook(() => useIntersection(ref, '0px'));
|
|
248
|
+
|
|
249
|
+
act(() => {
|
|
250
|
+
vi.advanceTimersByTime(VISIBILITY_FALLBACK_GRACE_MS + VISIBILITY_FALLBACK_INTERVAL_MS * 4);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
expect(result.current).toBe(false);
|
|
254
|
+
expect(logErrorSpy).not.toHaveBeenCalled();
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('recovers on foreground (visibilitychange) without waiting for the poll interval', () => {
|
|
258
|
+
const node = connectedNode({ top: 100, bottom: 300, left: 0, right: 200 });
|
|
259
|
+
const ref: RefObject<HTMLElement> = { current: node };
|
|
260
|
+
|
|
261
|
+
const { result } = renderHook(() =>
|
|
262
|
+
useIntersection(ref, '0px', { widget_type: 'ProductCardV3' }),
|
|
263
|
+
);
|
|
264
|
+
expect(result.current).toBe(false);
|
|
265
|
+
|
|
266
|
+
// Tab returns to foreground; the grace is far shorter than the poll interval.
|
|
267
|
+
act(() => {
|
|
268
|
+
document.dispatchEvent(new Event('visibilitychange'));
|
|
269
|
+
vi.advanceTimersByTime(VISIBILITY_FOREGROUND_GRACE_MS);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
expect(result.current).toBe(true);
|
|
273
|
+
expect(logErrorSpy).toHaveBeenCalledTimes(1);
|
|
274
|
+
expect(logErrorSpy.mock.calls[0][2]).toMatchObject({ widget_type: 'ProductCardV3' });
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('does not engage on foreground when the observer re-fires within the grace window', () => {
|
|
278
|
+
const node = connectedNode({ top: 100, bottom: 300, left: 0, right: 200 });
|
|
279
|
+
const ref: RefObject<HTMLElement> = { current: node };
|
|
280
|
+
|
|
281
|
+
const { result } = renderHook(() => useIntersection(ref, '0px'));
|
|
282
|
+
|
|
283
|
+
// Foreground schedules the grace check...
|
|
284
|
+
act(() => {
|
|
285
|
+
document.dispatchEvent(new Event('visibilitychange'));
|
|
286
|
+
});
|
|
287
|
+
// ...but a healthy observer re-fires first (in its own flush, as it would in the
|
|
288
|
+
// browser within a frame), flipping isVisible and tearing down the grace timer.
|
|
289
|
+
act(() => {
|
|
290
|
+
lastObserver().fire(true, node);
|
|
291
|
+
});
|
|
292
|
+
act(() => {
|
|
293
|
+
vi.advanceTimersByTime(VISIBILITY_FOREGROUND_GRACE_MS * 2);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
expect(result.current).toBe(true);
|
|
297
|
+
expect(logErrorSpy).not.toHaveBeenCalled();
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('does not engage on foreground while the document is still hidden', () => {
|
|
301
|
+
const node = connectedNode({ top: 100, bottom: 300, left: 0, right: 200 });
|
|
302
|
+
const ref: RefObject<HTMLElement> = { current: node };
|
|
303
|
+
const visibilitySpy = vi.spyOn(document, 'visibilityState', 'get').mockReturnValue('hidden');
|
|
304
|
+
|
|
305
|
+
const { result } = renderHook(() => useIntersection(ref, '0px'));
|
|
306
|
+
|
|
307
|
+
act(() => {
|
|
308
|
+
document.dispatchEvent(new Event('visibilitychange'));
|
|
309
|
+
vi.advanceTimersByTime(VISIBILITY_FOREGROUND_GRACE_MS);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
expect(result.current).toBe(false);
|
|
313
|
+
expect(logErrorSpy).not.toHaveBeenCalled();
|
|
314
|
+
visibilitySpy.mockRestore();
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('does not engage for a zero-area element within the viewport (unlaid-out / collapsed)', () => {
|
|
318
|
+
// An inline wrapper that has not laid out its content yet reports a zero-area rect at
|
|
319
|
+
// a viewport position. That is genuinely not-visible, not something the observer missed.
|
|
320
|
+
const node = connectedNode({ top: 100, bottom: 100, left: 50, right: 50 });
|
|
321
|
+
const ref: RefObject<HTMLElement> = { current: node };
|
|
322
|
+
|
|
323
|
+
const { result } = renderHook(() => useIntersection(ref, '0px'));
|
|
324
|
+
|
|
325
|
+
act(() => {
|
|
326
|
+
vi.advanceTimersByTime(VISIBILITY_FALLBACK_GRACE_MS + VISIBILITY_FALLBACK_INTERVAL_MS * 4);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
expect(result.current).toBe(false);
|
|
330
|
+
expect(logErrorSpy).not.toHaveBeenCalled();
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it('recovers a stuck on-screen element even while the document is hidden, but stays silent', () => {
|
|
334
|
+
// The environments this fallback exists for — iOS/WebKit in-app webviews and bfcache
|
|
335
|
+
// restores — can report the document as hidden while the shopper is actually looking at
|
|
336
|
+
// it, so recovery must NOT be gated on visibility (that was the CircleCI failure: a
|
|
337
|
+
// headless page reports non-visible and the widget never un-stuck). The error, however,
|
|
338
|
+
// is only a genuine signal when the page is visible — a suppressed observer in a real
|
|
339
|
+
// background tab is expected, not a bug — so it must not fire here and flood telemetry.
|
|
340
|
+
const node = connectedNode({ top: 100, bottom: 300, left: 0, right: 200 });
|
|
341
|
+
const ref: RefObject<HTMLElement> = { current: node };
|
|
342
|
+
const visibilitySpy = vi
|
|
343
|
+
.spyOn(document, 'visibilityState', 'get')
|
|
344
|
+
.mockReturnValue('hidden');
|
|
345
|
+
|
|
346
|
+
const { result } = renderHook(() =>
|
|
347
|
+
useIntersection(ref, '0px', { widget_type: 'ProductCardV3' }),
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
act(() => {
|
|
351
|
+
vi.advanceTimersByTime(VISIBILITY_FALLBACK_GRACE_MS);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
expect(result.current).toBe(true); // recovered despite being "hidden"
|
|
355
|
+
expect(logErrorSpy).not.toHaveBeenCalled(); // but no false-positive error logged
|
|
356
|
+
visibilitySpy.mockRestore();
|
|
357
|
+
});
|
|
358
|
+
});
|
|
134
359
|
});
|
|
@@ -3,11 +3,49 @@ import Logger from 'src/application/logging/logger';
|
|
|
3
3
|
|
|
4
4
|
const logger = new Logger('useIntersection');
|
|
5
5
|
|
|
6
|
+
// How long to wait before the fallback's FIRST reconcile. Long enough that a healthy
|
|
7
|
+
// IntersectionObserver has delivered its initial callback (so we don't falsely flag a
|
|
8
|
+
// normally-loading widget), short enough to keep the worst-case blank window small.
|
|
9
|
+
// Exported for tests.
|
|
10
|
+
export const VISIBILITY_FALLBACK_GRACE_MS = 1000;
|
|
11
|
+
|
|
12
|
+
// How often the fallback re-checks after the initial grace. A genuinely stuck widget
|
|
13
|
+
// recovers within grace + one interval (~1.3s). Exported for tests.
|
|
14
|
+
export const VISIBILITY_FALLBACK_INTERVAL_MS = 300;
|
|
15
|
+
|
|
16
|
+
// After the tab returns to the foreground, how long to wait before the fast-path reconcile —
|
|
17
|
+
// long enough for a healthy observer to re-fire on its own (so we don't falsely flag it),
|
|
18
|
+
// short enough that recovery is near-instant. Exported for tests.
|
|
19
|
+
export const VISIBILITY_FOREGROUND_GRACE_MS = 200;
|
|
20
|
+
|
|
21
|
+
const isOnScreen = (node: HTMLElement): boolean => {
|
|
22
|
+
const rect = node.getBoundingClientRect();
|
|
23
|
+
// Require real area: an element that has not laid out yet (a 0×0 inline wrapper mid-mount)
|
|
24
|
+
// or is collapsed to zero by an overflow-clipping ancestor is not something the observer
|
|
25
|
+
// wrongly missed — it is genuinely not visible. display:none subtrees report an all-zero
|
|
26
|
+
// rect and are excluded here too.
|
|
27
|
+
if (rect.width <= 0 || rect.height <= 0) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return (
|
|
31
|
+
rect.top < window.innerHeight &&
|
|
32
|
+
rect.bottom > 0 &&
|
|
33
|
+
rect.left < window.innerWidth &&
|
|
34
|
+
rect.right > 0
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
6
38
|
// https://rasilbaidar.medium.com/trigger-event-when-element-enters-viewport-the-react-way-168509da2e23
|
|
7
|
-
export const useIntersection = (
|
|
39
|
+
export const useIntersection = (
|
|
40
|
+
element: RefObject<HTMLElement>,
|
|
41
|
+
rootMargin: string,
|
|
42
|
+
logContext?: Record<string, unknown>,
|
|
43
|
+
) => {
|
|
8
44
|
const [isVisible, setIsVisible] = useState(false);
|
|
9
45
|
const observerRef = useRef<IntersectionObserver | null>(null);
|
|
10
46
|
const observedNodeRef = useRef<HTMLElement | null>(null);
|
|
47
|
+
const logContextRef = useRef(logContext);
|
|
48
|
+
logContextRef.current = logContext;
|
|
11
49
|
|
|
12
50
|
// Runs after every render so it catches when element.current transitions from null to a
|
|
13
51
|
// mounted DOM node, AND when the node under the ref is replaced. The replacement case is
|
|
@@ -18,35 +56,18 @@ export const useIntersection = (element: RefObject<HTMLElement>, rootMargin: str
|
|
|
18
56
|
// keeping per-render cost O(1).
|
|
19
57
|
useEffect(() => {
|
|
20
58
|
const current = element?.current;
|
|
21
|
-
logger.logDebug('effect ran', {
|
|
22
|
-
elementCurrent: current,
|
|
23
|
-
rootMargin,
|
|
24
|
-
alreadyObserving: !!observerRef.current,
|
|
25
|
-
observingCurrentNode: observedNodeRef.current === current,
|
|
26
|
-
});
|
|
27
|
-
|
|
28
59
|
if (!current) {
|
|
29
|
-
logger.logDebug('element.current is null — observer NOT attached');
|
|
30
60
|
return;
|
|
31
61
|
}
|
|
32
62
|
if (observedNodeRef.current === current) return; // already observing this exact node
|
|
33
63
|
|
|
34
64
|
if (observerRef.current) {
|
|
35
|
-
|
|
36
|
-
previousNode: observedNodeRef.current,
|
|
37
|
-
newNode: current,
|
|
38
|
-
});
|
|
65
|
+
// Node under the ref was replaced — drop the observer on the detached node.
|
|
39
66
|
observerRef.current.disconnect();
|
|
40
67
|
}
|
|
41
68
|
|
|
42
69
|
const observer = new IntersectionObserver(
|
|
43
70
|
([entry]) => {
|
|
44
|
-
logger.logDebug('IntersectionObserver fired', {
|
|
45
|
-
isIntersecting: entry.isIntersecting,
|
|
46
|
-
intersectionRatio: entry.intersectionRatio,
|
|
47
|
-
boundingClientRect: entry.boundingClientRect,
|
|
48
|
-
target: entry.target,
|
|
49
|
-
});
|
|
50
71
|
setIsVisible(entry.isIntersecting);
|
|
51
72
|
},
|
|
52
73
|
{ rootMargin },
|
|
@@ -55,9 +76,80 @@ export const useIntersection = (element: RefObject<HTMLElement>, rootMargin: str
|
|
|
55
76
|
observer.observe(current);
|
|
56
77
|
observerRef.current = observer;
|
|
57
78
|
observedNodeRef.current = current;
|
|
58
|
-
logger.logDebug('observer attached to element', current);
|
|
59
79
|
});
|
|
60
80
|
|
|
81
|
+
// Safety net: visibility detection must not be a single point of failure. While the
|
|
82
|
+
// observer reports not-visible, periodically reconcile against the element's actual
|
|
83
|
+
// position; an element that is on screen while the observer stayed silent means
|
|
84
|
+
// observation is broken for a reason we haven't met yet (wrapped/overridden
|
|
85
|
+
// IntersectionObserver, engine quirk, a failure mode like the stale-node bug). Report it
|
|
86
|
+
// as a console error (so session tools can count affected sessions) and treat the
|
|
87
|
+
// element as visible so it still loads.
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (isVisible) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const reconcile = () => {
|
|
94
|
+
const node = element?.current;
|
|
95
|
+
if (!node || !node.isConnected) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (isOnScreen(node)) {
|
|
99
|
+
// Recover the widget regardless of document.visibilityState. The environments this
|
|
100
|
+
// fallback exists for — iOS/WebKit in-app webviews and bfcache restores — can report
|
|
101
|
+
// the document as hidden even while the shopper is looking at it, so gating recovery
|
|
102
|
+
// on visibility would defeat the fix in exactly those cases. Only LOG a genuine
|
|
103
|
+
// failure when the page is actually visible, so a legitimately suppressed observer in
|
|
104
|
+
// a hidden/background tab does not flood error telemetry with false positives.
|
|
105
|
+
if (document.visibilityState === 'visible') {
|
|
106
|
+
logger.logError(
|
|
107
|
+
'Visibility fallback engaged — element is on screen but IntersectionObserver never reported it',
|
|
108
|
+
undefined,
|
|
109
|
+
{
|
|
110
|
+
...logContextRef.current,
|
|
111
|
+
fallback_interval_ms: VISIBILITY_FALLBACK_INTERVAL_MS,
|
|
112
|
+
},
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
setIsVisible(true);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Give the real observer a grace window to deliver its initial callback, then poll on a
|
|
120
|
+
// shorter cadence so a genuinely stuck widget recovers quickly.
|
|
121
|
+
let interval: ReturnType<typeof setInterval> | undefined;
|
|
122
|
+
const grace = setTimeout(() => {
|
|
123
|
+
reconcile();
|
|
124
|
+
interval = setInterval(reconcile, VISIBILITY_FALLBACK_INTERVAL_MS);
|
|
125
|
+
}, VISIBILITY_FALLBACK_GRACE_MS);
|
|
126
|
+
|
|
127
|
+
// Fast path: a widget composited while the tab was hidden can have its
|
|
128
|
+
// IntersectionObserver suppressed, and some engines fail to re-fire it when the tab
|
|
129
|
+
// returns to the foreground for an element already in the viewport. On visibility
|
|
130
|
+
// change, reconcile after a short grace — if a healthy observer re-fires first,
|
|
131
|
+
// isVisible flips and this effect tears the timer down before it runs.
|
|
132
|
+
let foregroundCheck: ReturnType<typeof setTimeout> | undefined;
|
|
133
|
+
const onVisibilityChange = () => {
|
|
134
|
+
if (document.visibilityState !== 'visible') {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
foregroundCheck = setTimeout(reconcile, VISIBILITY_FOREGROUND_GRACE_MS);
|
|
138
|
+
};
|
|
139
|
+
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
140
|
+
|
|
141
|
+
return () => {
|
|
142
|
+
clearTimeout(grace);
|
|
143
|
+
if (interval !== undefined) {
|
|
144
|
+
clearInterval(interval);
|
|
145
|
+
}
|
|
146
|
+
document.removeEventListener('visibilitychange', onVisibilityChange);
|
|
147
|
+
if (foregroundCheck !== undefined) {
|
|
148
|
+
clearTimeout(foregroundCheck);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}, [isVisible, element]);
|
|
152
|
+
|
|
61
153
|
// Disconnect on unmount only — intentionally separate from the setup effect above.
|
|
62
154
|
useEffect(() => {
|
|
63
155
|
return () => {
|
|
@@ -35,7 +35,9 @@ export const useTrackComponentVisibleEvent = (
|
|
|
35
35
|
rootMargin: string = '0px',
|
|
36
36
|
enabled: boolean = true,
|
|
37
37
|
): { isVisible: boolean } => {
|
|
38
|
-
|
|
38
|
+
// eventProps (widget_config_id, widget_type, …) double as log context so the hook's
|
|
39
|
+
// visibility-fallback error identifies which widget it rescued.
|
|
40
|
+
const isVisible = useIntersection(element, rootMargin, eventProps);
|
|
39
41
|
const hasTrackedEvent = useRef(false);
|
|
40
42
|
const { trackEvent } = useAmplitude();
|
|
41
43
|
const variantInfo = useAtomValue(pageVariantInfoAtom);
|