@bianic-ui/descendant
Version:
Register child nodes of a react element for better accessibility
99 lines (86 loc) • 3.16 kB
JavaScript
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
import { useCallback, useMemo, useState } from "react";
import { useSafeLayoutEffect, useForceUpdate } from "@bianic-ui/hooks";
export function useDescendant(props) {
var {
context,
element,
index: indexProp,
disabled,
focusable
} = props,
rest = _objectWithoutPropertiesLoose(props, ["context", "element", "index", "disabled", "focusable"]);
var forceUpdate = useForceUpdate();
var {
register,
unregister,
descendants
} = context;
useSafeLayoutEffect(() => {
if (!element) {
forceUpdate();
}
/**
* Don't register this descendant if it's disabled and not focusable
*/
if (disabled && !focusable) return;
/**
* else, register the descendant
*/
register(_extends({
element,
disabled,
focusable
}, rest));
/**
* when it unmounts, unregister the descendant
*/
return () => {
if (element) {
unregister(element);
}
}; //eslint-disable-next-line
}, [element, disabled, focusable, ...Object.values(rest)]);
var index = indexProp != null ? indexProp : descendants.findIndex(descendant => descendant.element === element);
return index;
}
export function useDescendants() {
var [descendants, setDescendants] = useState([]);
var register = useCallback((_ref) => {
var {
element
} = _ref,
rest = _objectWithoutPropertiesLoose(_ref, ["element"]);
if (!element) return; //@ts-ignore
setDescendants(prevDescendants => {
if (prevDescendants.find(item => item.element === element) == null) {
var index = prevDescendants.findIndex(item => {
if (!item.element || !element) return false;
return Boolean(item.element.compareDocumentPosition(element) & Node.DOCUMENT_POSITION_PRECEDING);
});
var newItem = _extends({
element
}, rest);
if (index === -1) {
return [...prevDescendants, newItem];
}
return [...prevDescendants.slice(0, index), newItem, ...prevDescendants.slice(index)];
}
return prevDescendants;
});
}, []);
var unregister = useCallback(element => {
if (!element) return;
setDescendants(descendants => descendants.filter(descendant => element !== descendant.element));
}, []);
var context = useMemo(() => {
return {
descendants,
register,
unregister
};
}, [descendants, register, unregister]);
return context;
}
//# sourceMappingURL=use-descendant.js.map