// @ts-nocheck /** * Copyright (c) Nicolas Gallagher. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import type { ElementRef } from 'react' import type { LayoutEvent } from '../../types' import canUseDOM from '../canUseDOM' import UIManager from '../UIManager/index' import useLayoutEffect from '../useLayoutEffect/index' const DOM_LAYOUT_HANDLER_NAME = '__reactLayoutHandler' let didWarn = !canUseDOM let resizeObserver = null function getResizeObserver(): ResizeObserver | null { if (canUseDOM && typeof window.ResizeObserver !== 'undefined') { if (resizeObserver == null) { resizeObserver = new window.ResizeObserver(function (entries) { entries.forEach((entry) => { const node = entry.target const onLayout = node[DOM_LAYOUT_HANDLER_NAME] if (typeof onLayout === 'function') { // We still need to measure the view because browsers don't yet provide // border-box dimensions in the entry UIManager.measure(node, (x, y, width, height, left, top) => { const event: LayoutEvent = { // @ts-ignore nativeEvent: { layout: { x, y, width, height, left, top }, }, timeStamp: Date.now(), } Object.defineProperty(event.nativeEvent, 'target', { enumerable: true, get: () => entry.target, }) onLayout(event) }) } }) }) } } else if (!didWarn) { if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test') { console.warn( 'onLayout relies on ResizeObserver which is not supported by your browser. ' + 'Please include a polyfill, e.g., https://github.com/que-etc/resize-observer-polyfill.' ) didWarn = true } } return resizeObserver } export default function useElementLayout( ref: ElementRef, onLayout?: ((e: LayoutEvent) => void) | null ) { const observer = getResizeObserver() useLayoutEffect(() => { const node = ref.current if (node != null) { node[DOM_LAYOUT_HANDLER_NAME] = onLayout } }, [ref, onLayout]) // Observing is done in a separate effect to avoid this effect running // when 'onLayout' changes. useLayoutEffect(() => { const node = ref.current if (node != null && observer != null) { if (typeof node[DOM_LAYOUT_HANDLER_NAME] === 'function') { observer.observe(node) } else { observer.unobserve(node) } } return () => { if (node != null && observer != null) { observer.unobserve(node) } } }, [ref, observer]) }