# All files / src/_hooks/OverflowObserver OverflowObserver.tsx

93.75% Statements 30/32
83.33% Branches 5/6
100% Functions 6/6
91.66% Lines 22/24

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
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    6838x

    552x

    276x

    276x

    38x
    313x
    313x

    313x
    478x
    202x

    276x
    276x
    2x

    276x
    276x
    2x

    313x

    256x
    256x
    256x

    256x

    256x

     import React from 'react'
    import { OverflowObserverProps, OverflowState } from './OverflowObserver.types'

    // Browsers occasionally miscalculate scroll and client width/height by one pixel up or down
    //  so we're use |x| > 1 instead of x > 0 assertion eliminating the issue at the cost of
    //  a false-negative result if the content is overflowing by just 1 pixel
    function isContentOverflowing(length: number, visibleLength: number) {
      return Math.abs(length - visibleLength) > 1
    }

    function isContentOverflowingX(node: HTMLElement) {
      return isContentOverflowing(node.scrollWidth, node.clientWidth)
    }

    function isContentOverflowingY(node: HTMLElement) {
      return isContentOverflowing(node.scrollHeight, node.clientHeight)
    }

    /**
     * @deprecatedSince 11
     * @deprecated Never officially documented/supported
     */
    export function useOverflowObserver(): OverflowState {
      const [isOverflowingX, setIsOverflowingX] = React.useState(false)
      const [isOverflowingY, setIsOverflowingY] = React.useState(false)

      const ref = (node: HTMLElement | null) => {
        if (!node) {
          return
        }

        const newIsOverflowingX = isContentOverflowingX(node)
        if (newIsOverflowingX !== isOverflowingX) {
          setIsOverflowingX(newIsOverflowingX)
        }

        const newIsOverflowingY = isContentOverflowingY(node)
        if (newIsOverflowingY !== isOverflowingY) {
          setIsOverflowingY(newIsOverflowingY)
        }
      }

      return {
        ref,
        isOverflowingX,
        isOverflowingY,
        isOverflowing: isOverflowingX || isOverflowingY,
      }
    }

    /**
     * @deprecatedSince 11
     * @deprecated Never officially documented/supported
     */
    export function OverflowObserver({ children }: OverflowObserverProps) {
      const { ref, isOverflowing, isOverflowingX, isOverflowingY } =
        useOverflowObserver()

      Iif (typeof children !== 'function') {
        console.warn(
          `OverflowObserver: expected a function as "children" prop, received ${typeof children}`
        )
        return children as JSX.Element
      }

      return children({ ref, isOverflowing, isOverflowingX, isOverflowingY })
    }