UNPKG

zent

Version:

一套前端设计语言和基于React的实现

353 lines (278 loc) 11.6 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports['default'] = exports.PopoverContextType = undefined; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _class, _temp, _initialiseProps; /** * 设计: * * Popover组件只是一个壳子,负责组装Trigger和Content。 * * 弹层实际的打开/关闭都是Content完成的,而什么情况打开弹层是Trigger控制的。 */ var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _reactDom = require('react-dom'); var _reactDom2 = _interopRequireDefault(_reactDom); var _classnames = require('zent-utils/classnames'); var _classnames2 = _interopRequireDefault(_classnames); var _noop = require('zent-utils/lodash/noop'); var _noop2 = _interopRequireDefault(_noop); var _uniqueId = require('zent-utils/lodash/uniqueId'); var _uniqueId2 = _interopRequireDefault(_uniqueId); var _isFunction = require('zent-utils/lodash/isFunction'); var _isFunction2 = _interopRequireDefault(_isFunction); var _isBoolean = require('zent-utils/lodash/isBoolean'); var _isBoolean2 = _interopRequireDefault(_isBoolean); var _isPromise = require('zent-utils/isPromise'); var _isPromise2 = _interopRequireDefault(_isPromise); var _Content = require('./Content'); var _Content2 = _interopRequireDefault(_Content); var _Trigger = require('./trigger/Trigger'); var _Trigger2 = _interopRequireDefault(_Trigger); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var SKIPPED = function SKIPPED() {}; function instanceOf(MaybeDerive, Base) { return MaybeDerive === Base || MaybeDerive.prototype instanceof Base; } function handleBeforeHook(beforeFn, arity, continuation) { // 有参数,传入continuation,由外部去控制何时调用 if (arity >= 1) { return beforeFn(continuation); } // 无参数,如果返回Promise那么resolve后调用continuation;如果返回不是Promise,直接调用Promise var mayBePromise = beforeFn(); if (!(0, _isPromise2['default'])(mayBePromise) && mayBePromise !== SKIPPED) { return continuation(); } mayBePromise.then(continuation); } var PopoverContextType = exports.PopoverContextType = { popover: _react.PropTypes.shape({ close: _react.PropTypes.func.isRequired, open: _react.PropTypes.func.isRequired, getContentNode: _react.PropTypes.func.isRequired, getTriggerNode: _react.PropTypes.func.isRequired }) }; var Popover = (_temp = _class = function (_Component) { _inherits(Popover, _Component); _createClass(Popover, [{ key: 'getChildContext', value: function getChildContext() { return { popover: { close: this.close, open: this.open, getContentNode: this.getPopoverNode, getTriggerNode: this.getTriggerNode } }; } }]); function Popover(props) { _classCallCheck(this, Popover); // id用来唯一标识popover实例 var _this = _possibleConstructorReturn(this, (Popover.__proto__ || Object.getPrototypeOf(Popover)).call(this, props)); _initialiseProps.call(_this); _this.id = (0, _uniqueId2['default'])(props.prefix + '-popover-internal-id-'); if (!_this.isVisibilityControlled(props)) { _this.state = { visible: false }; } return _this; } _createClass(Popover, [{ key: 'isVisibilityControlled', value: function isVisibilityControlled(props) { var _ref = props || this.props, visible = _ref.visible, onVisibleChange = _ref.onVisibleChange; var hasOnChange = (0, _isFunction2['default'])(onVisibleChange); var hasVisible = (0, _isBoolean2['default'])(visible); if (hasVisible && !hasOnChange || hasOnChange && !hasVisible) { throw new Error('visible and onVisibleChange must be used together'); } return hasVisible && hasOnChange; } }, { key: 'validateChildren', value: function validateChildren() { var children = this.props.children; var childArray = _react.Children.toArray(children); if (childArray.length !== 2) { throw new Error('There must be one and only one trigger and content in Popover'); } var _childArray$reduce = childArray.reduce(function (state, c) { var type = c.type; if (instanceOf(type, _Trigger2['default'])) { state.trigger = c; } else if (instanceOf(type, _Content2['default'])) { state.content = c; } return state; }, { trigger: null, content: null }), trigger = _childArray$reduce.trigger, content = _childArray$reduce.content; if (!trigger) { throw new Error('Missing trigger in Popover'); } if (!content) { throw new Error('Missing content in Popover'); } return { trigger: trigger, content: content }; } }, { key: 'componentDidMount', value: function componentDidMount() { if (this.isVisibilityControlled() && this.props.visible) { this.props.onShow(); } } }, { key: 'componentDidUpdate', value: function componentDidUpdate(prevProps, prevState) { var visible = this.getVisible(); if (visible !== this.getVisible(prevProps, prevState)) { var afterHook = visible ? this.props.onShow : this.props.onClose; afterHook(); } } }, { key: 'render', value: function render() { var _validateChildren = this.validateChildren(), trigger = _validateChildren.trigger, content = _validateChildren.content; var _props = this.props, display = _props.display, prefix = _props.prefix, className = _props.className, wrapperClassName = _props.wrapperClassName, containerSelector = _props.containerSelector, position = _props.position, cushion = _props.cushion; var visible = this.getVisible(); return _react2['default'].createElement( 'div', { style: { display: display }, className: (0, _classnames2['default'])(prefix + '-popover-wrapper', wrapperClassName) }, _react2['default'].cloneElement(trigger, { prefix: prefix, contentVisible: visible, onTriggerRefChange: this.onTriggerRefChange, getTriggerNode: this.getTriggerNode, getContentNode: this.getPopoverNode, open: this.open, close: this.close }), _react2['default'].cloneElement(content, { prefix: prefix, className: className, id: this.id, getContentNode: this.getPopoverNode, getAnchor: this.getTriggerNode, visible: visible, cushion: cushion, containerSelector: containerSelector, placement: position }) ); } }]); return Popover; }(_react.Component), _class.propTypes = { prefix: _react.PropTypes.string, className: _react.PropTypes.string, // custom classname for trigger wrapper wrapperClassName: _react.PropTypes.string, // container的display属性 display: _react.PropTypes.string, // position strategy position: _react.PropTypes.func.isRequired, // 定位时的偏移量 cushion: _react.PropTypes.number, // 只有用户触发的打开/关闭才会触发这两个毁掉 onBeforeClose: _react.PropTypes.func, onBeforeShow: _react.PropTypes.func, // 不管打开/关闭时如何触发的都会被调用 onClose: _react.PropTypes.func, onShow: _react.PropTypes.func, // defaults to body containerSelector: _react.PropTypes.string, children: _react.PropTypes.node.isRequired, // 两个必须一起出现 visible: _react.PropTypes.bool, onVisibleChange: _react.PropTypes.func }, _class.defaultProps = { prefix: 'zent', className: '', wrapperClassName: '', display: 'block', onBeforeClose: _noop2['default'], onBeforeShow: _noop2['default'], onClose: _noop2['default'], onShow: _noop2['default'], cushion: 0, containerSelector: 'body' }, _class.childContextTypes = PopoverContextType, _initialiseProps = function _initialiseProps() { var _this2 = this; this.getVisible = function (props, state) { if (_this2.isVisibilityControlled(props)) { props = props || _this2.props; return props.visible; } state = state || _this2.state; return state.visible; }; this.setVisible = function (visible, props, state) { props = props || _this2.props; state = state || _this2.state; var beforeHook = visible ? props.onBeforeShow : props.onBeforeClose; var onBefore = function onBefore() { // 确保pending的时候不会触发多次beforeHook if (_this2.pendingOnBeforeHook) { return SKIPPED; } _this2.pendingOnBeforeHook = true; return beforeHook.apply(undefined, arguments); }; if (_this2.isVisibilityControlled(props)) { if (_this2.pendingOnBeforeHook || props.visible === visible) { return; } handleBeforeHook(onBefore, beforeHook.length, function () { props.onVisibleChange(visible); _this2.pendingOnBeforeHook = false; }); } else { if (_this2.pendingOnBeforeHook || state.visible === visible) { return; } handleBeforeHook(onBefore, beforeHook.length, function () { _this2.setState({ visible: visible }); _this2.pendingOnBeforeHook = false; }); } }; this.getPopoverNode = function () { return document.querySelector('.' + _this2.id); }; this.onTriggerRefChange = function (triggerInstance) { _this2.triggerNode = _reactDom2['default'].findDOMNode(triggerInstance); }; this.getTriggerNode = function () { return _this2.triggerNode; }; this.open = function () { _this2.setVisible(true); }; this.close = function () { _this2.setVisible(false); }; }, _temp); exports['default'] = Popover;