Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 783x 783x 176x 44x 44x 132x 133x 133x 139x 132x 132x 132x 783x | import { useState } from "react";
import { useIsomorphicLayoutEffect } from "@usefy/use-isomorphic-layout-effect";
/** A viewport size in CSS px. */
export interface ViewportSize {
width: number;
height: number;
}
/**
* Track the window's inner size while `active` — used to feed the live
* viewport box into `computeTooltipPosition`. Commits state only when the
* size actually changes; returns `null` while inactive or on the server.
*
* `resize` is the only listener (scroll never changes the viewport size), so
* no rAF batching is needed — resize events are low-frequency and the commit
* is change-gated anyway.
*
* @param active - Track while true (typically "the tour is open").
* @returns The current viewport size, or `null` when inactive/SSR.
*
* @internal
*/
export function useViewportSize(active: boolean): ViewportSize | null {
const [size, setSize] = useState<ViewportSize | null>(null);
useIsomorphicLayoutEffect(() => {
if (!active || typeof window === "undefined") {
setSize(null);
return;
}
const update = () => {
const next = { width: window.innerWidth, height: window.innerHeight };
setSize((prev) =>
prev && prev.width === next.width && prev.height === next.height
? prev
: next
);
};
update();
window.addEventListener("resize", update, { passive: true });
return () => window.removeEventListener("resize", update);
}, [active]);
return size;
}
|