@datalayer/core
Version:
[](https://datalayer.io)
45 lines (44 loc) • 1.7 kB
JavaScript
/*
* Copyright (c) 2023-2025 Datalayer, Inc.
* Distributed under the terms of the Modified BSD License.
*/
import { useCallback, useEffect, useState } from 'react';
/**
* Determine if a child element of the provided ref is currently focussed.
* @param containerRef The ref to the container element.
* @param onFocusChange The callback to be called when the focus state changes.
* @type T The type of the container element.
* @returns The ref to be applied to the container element.
*/
export const useContainsFocus = (containerRef, onFocusChange) => {
const [isChildFocused, setIsChildFocused] = useState(false);
const updateState = useCallback((isFocused) => {
if (isFocused !== isChildFocused) {
setIsChildFocused(isFocused);
onFocusChange?.(isFocused);
}
}, [isChildFocused, onFocusChange]);
useEffect(() => {
if (!containerRef) {
return;
}
const handleFocusIn = () => {
updateState(true);
};
const handleFocusOut = (event) => {
if (containerRef.current &&
!containerRef.current.contains(event.relatedTarget)) {
updateState(false);
}
};
const container = containerRef.current;
if (container) {
container.addEventListener('focusin', handleFocusIn, true);
container.addEventListener('focusout', handleFocusOut, true);
return () => {
container.removeEventListener('focusin', handleFocusIn, true);
container.removeEventListener('focusout', handleFocusOut, true);
};
}
}, [updateState, containerRef]);
};