UNPKG

@intility/bifrost-react

Version:

React library for Intility's design system, Bifrost.

115 lines (112 loc) 3.61 kB
/* eslint-disable @typescript-eslint/no-explicit-any */ "use client"; import { c as _c } from "react-compiler-runtime"; import useLayoutEffect from "./useIsomorphicLayoutEffect.js"; import useEffectEvent from "./useEffectEvent.js"; // stolen from https://github.com/jaredLunde/react-hook/tree/master/packages/resize-observer // reworked slightly since it caused crashes when building static site for next.js // for some reason they think polyfilling should be the responsibility of the consumer for SSR/RSC // but we want bifrost to be ssr friendly out of the box https://github.com/jaredLunde/react-hook/issues/310 /** * A React hook that fires a callback whenever ResizeObserver detects a change to its size * * @param target A React ref created by `useRef()` or an HTML element * @param callback Invoked with a single `ResizeObserverEntry` any time * the `target` resizes */ function useResizeObserver(target, callback, t0) { const $ = _c(9); let t1; if ($[0] !== t0) { t1 = t0 === undefined ? {} : t0; $[0] = t0; $[1] = t1; } else { t1 = $[1]; } const options = t1; const callbackEvent = useEffectEvent(callback); let t2; if ($[2] !== callbackEvent || $[3] !== options.polyfill || $[4] !== target) { t2 = () => { const resizeObserver = getResizeObserver(options.polyfill); let didUnsubscribe = false; const targetEl = target && "current" in target ? target.current : target; if (!targetEl) { return; } const cb = function cb(entry, observer) { if (didUnsubscribe) { return; } callbackEvent(entry, observer); }; resizeObserver.subscribe(targetEl, cb); return () => { didUnsubscribe = true; resizeObserver.unsubscribe(targetEl, cb); }; }; $[2] = callbackEvent; $[3] = options.polyfill; $[4] = target; $[5] = t2; } else { t2 = $[5]; } let t3; if ($[6] !== options.polyfill || $[7] !== target) { t3 = [target, options.polyfill]; $[6] = options.polyfill; $[7] = target; $[8] = t3; } else { t3 = $[8]; } useLayoutEffect(t2, t3); } function createResizeObserver(polyfill) { let ticking = false; let allEntries = []; const callbacks = new Map(); const observer = new (polyfill || window.ResizeObserver)((entries, obs) => { allEntries = allEntries.concat(entries); if (!ticking) { window.requestAnimationFrame(() => { const triggered = new Set(); for (let i = 0; i < allEntries.length; i++) { if (triggered.has(allEntries[i].target)) continue; triggered.add(allEntries[i].target); const cbs = callbacks.get(allEntries[i].target); cbs?.forEach(cb => cb(allEntries[i], obs)); } allEntries = []; ticking = false; }); } ticking = true; }); return { observer, subscribe(target, callback) { observer.observe(target); const cbs = callbacks.get(target) ?? []; cbs.push(callback); callbacks.set(target, cbs); }, unsubscribe(target, callback) { const cbs = callbacks.get(target) ?? []; if (cbs.length === 1) { observer.unobserve(target); callbacks.delete(target); return; } const cbIndex = cbs.indexOf(callback); if (cbIndex !== -1) cbs.splice(cbIndex, 1); callbacks.set(target, cbs); } }; } let _resizeObserver; const getResizeObserver = polyfill => !_resizeObserver ? _resizeObserver = createResizeObserver(polyfill) : _resizeObserver; export default useResizeObserver;