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