useFloatingToolbarNavSize.ts 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. import { useLayoutEffect, useState } from 'react'
  2. import type { NavSize } from './FloatingMobileToolbar.utils'
  3. function measure(
  4. el: HTMLElement | null,
  5. setNavSize: React.Dispatch<React.SetStateAction<NavSize>>
  6. ) {
  7. if (!el) return
  8. const rect = el.getBoundingClientRect()
  9. setNavSize((prev) =>
  10. prev.width !== rect.width || prev.height !== rect.height
  11. ? { width: rect.width, height: rect.height }
  12. : prev
  13. )
  14. }
  15. export function useFloatingToolbarNavSize(
  16. navRef: React.RefObject<HTMLElement | null>,
  17. isSheetOpen: boolean
  18. ): NavSize {
  19. const [navSize, setNavSize] = useState<NavSize>({ width: 0, height: 0 })
  20. useLayoutEffect(() => {
  21. const el = navRef.current
  22. if (!el) return
  23. measure(el, setNavSize)
  24. const ro = new ResizeObserver(() => measure(el, setNavSize))
  25. ro.observe(el)
  26. return () => ro.disconnect()
  27. }, [navRef])
  28. useLayoutEffect(() => {
  29. if (!isSheetOpen) return
  30. const raf = requestAnimationFrame(() => measure(navRef.current, setNavSize))
  31. return () => cancelAnimationFrame(raf)
  32. }, [isSheetOpen, navRef])
  33. return navSize
  34. }