File size: 1,502 Bytes
00a912e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { useCallback, useRef, useState } from 'react'

/**
 * Measures the minimum dimension (min of width/height) of a container element.
 * Used to constrain sibling elements (info bar, controls) to match cover width.
 *
 * @param paused - When true, stops updating the width (e.g. during lyric mode
 *   where the container shrinks to compact height and would produce a misleading value).
 */
export function useCoverWidth(paused: boolean) {
  const [width, setWidth] = useState(0)
  const observerRef = useRef<ResizeObserver | null>(null)

  const ref = useCallback(
    (node: HTMLDivElement | null) => {
      observerRef.current?.disconnect()
      observerRef.current = null
      if (!node) return

      const update = (w: number, h: number) => {
        if (paused) return
        const newDimension = Math.floor(Math.min(w, h))

        setWidth((prev) => {
          // Hysteresis dead-zone: Ignore sub 3px changes to prevent ResizeObserver infinite loops
          // when the zoom scaling below changes the actual pixel height of the controls.
          if (Math.abs(prev - newDimension) <= 3) return prev
          return newDimension
        })
      }

      const rect = node.getBoundingClientRect()
      update(rect.width, rect.height)

      const ro = new ResizeObserver(([entry]) => {
        update(entry.contentRect.width, entry.contentRect.height)
      })
      ro.observe(node)
      observerRef.current = ro
    },
    [paused],
  )

  return { ref, coverWidth: width }
}