92 lines
2.8 KiB
JavaScript
92 lines
2.8 KiB
JavaScript
/**
|
|
* 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.
|
|
*
|
|
*
|
|
*/
|
|
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
|
|
import useLayoutEffect from './useLayoutEffect';
|
|
import UIManager from '../exports/UIManager';
|
|
var DOM_LAYOUT_HANDLER_NAME = '__reactLayoutHandler';
|
|
var didWarn = !canUseDOM;
|
|
var resizeObserver = null;
|
|
|
|
function getResizeObserver() {
|
|
if (canUseDOM && typeof window.ResizeObserver !== 'undefined') {
|
|
if (resizeObserver == null) {
|
|
resizeObserver = new window.ResizeObserver(function (entries) {
|
|
entries.forEach(function (entry) {
|
|
var node = entry.target;
|
|
var 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, function (x, y, width, height, left, top) {
|
|
var event = {
|
|
// $FlowFixMe
|
|
nativeEvent: {
|
|
layout: {
|
|
x: x,
|
|
y: y,
|
|
width: width,
|
|
height: height,
|
|
left: left,
|
|
top: top
|
|
}
|
|
},
|
|
timeStamp: Date.now()
|
|
};
|
|
Object.defineProperty(event.nativeEvent, 'target', {
|
|
enumerable: true,
|
|
get: function get() {
|
|
return 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, onLayout) {
|
|
var observer = getResizeObserver();
|
|
useLayoutEffect(function () {
|
|
var 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(function () {
|
|
var node = ref.current;
|
|
|
|
if (node != null && observer != null) {
|
|
if (typeof node[DOM_LAYOUT_HANDLER_NAME] === 'function') {
|
|
observer.observe(node);
|
|
} else {
|
|
observer.unobserve(node);
|
|
}
|
|
}
|
|
|
|
return function () {
|
|
if (node != null && observer != null) {
|
|
observer.unobserve(node);
|
|
}
|
|
};
|
|
}, [ref, observer]);
|
|
} |