/** @license MIT | @cube-dev/ui-kit v0.147.0 | Cube Dev Team */
import { useCallback, useEffect, useRef } from "react";

//#region src/components/fields/ListBoxPopover/useCompositeFocus.ts
/**
* Tracks focus across a wrapper element and its (portaled) popover as a single
* logical focus scope. Fires `onFocus` when focus enters either and `onBlur`
* when it leaves both — essential for components whose overlay is portaled, so
* that clicking an option does not look like a blur of the whole component.
*
* Focus checks are deferred to the next animation frame to tolerate the
* synchronous focus shuffles React Aria and portals perform on selection.
*/
function useCompositeFocus({ wrapperRef, popoverRef, onFocus, onBlur, isDisabled }) {
	const wasInsideRef = useRef(false);
	const rafRef = useRef(null);
	const checkFocus = useCallback(() => {
		if (isDisabled) return;
		const activeElement = document.activeElement;
		const isInside = (wrapperRef.current?.contains(activeElement) ?? false) || (popoverRef.current?.contains(activeElement) ?? false);
		if (isInside !== wasInsideRef.current) {
			wasInsideRef.current = isInside;
			if (isInside) onFocus?.();
			else onBlur?.();
		}
	}, [
		wrapperRef,
		popoverRef,
		onFocus,
		onBlur,
		isDisabled
	]);
	const handleFocusOrBlur = useCallback((e) => {
		if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
		rafRef.current = requestAnimationFrame(() => {
			rafRef.current = null;
			checkFocus();
		});
	}, [checkFocus]);
	useEffect(() => {
		return () => {
			if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
		};
	}, []);
	return { compositeFocusProps: {
		onFocus: handleFocusOrBlur,
		onBlur: handleFocusOrBlur
	} };
}

//#endregion
export { useCompositeFocus };
//# sourceMappingURL=useCompositeFocus.js.map