@douyinfe/semi-ui
Version:
A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.
133 lines (132 loc) • 5.02 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.ObserverProperty = void 0;
var _react = _interopRequireDefault(require("react"));
var _reactDom = require("react-dom");
var _propTypes = _interopRequireDefault(require("prop-types"));
var _baseComponent = _interopRequireDefault(require("../_base/baseComponent"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var ObserverProperty;
(function (ObserverProperty) {
ObserverProperty["Width"] = "width";
ObserverProperty["Height"] = "height";
ObserverProperty["All"] = "all";
})(ObserverProperty || (exports.ObserverProperty = ObserverProperty = {}));
class ReactResizeObserver extends _baseComponent.default {
constructor(props) {
var _this;
super(props);
_this = this;
this.formerPropertyValue = new Map();
this.getElement = () => {
try {
// using findDOMNode for two reasons:
// 1. cloning to insert a ref is unwieldy and not performant.
// 2. ensure that we resolve to an actual DOM node (instead of any JSX ref instance).
return (0, _reactDom.findDOMNode)(this.childNode || this);
} catch (error) {
// swallow error if findDOMNode is run on unmounted component.
return null;
}
};
this.handleResizeEventTriggered = entries => {
var _a, _b, _c, _d;
if (this.props.observerProperty === ObserverProperty.All) {
(_b = (_a = this.props).onResize) === null || _b === void 0 ? void 0 : _b.call(_a, entries);
} else {
const finalEntries = [];
for (const entry of entries) {
if (this.formerPropertyValue.has(entry.target)) {
if (entry.contentRect[this.props.observerProperty] !== this.formerPropertyValue.get(entry.target)) {
this.formerPropertyValue.set(entry.target, entry.contentRect[this.props.observerProperty]);
finalEntries.push(entry);
}
} else {
this.formerPropertyValue.set(entry.target, entry.contentRect[this.props.observerProperty]);
finalEntries.push(entry);
}
}
if (finalEntries.length > 0) {
(_d = (_c = this.props).onResize) === null || _d === void 0 ? void 0 : _d.call(_c, finalEntries);
}
}
};
this.observeElement = function () {
let force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
const element = _this.getElement();
if (!_this.observer) {
_this.observer = new ResizeObserver(_this.handleResizeEventTriggered);
}
if (!(element && element instanceof Element)) {
// stop everything if not defined
_this.observer.disconnect();
return;
}
if (element === _this.element && !force) {
// abort if given same element -- nothing to update (unless forced)
return;
} else {
// clear observer list if new element
_this.observer.disconnect();
// remember element reference for next time
_this.element = element;
}
// observer callback is invoked immediately when observing new elements
_this.observer.observe(element);
if (_this.props.observeParent && element.parentNode && element.parentNode.ownerDocument && element.parentNode.ownerDocument.defaultView && element.parentNode instanceof element.parentNode.ownerDocument.defaultView.HTMLElement) {
_this._parentNode = element.parentNode;
_this.observer.observe(_this._parentNode);
}
};
this.mergeRef = (ref, node) => {
this.childNode = node;
if (typeof ref === 'function') {
ref(node);
} else if (typeof ref === 'object' && ref && 'current' in ref) {
ref.current = node;
}
};
if (globalThis['ResizeObserver']) {
this.observer = new ResizeObserver(this.handleResizeEventTriggered);
}
}
componentDidMount() {
var _a;
(_a = this.observeElement) === null || _a === void 0 ? void 0 : _a.call(this);
}
componentDidUpdate(prevProps) {
var _a;
(_a = this.observeElement) === null || _a === void 0 ? void 0 : _a.call(this, this.props.observeParent !== prevProps.observeParent);
}
componentWillUnmount() {
if (this.observer) {
this.observer.disconnect();
this.observer = null;
this.element = null;
}
}
render() {
const child = _react.default.Children.only(this.props.children);
const {
ref
} = child;
return /*#__PURE__*/_react.default.cloneElement(child, {
ref: node => this.mergeRef(ref, node)
});
}
}
exports.default = ReactResizeObserver;
ReactResizeObserver.propTypes = {
onResize: _propTypes.default.func,
observeParent: _propTypes.default.bool,
observerProperty: _propTypes.default.string,
delayTick: _propTypes.default.number
};
ReactResizeObserver.defaultProps = {
onResize: () => {},
observeParent: false,
observerProperty: "all",
delayTick: 0
};