UNPKG

@atlaskit/renderer

Version:
89 lines (83 loc) 3.33 kB
import { useRef, useCallback } from 'react'; /** * Hook that provides functionality to wait for layout stability before performing an action. * Uses ResizeObserver to detect when a container has stopped resizing (e.g., images finished loading). */ export var useStableScroll = function useStableScroll() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var _options$stabilityWai = options.stabilityWaitTime, stabilityWaitTime = _options$stabilityWai === void 0 ? 200 : _options$stabilityWai, _options$maxStability = options.maxStabilityWaitTime, maxStabilityWaitTime = _options$maxStability === void 0 ? 10000 : _options$maxStability; var stabilityTimeoutRef = useRef(null); var resizeObserverRef = useRef(null); var lastStableTimeRef = useRef(0); var onStableCallbackRef = useRef(null); var cleanup = useCallback(function () { if (stabilityTimeoutRef.current) { clearTimeout(stabilityTimeoutRef.current); stabilityTimeoutRef.current = null; } if (resizeObserverRef.current) { resizeObserverRef.current.disconnect(); resizeObserverRef.current = null; } onStableCallbackRef.current = null; lastStableTimeRef.current = 0; }, []); var scheduleStabilityCheck = useCallback(function () { // Clear any existing stability timeout. if (stabilityTimeoutRef.current) { clearTimeout(stabilityTimeoutRef.current); stabilityTimeoutRef.current = null; } // Check if we've exceeded the maximum stability wait time. var now = Date.now(); if (lastStableTimeRef.current === 0) { lastStableTimeRef.current = now; } else if (now - lastStableTimeRef.current > maxStabilityWaitTime) { // We've waited too long for stability, call the callback now. if (onStableCallbackRef.current) { onStableCallbackRef.current(); cleanup(); } return; } // Set a timeout to call the callback after the stability wait time. stabilityTimeoutRef.current = setTimeout(function () { if (onStableCallbackRef.current) { onStableCallbackRef.current(); cleanup(); } }, stabilityWaitTime); }, [stabilityWaitTime, maxStabilityWaitTime, cleanup]); var waitForStability = useCallback(function (container, onStable) { // Clean up any existing observer cleanup(); // Store the callback onStableCallbackRef.current = onStable; // Check if ResizeObserver is available if (typeof ResizeObserver === 'undefined') { // Fallback: just call the callback after the stability wait time stabilityTimeoutRef.current = setTimeout(function () { if (onStableCallbackRef.current) { onStableCallbackRef.current(); cleanup(); } }, stabilityWaitTime); return; } // Create a ResizeObserver to monitor the container for size changes. resizeObserverRef.current = new ResizeObserver(function () { // Container size changed, reset stability timer. scheduleStabilityCheck(); }); resizeObserverRef.current.observe(container); // Start the initial stability check scheduleStabilityCheck(); }, [stabilityWaitTime, scheduleStabilityCheck, cleanup]); return { waitForStability: waitForStability, cleanup: cleanup }; };