index.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import _typeof from "@babel/runtime/helpers/esm/typeof";
  3. import findDOMNode from "rc-util/es/Dom/findDOMNode";
  4. import { supportRef, useComposeRef, getNodeRef } from "rc-util/es/ref";
  5. import * as React from 'react';
  6. import { CollectionContext } from "../Collection";
  7. import { observe, unobserve } from "../utils/observerUtil";
  8. import DomWrapper from "./DomWrapper";
  9. function SingleObserver(props, ref) {
  10. var children = props.children,
  11. disabled = props.disabled;
  12. var elementRef = React.useRef(null);
  13. var wrapperRef = React.useRef(null);
  14. var onCollectionResize = React.useContext(CollectionContext);
  15. // =========================== Children ===========================
  16. var isRenderProps = typeof children === 'function';
  17. var mergedChildren = isRenderProps ? children(elementRef) : children;
  18. // ============================= Size =============================
  19. var sizeRef = React.useRef({
  20. width: -1,
  21. height: -1,
  22. offsetWidth: -1,
  23. offsetHeight: -1
  24. });
  25. // ============================= Ref ==============================
  26. var canRef = !isRenderProps && /*#__PURE__*/React.isValidElement(mergedChildren) && supportRef(mergedChildren);
  27. var originRef = canRef ? getNodeRef(mergedChildren) : null;
  28. var mergedRef = useComposeRef(originRef, elementRef);
  29. var getDom = function getDom() {
  30. var _elementRef$current;
  31. return findDOMNode(elementRef.current) || (
  32. // Support `nativeElement` format
  33. elementRef.current && _typeof(elementRef.current) === 'object' ? findDOMNode((_elementRef$current = elementRef.current) === null || _elementRef$current === void 0 ? void 0 : _elementRef$current.nativeElement) : null) || findDOMNode(wrapperRef.current);
  34. };
  35. React.useImperativeHandle(ref, function () {
  36. return getDom();
  37. });
  38. // =========================== Observe ============================
  39. var propsRef = React.useRef(props);
  40. propsRef.current = props;
  41. // Handler
  42. var onInternalResize = React.useCallback(function (target) {
  43. var _propsRef$current = propsRef.current,
  44. onResize = _propsRef$current.onResize,
  45. data = _propsRef$current.data;
  46. var _target$getBoundingCl = target.getBoundingClientRect(),
  47. width = _target$getBoundingCl.width,
  48. height = _target$getBoundingCl.height;
  49. var offsetWidth = target.offsetWidth,
  50. offsetHeight = target.offsetHeight;
  51. /**
  52. * Resize observer trigger when content size changed.
  53. * In most case we just care about element size,
  54. * let's use `boundary` instead of `contentRect` here to avoid shaking.
  55. */
  56. var fixedWidth = Math.floor(width);
  57. var fixedHeight = Math.floor(height);
  58. if (sizeRef.current.width !== fixedWidth || sizeRef.current.height !== fixedHeight || sizeRef.current.offsetWidth !== offsetWidth || sizeRef.current.offsetHeight !== offsetHeight) {
  59. var size = {
  60. width: fixedWidth,
  61. height: fixedHeight,
  62. offsetWidth: offsetWidth,
  63. offsetHeight: offsetHeight
  64. };
  65. sizeRef.current = size;
  66. // IE is strange, right?
  67. var mergedOffsetWidth = offsetWidth === Math.round(width) ? width : offsetWidth;
  68. var mergedOffsetHeight = offsetHeight === Math.round(height) ? height : offsetHeight;
  69. var sizeInfo = _objectSpread(_objectSpread({}, size), {}, {
  70. offsetWidth: mergedOffsetWidth,
  71. offsetHeight: mergedOffsetHeight
  72. });
  73. // Let collection know what happened
  74. onCollectionResize === null || onCollectionResize === void 0 || onCollectionResize(sizeInfo, target, data);
  75. if (onResize) {
  76. // defer the callback but not defer to next frame
  77. Promise.resolve().then(function () {
  78. onResize(sizeInfo, target);
  79. });
  80. }
  81. }
  82. }, []);
  83. // Dynamic observe
  84. React.useEffect(function () {
  85. var currentElement = getDom();
  86. if (currentElement && !disabled) {
  87. observe(currentElement, onInternalResize);
  88. }
  89. return function () {
  90. return unobserve(currentElement, onInternalResize);
  91. };
  92. }, [elementRef.current, disabled]);
  93. // ============================ Render ============================
  94. return /*#__PURE__*/React.createElement(DomWrapper, {
  95. ref: wrapperRef
  96. }, canRef ? /*#__PURE__*/React.cloneElement(mergedChildren, {
  97. ref: mergedRef
  98. }) : mergedChildren);
  99. }
  100. var RefSingleObserver = /*#__PURE__*/React.forwardRef(SingleObserver);
  101. if (process.env.NODE_ENV !== 'production') {
  102. RefSingleObserver.displayName = 'SingleObserver';
  103. }
  104. export default RefSingleObserver;