|
- import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
- import _createClass from 'babel-runtime/helpers/createClass';
- import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
- import _inherits from 'babel-runtime/helpers/inherits';
- import React, { Component } from 'react';
- import PropTypes from 'prop-types';
- import ReactDOM from 'react-dom';
- import { alignElement, alignPoint } from 'dom-align';
- import addEventListener from 'rc-util/es/Dom/addEventListener';
-
- import { isWindow, buffer, isSamePoint, isSimilarValue, restoreFocus } from './util';
-
- function getElement(func) {
- if (typeof func !== 'function' || !func) return null;
- return func();
- }
-
- function getPoint(point) {
- if (typeof point !== 'object' || !point) return null;
- return point;
- }
-
- var Align = function (_Component) {
- _inherits(Align, _Component);
-
- function Align() {
- var _ref;
-
- var _temp, _this, _ret;
-
- _classCallCheck(this, Align);
-
- for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
-
- return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Align.__proto__ || Object.getPrototypeOf(Align)).call.apply(_ref, [this].concat(args))), _this), _this.forceAlign = function () {
- var _this$props = _this.props,
- disabled = _this$props.disabled,
- target = _this$props.target,
- align = _this$props.align,
- onAlign = _this$props.onAlign;
-
- if (!disabled && target) {
- var source = ReactDOM.findDOMNode(_this);
-
- var result = void 0;
- var element = getElement(target);
- var point = getPoint(target);
-
- // IE lose focus after element realign
- // We should record activeElement and restore later
- var activeElement = document.activeElement;
-
- if (element) {
- result = alignElement(source, element, align);
- } else if (point) {
- result = alignPoint(source, point, align);
- }
-
- restoreFocus(activeElement, source);
-
- if (onAlign) {
- onAlign(source, result);
- }
- }
- }, _temp), _possibleConstructorReturn(_this, _ret);
- }
-
- _createClass(Align, [{
- key: 'componentDidMount',
- value: function componentDidMount() {
- var props = this.props;
- // if parent ref not attached .... use document.getElementById
- this.forceAlign();
- if (!props.disabled && props.monitorWindowResize) {
- this.startMonitorWindowResize();
- }
- }
- }, {
- key: 'componentDidUpdate',
- value: function componentDidUpdate(prevProps) {
- var reAlign = false;
- var props = this.props;
-
- if (!props.disabled) {
- var source = ReactDOM.findDOMNode(this);
- var sourceRect = source ? source.getBoundingClientRect() : null;
-
- if (prevProps.disabled) {
- reAlign = true;
- } else {
- var lastElement = getElement(prevProps.target);
- var currentElement = getElement(props.target);
- var lastPoint = getPoint(prevProps.target);
- var currentPoint = getPoint(props.target);
-
- if (isWindow(lastElement) && isWindow(currentElement)) {
- // Skip if is window
- reAlign = false;
- } else if (lastElement !== currentElement || // Element change
- lastElement && !currentElement && currentPoint || // Change from element to point
- lastPoint && currentPoint && currentElement || // Change from point to element
- currentPoint && !isSamePoint(lastPoint, currentPoint)) {
- reAlign = true;
- }
-
- // If source element size changed
- var preRect = this.sourceRect || {};
- if (!reAlign && source && (!isSimilarValue(preRect.width, sourceRect.width) || !isSimilarValue(preRect.height, sourceRect.height))) {
- reAlign = true;
- }
- }
-
- this.sourceRect = sourceRect;
- }
-
- if (reAlign) {
- this.forceAlign();
- }
-
- if (props.monitorWindowResize && !props.disabled) {
- this.startMonitorWindowResize();
- } else {
- this.stopMonitorWindowResize();
- }
- }
- }, {
- key: 'componentWillUnmount',
- value: function componentWillUnmount() {
- this.stopMonitorWindowResize();
- }
- }, {
- key: 'startMonitorWindowResize',
- value: function startMonitorWindowResize() {
- if (!this.resizeHandler) {
- this.bufferMonitor = buffer(this.forceAlign, this.props.monitorBufferTime);
- this.resizeHandler = addEventListener(window, 'resize', this.bufferMonitor);
- }
- }
- }, {
- key: 'stopMonitorWindowResize',
- value: function stopMonitorWindowResize() {
- if (this.resizeHandler) {
- this.bufferMonitor.clear();
- this.resizeHandler.remove();
- this.resizeHandler = null;
- }
- }
- }, {
- key: 'render',
- value: function render() {
- var _this2 = this;
-
- var _props = this.props,
- childrenProps = _props.childrenProps,
- children = _props.children;
-
- var child = React.Children.only(children);
- if (childrenProps) {
- var newProps = {};
- var propList = Object.keys(childrenProps);
- propList.forEach(function (prop) {
- newProps[prop] = _this2.props[childrenProps[prop]];
- });
-
- return React.cloneElement(child, newProps);
- }
- return child;
- }
- }]);
-
- return Align;
- }(Component);
-
- Align.propTypes = {
- childrenProps: PropTypes.object,
- align: PropTypes.object.isRequired,
- target: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
- clientX: PropTypes.number,
- clientY: PropTypes.number,
- pageX: PropTypes.number,
- pageY: PropTypes.number
- })]),
- onAlign: PropTypes.func,
- monitorBufferTime: PropTypes.number,
- monitorWindowResize: PropTypes.bool,
- disabled: PropTypes.bool,
- children: PropTypes.any
- };
- Align.defaultProps = {
- target: function target() {
- return window;
- },
- monitorBufferTime: 50,
- monitorWindowResize: false,
- disabled: false
- };
-
-
- export default Align;
|