@nex-ui/hooks
Version:
A collection of React Hooks for Nex UI components.
75 lines (71 loc) • 2.11 kB
JavaScript
"use client";
;
var react = require('react');
function isFocusVisible(element) {
try {
return element.matches(':focus-visible');
} catch {
// Do not warn on jsdom tests, otherwise all tests that rely on focus have to be skipped
// Tests that rely on `:focus-visible` will still have to be skipped in jsdom
if (process.env.NODE_ENV !== 'production' && !/jsdom/.test(window.navigator.userAgent)) {
console.warn([
'The `:focus-visible` pseudo class is not supported in this browser.',
'Some components rely on this feature to work properly.'
].join('\n'));
}
}
return false;
}
let mounted = false;
const refs = new Map();
const handler = ()=>{
refs.forEach(([ref, setFocusVisible])=>{
if (ref.current) {
setFocusVisible(isFocusVisible(ref.current));
} else {
setFocusVisible(false);
}
});
};
function setGlobalListeners() {
if (typeof window === 'undefined') {
return;
}
if (!mounted) {
document.body.addEventListener('keydown', handler);
document.body.addEventListener('focusin', handler);
document.body.addEventListener('focusout', handler);
}
mounted = true;
}
function removeGlobalListeners() {
if (mounted) {
document.body.removeEventListener('keydown', handler);
document.body.removeEventListener('focusin', handler);
document.body.removeEventListener('focusout', handler);
}
mounted = false;
}
const useFocusVisible = ({ ref })=>{
const [focusVisible, setFocusVisible] = react.useState(false);
const id = react.useId();
setGlobalListeners();
react.useEffect(()=>{
refs.set(id, [
ref,
setFocusVisible
]);
return ()=>{
refs.delete(id);
if (refs.size === 0) removeGlobalListeners();
};
}, [
id,
ref
]);
return [
focusVisible,
setFocusVisible
];
};
exports.useFocusVisible = useFocusVisible;