@hello-pangea/dnd
Version:
Beautiful and accessible drag and drop for lists with React
47 lines (38 loc) • 1.2 kB
text/typescript
const supportedMatchesName:
| 'matches'
| 'msMatchesSelector'
| 'webkitMatchesSelector' = (() => {
const base = 'matches' as const;
// Server side rendering
if (typeof document === 'undefined') {
return base;
}
// See https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
const candidates = [
base,
'msMatchesSelector' as const,
'webkitMatchesSelector' as const,
];
const value = candidates.find((name): boolean => name in Element.prototype);
return value || base;
})();
function closestPonyfill(el: Element | null, selector: string): null | Element {
if (el == null) {
return null;
}
// Element.prototype.matches is supported in ie11 with a different name
// https://caniuse.com/#feat=matchesselector
if (el[supportedMatchesName as 'matches'](selector)) {
return el;
}
// recursively look up the tree
return closestPonyfill(el.parentElement, selector);
}
export default function closest(el: Element, selector: string): Element | null {
// Using native closest for maximum speed where we can
if (el.closest) {
return el.closest(selector);
}
// ie11: damn you!
return closestPonyfill(el, selector);
}