rc-trigger

rc-trigger用于绘制触发节点及相应浮层。

Trigger.js

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);

var _react = require('react');
var _react2 = _interopRequireDefault(_react);

var _reactDom = require('react-dom');
var _reactDom2 = _interopRequireDefault(_reactDom);

var _contains = require('rc-util/lib/Dom/contains');
var _contains2 = _interopRequireDefault(_contains);

var _addEventListener = require('rc-util/lib/Dom/addEventListener');
var _addEventListener2 = _interopRequireDefault(_addEventListener);

var _Popup = require('./Popup');
var _Popup2 = _interopRequireDefault(_Popup);

var _utils = require('./utils');

// 提供在document中创建div,并将组件的renderComponent渲染的元素挂载到该div下的能力
// 同时使组件实例的_component属性指向renderComponent方法渲染出来的组件实例
var _getContainerRenderMixin = require('rc-util/lib/getContainerRenderMixin');
var _getContainerRenderMixin2 = _interopRequireDefault(_getContainerRenderMixin);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function noop() {}

function returnEmptyString() {
  return '';
}

var ALL_HANDLERS = ['onClick', 'onMouseDown', 'onTouchStart', 'onMouseEnter', 'onMouseLeave', 'onFocus', 'onBlur'];

var Trigger = _react2["default"].createClass({
  displayName: 'Trigger',

  propTypes: {
    // 实际显示用的待渲染节点
    children: _react.PropTypes.any,

    // 设置触发props.children显示隐藏的方法,将作为props添加到props.children元素中,如["click"]
    // 特别的,action、showAction、hideAction中没有添加"click"时,调用this.props.onClick的同时调用this.props.children.props.onClick,却不触发this.onClick
    //    添加"click"时,执行this.props.onClick、this.props.children.props.onClick、及this.onClick
    action: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.arrayOf(_react.PropTypes.string)]),
    // 设置触发props.children显示的方法
    showAction: _react.PropTypes.any,
    // 设置触发props.children隐藏的方法
    hideAction: _react.PropTypes.any,

    // 设置浮层的容器,默认的容器document.body
    getPopupContainer: _react.PropTypes.func,

    // 浮层位置调整数据
    popupAlign: _react.PropTypes.object,
    popupPlacement: _react.PropTypes.string,
    builtinPlacements: _react.PropTypes.object,

    // 通过浮层位置调整数据获取添加到浮层中的样式类
    getPopupClassNameFromAlign: _react.PropTypes.any,

    // 浮层显示隐藏时执行的回调函数
    onPopupVisibleChange: _react.PropTypes.func,
    // 浮层重绘、且其显隐状态改变时执行的回调函数
    afterPopupVisibleChange: _react.PropTypes.func,

    popup: _react.PropTypes.oneOfType([_react.PropTypes.node, _react.PropTypes.func]).isRequired,

    // 浮层的样式类前缀
    prefixCls: _react.PropTypes.string,
    // 浮层的样式类
    popupClassName: _react.PropTypes.string,
    // 浮层元素的样式
    popupStyle: _react.PropTypes.object,
    // 浮层的zIndex
    zIndex: _react.PropTypes.number,

    // 浮层显隐时添加的css动效,popupAnimation将转化为rc-animation机制下的transitionName
    popupTransitionName: _react.PropTypes.string,
    popupAnimation: _react.PropTypes.any,

    // 鼠标移入移出、获得焦点、失去焦点时延迟显隐的事件
    mouseEnterDelay: _react.PropTypes.number,
    mouseLeaveDelay: _react.PropTypes.number,
    focusDelay: _react.PropTypes.number,
    blurDelay: _react.PropTypes.number,

    // 浮层隐藏时,是否卸载该浮层元素
    destroyPopupOnHide: _react.PropTypes.bool,

    // 浮层位置对齐时执行的回调函数
    onPopupAlign: _react.PropTypes.func,

    // 挂载时设置浮层是否显示
    popupVisible: _react.PropTypes.bool,
    // defaultPopupVisible

    // 蒙层相关设置
    mask: _react.PropTypes.bool,
    maskClosable: _react.PropTypes.bool,
    maskTransitionName: _react.PropTypes.string,
    maskAnimation: _react.PropTypes.string
  },

  mixins: [(0, _getContainerRenderMixin2["default"])({
    autoMount: false,

    isVisible: function isVisible(instance) {
      return instance.state.popupVisible;
    },

    // renderComponent绘制的节点将挂载到popupContainer下
    getContainer: function getContainer(instance) {
      var popupContainer = document.createElement('div');
      var mountNode = instance.props.getPopupContainer ? instance.props.getPopupContainer((0, _reactDom.findDOMNode)(instance)) : document.body;
      mountNode.appendChild(popupContainer);
      return popupContainer;
    }
  })],

  getDefaultProps: function getDefaultProps() {
    return {
      prefixCls: 'rc-trigger-popup',
      getPopupClassNameFromAlign: returnEmptyString,
      onPopupVisibleChange: noop,
      afterPopupVisibleChange: noop,
      onPopupAlign: noop,
      popupClassName: '',
      mouseEnterDelay: 0,
      mouseLeaveDelay: 0.1,
      focusDelay: 0,
      blurDelay: 0.15,
      popupStyle: {},
      destroyPopupOnHide: false,
      popupAlign: {},
      defaultPopupVisible: false,
      mask: false,
      maskClosable: true,
      action: [],
      showAction: [],
      hideAction: []
    };
  },
  getInitialState: function getInitialState() {
    var props = this.props;
    var popupVisible = void 0;
    if ('popupVisible' in props) {
      popupVisible = !!props.popupVisible;
    } else {
      popupVisible = !!props.defaultPopupVisible;
    }
    return {
      popupVisible: popupVisible
    };
  },

  // 组件实例添加this.fireonClick等方法,供this.createTwoChains方法使用
  componentWillMount: function componentWillMount() {
    var _this = this;

    ALL_HANDLERS.forEach(function (h) {
      _this['fire' + h] = function (e) {
        _this.fireEvents(h, e);
      };
    });
  },
  componentDidMount: function componentDidMount() {
    // 调用componentDidUpdate生命周期方法绘制浮层
    this.componentDidUpdate({}, {
      popupVisible: this.state.popupVisible
    });
  },
  componentWillReceiveProps: function componentWillReceiveProps(_ref) {
    var popupVisible = _ref.popupVisible;

    if (popupVisible !== undefined) {
      this.setState({
        popupVisible: popupVisible
      });
    }
  },
  componentDidUpdate: function componentDidUpdate(_, prevState) {
    var props = this.props;
    var state = this.state;
    // 通过'rc-util/lib/Dom/addEventListener'机制绘制浮层,浮层绘制完成后执行afterPopupVisibleChange
    this.renderComponent(null, function () {
      if (prevState.popupVisible !== state.popupVisible) {
        props.afterPopupVisibleChange(state.popupVisible);
      }
    });

    // 点击隐藏事件存在,允许点击浮层外围用于隐藏该浮层
    if (this.isClickToHide()) {
      if (state.popupVisible) {
        if (!this.clickOutsideHandler) {
          this.clickOutsideHandler = (0, _addEventListener2["default"])(document, 'mousedown', this.onDocumentClick);
          this.touchOutsideHandler = (0, _addEventListener2["default"])(document, 'touchstart', this.onDocumentClick);
        }
        return;
      }
    }

    // 点击隐藏事件不存在时,释放内存
    if (this.clickOutsideHandler) {
      this.clickOutsideHandler.remove();
      this.touchOutsideHandler.remove();
      this.clickOutsideHandler = null;
      this.touchOutsideHandler = null;
    }
  },
  componentWillUnmount: function componentWillUnmount() {
    this.clearDelayTimer();
    if (this.clickOutsideHandler) {
      this.clickOutsideHandler.remove();
      this.touchOutsideHandler.remove();
      this.clickOutsideHandler = null;
      this.touchOutsideHandler = null;
    }
  },

  // 传给PopupInner组件,以控制浮层的显隐???
  onPopupMouseEnter: function onPopupMouseEnter() {
    this.clearDelayTimer();
  },
  onPopupMouseLeave: function onPopupMouseLeave(e) {
    // https://github.com/react-component/trigger/pull/13
    // react bug?
    if (e.relatedTarget && !e.relatedTarget.setTimeout && this._component && (0, _contains2["default"])(this._component.getPopupDomNode(), e.relatedTarget)) {
      return;
    }
    this.delaySetPopupVisible(false, this.props.mouseLeaveDelay);
  },

  // 鼠标移入移除、获取焦点、点击事件发生时,显示隐藏浮层;同时处理获取焦点和点击事件前后相差无几的状况
  onMouseEnter: function onMouseEnter(e) {
    this.fireEvents('onMouseEnter', e);
    this.delaySetPopupVisible(true, this.props.mouseEnterDelay);
  },
  onMouseLeave: function onMouseLeave(e) {
    this.fireEvents('onMouseLeave', e);
    this.delaySetPopupVisible(false, this.props.mouseLeaveDelay);
  },
  onFocus: function onFocus(e) {
    this.fireEvents('onFocus', e);
    this.clearDelayTimer();
    if (this.isFocusToShow()) {
      this.focusTime = Date.now();
      this.delaySetPopupVisible(true, this.props.focusDelay);
    }
  },
  onMouseDown: function onMouseDown(e) {
    this.fireEvents('onMouseDown', e);
    this.preClickTime = Date.now();
  },
  onTouchStart: function onTouchStart(e) {
    this.fireEvents('onTouchStart', e);
    this.preTouchTime = Date.now();
  },
  onBlur: function onBlur(e) {
    this.fireEvents('onBlur', e);
    this.clearDelayTimer();
    if (this.isBlurToHide()) {
      this.delaySetPopupVisible(false, this.props.blurDelay);
    }
  },
  // 获得焦点和鼠标点击时相差无几,阻止onClick方法对浮层显隐的影响
  onClick: function onClick(event) {
    this.fireEvents('onClick', event);
    // focus will trigger click
    if (this.focusTime) {
      var preTime = void 0;
      if (this.preClickTime && this.preTouchTime) {
        preTime = Math.min(this.preClickTime, this.preTouchTime);
      } else if (this.preClickTime) {
        preTime = this.preClickTime;
      } else if (this.preTouchTime) {
        preTime = this.preTouchTime;
      }
      if (Math.abs(preTime - this.focusTime) < 20) {
        return;
      }
      this.focusTime = 0;
    }
    this.preClickTime = 0;
    this.preTouchTime = 0;
    event.preventDefault();
    var nextVisible = !this.state.popupVisible;
    if (this.isClickToHide() && !nextVisible || nextVisible && this.isClickToShow()) {
      this.setPopupVisible(!this.state.popupVisible);
    }
  },

  // rc-trigger组件已绘制,且浮层显示时,点击浮层外围移除该浮层
  onDocumentClick: function onDocumentClick(event) {
    if (this.props.mask && !this.props.maskClosable) {
      return;
    }
    var target = event.target;
    var root = (0, _reactDom.findDOMNode)(this);
    var popupNode = this.getPopupDomNode();
    if (!(0, _contains2["default"])(root, target) && !(0, _contains2["default"])(popupNode, target)) {
      this.close();
    }
  },

  // 获取PopupInner组件实例的顶层dom节点
  getPopupDomNode: function getPopupDomNode() {
    if (this._component) {
      return this._component.isMounted() ? this._component.getPopupDomNode() : null;
    }
    return null;
  },
  // 获取当前组件顶层的dom节点,作为浮层对齐时的参照节点
  getRootDomNode: function getRootDomNode() {
    return _reactDom2["default"].findDOMNode(this);
  },

  // 通过浮层调整位置数据为浮层添加样式类
  getPopupClassNameFromAlign: function getPopupClassNameFromAlign(align) {
    var className = [];
    var props = this.props;
    var popupPlacement = props.popupPlacement,
        builtinPlacements = props.builtinPlacements,
        prefixCls = props.prefixCls;

    if (popupPlacement && builtinPlacements) {
      className.push((0, _utils.getPopupClassNameFromAlign)(builtinPlacements, prefixCls, align));
    }
    if (props.getPopupClassNameFromAlign) {
      className.push(props.getPopupClassNameFromAlign(align));
    }
    return className.join(' ');
  },
  // 获取浮层调整位置数据
  getPopupAlign: function getPopupAlign() {
    var props = this.props;
    var popupPlacement = props.popupPlacement,
        popupAlign = props.popupAlign,
        builtinPlacements = props.builtinPlacements;

    if (popupPlacement && builtinPlacements) {
      return (0, _utils.getAlignFromPlacement)(builtinPlacements, popupPlacement, popupAlign);
    }
    return popupAlign;
  },

  // 绘制浮层的具体方法,挂载到this._container下,整个机制由'rc-util/lib/Dom/addEventListener'提供
  getComponent: function getComponent() {
    var props = this.props,
        state = this.state;

    var mouseProps = {};
    if (this.isMouseEnterToShow()) {
      mouseProps.onMouseEnter = this.onPopupMouseEnter;
    }
    if (this.isMouseLeaveToHide()) {
      mouseProps.onMouseLeave = this.onPopupMouseLeave;
    }

    return _react2["default"].createElement(
      _Popup2["default"],
      (0, _extends3["default"])({
        prefixCls: props.prefixCls,
        destroyPopupOnHide: props.destroyPopupOnHide,
        visible: state.popupVisible,
        className: props.popupClassName,
        action: props.action,
        align: this.getPopupAlign(),
        onAlign: props.onPopupAlign,
        animation: props.popupAnimation,
        getClassNameFromAlign: this.getPopupClassNameFromAlign
      }, mouseProps, {
        getRootDomNode: this.getRootDomNode,
        style: props.popupStyle,
        mask: props.mask,
        zIndex: props.zIndex,
        transitionName: props.popupTransitionName,
        maskAnimation: props.maskAnimation,
        maskTransitionName: props.maskTransitionName
      }),
      typeof props.popup === 'function' ? props.popup() : props.popup
    );
  },

  // 显示或隐藏浮层,调用this.props.onPopupVisibleChange方法
  setPopupVisible: function setPopupVisible(popupVisible) {
    this.clearDelayTimer();
    if (this.state.popupVisible !== popupVisible) {
      if (!('popupVisible' in this.props)) {
        this.setState({
          popupVisible: popupVisible
        });
      }
      this.props.onPopupVisibleChange(popupVisible);
    }
  },
  // 延迟delayS时间,显示或隐藏浮层
  delaySetPopupVisible: function delaySetPopupVisible(visible, delayS) {
    var _this2 = this;

    var delay = delayS * 1000;
    this.clearDelayTimer();
    if (delay) {
      this.delayTimer = setTimeout(function () {
        _this2.setPopupVisible(visible);
        _this2.clearDelayTimer();
      }, delay);
    } else {
      this.setPopupVisible(visible);
    }
  },
  // 清除定时器
  clearDelayTimer: function clearDelayTimer() {
    if (this.delayTimer) {
      clearTimeout(this.delayTimer);
      this.delayTimer = null;
    }
  },

  // 传参event为"onClick"等,调用this.fireEvents("onClick",e)
  // 最终执行this.props.onClick及this.props.children.props.onClick
  createTwoChains: function createTwoChains(event) {
    var childPros = this.props.children.props;
    var props = this.props;
    if (childPros[event] && props[event]) {
      return this['fire' + event];// componentWillMount生命周期添加的方法,执行this.fireEvents(event,e)
    }
    return childPros[event] || props[event];
  },

  // 是否为props.children提供显示隐藏的onClick、onMouseDown、onTouchStart等方法
  isClickToShow: function isClickToShow() {
    var _props = this.props,
        action = _props.action,
        showAction = _props.showAction;

    return action.indexOf('click') !== -1 || showAction.indexOf('click') !== -1;
  },
  isClickToHide: function isClickToHide() {
    var _props2 = this.props,
        action = _props2.action,
        hideAction = _props2.hideAction;

    return action.indexOf('click') !== -1 || hideAction.indexOf('click') !== -1;
  },
  isMouseEnterToShow: function isMouseEnterToShow() {
    var _props3 = this.props,
        action = _props3.action,
        showAction = _props3.showAction;

    return action.indexOf('hover') !== -1 || showAction.indexOf('mouseEnter') !== -1;
  },
  isMouseLeaveToHide: function isMouseLeaveToHide() {
    var _props4 = this.props,
        action = _props4.action,
        hideAction = _props4.hideAction;

    return action.indexOf('hover') !== -1 || hideAction.indexOf('mouseLeave') !== -1;
  },
  isFocusToShow: function isFocusToShow() {
    var _props5 = this.props,
        action = _props5.action,
        showAction = _props5.showAction;

    return action.indexOf('focus') !== -1 || showAction.indexOf('focus') !== -1;
  },
  isBlurToHide: function isBlurToHide() {
    var _props6 = this.props,
        action = _props6.action,
        hideAction = _props6.hideAction;

    return action.indexOf('focus') !== -1 || hideAction.indexOf('blur') !== -1;
  },

  // 强制对齐popup浮层
  forcePopupAlign: function forcePopupAlign() {
    if (this.state.popupVisible && this.popupInstance && this.popupInstance.alignInstance) {
      this.popupInstance.alignInstance.forceAlign();
    }
  },

  // 执行this.props.children.props[type]及this.props[type]方法
  fireEvents: function fireEvents(type, e) {
    var childCallback = this.props.children.props[type];
    if (childCallback) {
      childCallback(e);
    }
    var callback = this.props[type];
    if (callback) {
      callback(e);
    }
  },

  // 组件卸载时隐藏浮层
  close: function close() {
    this.setPopupVisible(false);
  },

  render: function render() {
    var props = this.props;
    var children = props.children;

    // this.props.children只允许单个reactElement
    var child = _react2["default"].Children.only(children);
    var newChildProps = {};

    // 为this.props.children注入显示隐藏浮层的方法
    if (this.isClickToHide() || this.isClickToShow()) {
      newChildProps.onClick = this.onClick;
      newChildProps.onMouseDown = this.onMouseDown;
      newChildProps.onTouchStart = this.onTouchStart;
    } else {
      newChildProps.onClick = this.createTwoChains('onClick');
      newChildProps.onMouseDown = this.createTwoChains('onMouseDown');
      newChildProps.onTouchStart = this.createTwoChains('onTouchStart');
    }
    if (this.isMouseEnterToShow()) {
      newChildProps.onMouseEnter = this.onMouseEnter;
    } else {
      newChildProps.onMouseEnter = this.createTwoChains('onMouseEnter');
    }
    if (this.isMouseLeaveToHide()) {
      newChildProps.onMouseLeave = this.onMouseLeave;
    } else {
      newChildProps.onMouseLeave = this.createTwoChains('onMouseLeave');
    }
    if (this.isFocusToShow() || this.isBlurToHide()) {
      newChildProps.onFocus = this.onFocus;
      newChildProps.onBlur = this.onBlur;
    } else {
      newChildProps.onFocus = this.createTwoChains('onFocus');
      newChildProps.onBlur = this.createTwoChains('onBlur');
    }

    return _react2["default"].cloneElement(child, newChildProps);
  }
});

exports["default"] = Trigger;
module.exports = exports['default'];

Popup.js

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);

var _react = require('react');
var _react2 = _interopRequireDefault(_react);

var _reactDom = require('react-dom');
var _reactDom2 = _interopRequireDefault(_reactDom);

var _rcAlign = require('rc-align');
var _rcAlign2 = _interopRequireDefault(_rcAlign);

var _rcAnimate = require('rc-animate');
var _rcAnimate2 = _interopRequireDefault(_rcAnimate);

var _PopupInner = require('./PopupInner');
var _PopupInner2 = _interopRequireDefault(_PopupInner);

var _LazyRenderBox = require('./LazyRenderBox');
var _LazyRenderBox2 = _interopRequireDefault(_LazyRenderBox);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

var Popup = _react2["default"].createClass({
  displayName: 'Popup',

  propTypes: {
    visible: _react.PropTypes.bool,// 显隐状况
    style: _react.PropTypes.object,// 浮层元素的样式
    getClassNameFromAlign: _react.PropTypes.func,// 获取根据浮层对齐时的位置调整数据添加的样式类
    onAlign: _react.PropTypes.func,// 浮层对齐时的回调函数
    getRootDomNode: _react.PropTypes.func,// 获取RcTrigger组件的顶层dom节点,即浮层对齐时的参照节点
    align: _react.PropTypes.any,// 浮层对齐时的位置调整数据
    destroyPopupOnHide: _react.PropTypes.bool,// 浮层隐藏时,是否卸载该浮层元素
    className: _react.PropTypes.string,// 浮层的样式
    prefixCls: _react.PropTypes.string,// 浮层的样式类
    onMouseEnter: _react.PropTypes.func,
    onMouseLeave: _react.PropTypes.func
  },

  componentDidMount: function componentDidMount() {
    this.rootNode = this.getPopupDomNode();
  },

  // 浮层对齐时调整浮层的样式,同时触发this.props.onAlign回调
  onAlign: function onAlign(popupDomNode, align) {
    var props = this.props;
    var alignClassName = props.getClassNameFromAlign(props.align);
    var currentAlignClassName = props.getClassNameFromAlign(align);
    if (alignClassName !== currentAlignClassName) {
      this.currentAlignClassName = currentAlignClassName;
      popupDomNode.className = this.getClassName(currentAlignClassName);
    }
    props.onAlign(popupDomNode, align);
  },

  // 获取PopupInner组件实例的顶层dom节点
  getPopupDomNode: function getPopupDomNode() {
    return _reactDom2["default"].findDOMNode(this.refs.popup);
  },

  // 获取浮层对齐时的参照节点
  getTarget: function getTarget() {
    return this.props.getRootDomNode();
  },
  getMaskTransitionName: function getMaskTransitionName() {
    var props = this.props;
    var transitionName = props.maskTransitionName;
    var animation = props.maskAnimation;
    if (!transitionName && animation) {
      transitionName = props.prefixCls + '-' + animation;
    }
    return transitionName;
  },

  // 浮层显隐时添加的css动效
  getTransitionName: function getTransitionName() {
    var props = this.props;
    var transitionName = props.transitionName;
    if (!transitionName && props.animation) {
      transitionName = props.prefixCls + '-' + props.animation;
    }
    return transitionName;
  },
  // 浮层的样式类
  getClassName: function getClassName(currentAlignClassName) {
    return this.props.prefixCls + ' ' + this.props.className + ' ' + currentAlignClassName;
  },

  // 绘制浮层
  getPopupElement: function getPopupElement() {
    var props = this.props;
    var align = props.align,
        style = props.style,
        visible = props.visible,
        prefixCls = props.prefixCls,
        destroyPopupOnHide = props.destroyPopupOnHide;

    var className = this.getClassName(this.currentAlignClassName || props.getClassNameFromAlign(align));
    var hiddenClassName = prefixCls + '-hidden';
    if (!visible) {
      this.currentAlignClassName = null;
    }
    var newStyle = (0, _extends3["default"])({}, style, this.getZIndexStyle());
    var popupInnerProps = {
      className: className,
      prefixCls: prefixCls,
      ref: 'popup',
      onMouseEnter: props.onMouseEnter,
      onMouseLeave: props.onMouseLeave,
      style: newStyle
    };
    if (destroyPopupOnHide) {
      return _react2["default"].createElement(
        _rcAnimate2["default"],
        {
          component: '',
          exclusive: true,
          transitionAppear: true,
          transitionName: this.getTransitionName()
        },
        visible ? _react2["default"].createElement(
          _rcAlign2["default"],
          {
            target: this.getTarget,
            key: 'popup',
            ref: this.saveAlign,
            monitorWindowResize: true,
            align: align,
            onAlign: this.onAlign
          },
          _react2["default"].createElement(
            _PopupInner2["default"],
            (0, _extends3["default"])({
              visible: true
            }, popupInnerProps),
            props.children
          )
        ) : null
      );
    }
    return _react2["default"].createElement(
      _rcAnimate2["default"],
      {
        component: '',
        exclusive: true,
        transitionAppear: true,
        transitionName: this.getTransitionName(),
        showProp: 'xVisible'
      },
      _react2["default"].createElement(
        _rcAlign2["default"],
        {
          target: this.getTarget,
          key: 'popup',
          ref: this.saveAlign,
          monitorWindowResize: true,
          xVisible: visible,
          childrenProps: { visible: 'xVisible' },
          disabled: !visible,
          align: align,
          onAlign: this.onAlign
        },
        _react2["default"].createElement(
          _PopupInner2["default"],
          (0, _extends3["default"])({
            hiddenClassName: hiddenClassName
          }, popupInnerProps),
          props.children
        )
      )
    );
  },
  getZIndexStyle: function getZIndexStyle() {
    var style = {};
    var props = this.props;
    if (props.zIndex !== undefined) {
      style.zIndex = props.zIndex;
    }
    return style;
  },
  getMaskElement: function getMaskElement() {
    var props = this.props;
    var maskElement = void 0;
    if (props.mask) {
      var maskTransition = this.getMaskTransitionName();
      maskElement = _react2["default"].createElement(_LazyRenderBox2["default"], {
        style: this.getZIndexStyle(),
        key: 'mask',
        className: props.prefixCls + '-mask',
        hiddenClassName: props.prefixCls + '-mask-hidden',
        visible: props.visible
      });
      if (maskTransition) {
        maskElement = _react2["default"].createElement(
          _rcAnimate2["default"],
          {
            key: 'mask',
            showProp: 'visible',
            transitionAppear: true,
            component: '',
            transitionName: maskTransition
          },
          maskElement
        );
      }
    }
    return maskElement;
  },

  // rc-align实例的引用,供父组件Trigger中forcePopupAlign方法强制对齐使用
  saveAlign: function saveAlign(align) {
    this.alignInstance = align;
  },
  
  render: function render() {
    return _react2["default"].createElement(
      'div',
      null,
      this.getMaskElement(),
      this.getPopupElement()
    );
  }
});

exports["default"] = Popup;
module.exports = exports['default'];

PopupInner.js

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _react = require('react');
var _react2 = _interopRequireDefault(_react);

var _LazyRenderBox = require('./LazyRenderBox');
var _LazyRenderBox2 = _interopRequireDefault(_LazyRenderBox);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

var PopupInner = _react2["default"].createClass({
  displayName: 'PopupInner',

  propTypes: {
    hiddenClassName: _react.PropTypes.string,
    className: _react.PropTypes.string,
    prefixCls: _react.PropTypes.string,
    onMouseEnter: _react.PropTypes.func,
    onMouseLeave: _react.PropTypes.func,
    children: _react.PropTypes.any
  },
  render: function render() {
    var props = this.props;
    var className = props.className;
    if (!props.visible) {
      className += ' ' + props.hiddenClassName;
    }
    return _react2["default"].createElement(
      'div',
      {
        className: className,
        onMouseEnter: props.onMouseEnter,
        onMouseLeave: props.onMouseLeave,
        style: props.style
      },
      _react2["default"].createElement(
        _LazyRenderBox2["default"],
        { className: props.prefixCls + '-content', visible: props.visible },
        props.children// Trigger组件的props.popup
      )
    );
  }
});

exports["default"] = PopupInner;
module.exports = exports['default'];

LazyRenderBox.js

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');

var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

var LazyRenderBox = _react2["default"].createClass({
  displayName: 'LazyRenderBox',

  propTypes: {
    children: _react.PropTypes.any,
    className: _react.PropTypes.string,
    visible: _react.PropTypes.bool,
    hiddenClassName: _react.PropTypes.string
  },
  shouldComponentUpdate: function shouldComponentUpdate(nextProps) {
    // 根据浮层显隐情况决定是否重绘子组件
    return nextProps.hiddenClassName || nextProps.visible;
  },
  render: function render() {
    var _props = this.props,
        hiddenClassName = _props.hiddenClassName,
        visible = _props.visible,
        props = (0, _objectWithoutProperties3["default"])(_props, ['hiddenClassName', 'visible']);


    if (hiddenClassName || _react2["default"].Children.count(props.children) > 1) {
      if (!visible && hiddenClassName) {
        props.className += ' ' + hiddenClassName;
      }
      return _react2["default"].createElement('div', props);
    }

    return _react2["default"].Children.only(props.children);
  }
});

exports["default"] = LazyRenderBox;
module.exports = exports['default'];

utils.js

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

exports.getAlignFromPlacement = getAlignFromPlacement;
exports.getPopupClassNameFromAlign = getPopupClassNameFromAlign;

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function isPointsEq(a1, a2) {
  return a1[0] === a2[0] && a1[1] === a2[1];
}

function getAlignFromPlacement(builtinPlacements, placementStr, align) {
  var baseAlign = builtinPlacements[placementStr] || {};
  return (0, _extends3["default"])({}, baseAlign, align);
}

function getPopupClassNameFromAlign(builtinPlacements, prefixCls, align) {
  var points = align.points;
  for (var placement in builtinPlacements) {
    if (builtinPlacements.hasOwnProperty(placement)) {
      if (isPointsEq(builtinPlacements[placement].points, points)) {
        return prefixCls + '-placement-' + placement;
      }
    }
  }
  return '';
}

猜你喜欢

转载自schifred.iteye.com/blog/2364444
今日推荐