@atlaskit/spotlight
Version:
A spotlight introduces users to points of interest, from focused messages to multi-step tours.
65 lines (63 loc) • 1.94 kB
JavaScript
import { useEffect, useState } from 'react';
import { bind } from 'bind-event-listener';
/**
* Future improvements to this might be to check if the target resizes with:
* ```
* const ro = new ResizeObserver(read);
* ro.observe(targetRef.current);
* ```
*
* No need to do this for the PopoverContent, as it has static height/width.
*/
export const usePositionArea = ref => {
const [positionArea, setPositionArea] = useState(undefined);
useEffect(() => {
const el = ref.current;
if (!el) {
return;
}
const readPositionArea = () => {
try {
var _el$computedStyleMap$;
return (_el$computedStyleMap$ = el.computedStyleMap().get('position-area')) === null || _el$computedStyleMap$ === void 0 ? void 0 : _el$computedStyleMap$.toString();
} catch {
// Some old browsers do not support computedStyleMap, so fall back to getPropertyValue
return window.getComputedStyle(el).getPropertyValue('position-area').trim();
}
};
const read = () => {
const positionArea = readPositionArea();
setPositionArea(positionArea);
};
read();
/**
* requestAnimationFrame ensures that initial renders are in a different position
* to the supplied prop value (e.g. the viewport is too small so the position is
* recalculated) are rendered correctly.
*/
const rafId = window.requestAnimationFrame(read);
// Check if the viewport resizes
const unbindResize = bind(window, {
type: 'resize',
listener: read,
options: {
passive: true
}
});
// Check if the viewport scrolls
const unbindScroll = bind(window, {
type: 'scroll',
listener: read,
options: {
passive: true,
capture: true
}
});
return () => {
window.cancelAnimationFrame(rafId);
unbindResize();
unbindScroll();
};
}, [ref]);
return positionArea;
};