@alifd/next
Version:
A configurable component library for web built on React.
507 lines (436 loc) • 16.8 kB
JavaScript
'use strict';
exports.__esModule = true;
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _class, _temp;
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _reactLifecyclesCompat = require('react-lifecycles-compat');
var _overlay = require('../overlay');
var _overlay2 = _interopRequireDefault(_overlay);
var _util = require('../util');
var _inner = require('./inner');
var _inner2 = _interopRequireDefault(_inner);
var _alignMap = require('./alignMap');
var _util2 = require('./util');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var noop = _util.func.noop;
var Popup = _overlay2.default.Popup;
var alignList = ['t', 'r', 'b', 'l', 'tl', 'tr', 'bl', 'br', 'lt', 'lb', 'rt', 'rb'];
var alignMap = _alignMap.normalMap;
/** Balloon */
var Balloon = (_temp = _class = function (_React$Component) {
(0, _inherits3.default)(Balloon, _React$Component);
function Balloon(props, context) {
(0, _classCallCheck3.default)(this, Balloon);
var _this = (0, _possibleConstructorReturn3.default)(this, _React$Component.call(this, props, context));
_this.beforePosition = function (result, obj) {
var placement = result.config.placement;
if (placement !== _this.state.align) {
_this.setState({
align: placement,
innerAlign: true
});
}
if (_this.props.arrowPointToCenter) {
var _obj$target = obj.target,
width = _obj$target.width,
height = _obj$target.height;
if (placement.length === 2) {
var offset = _alignMap.normalMap[placement].offset;
switch (placement[0]) {
case 'b':
case 't':
{
var plus = offset[0] > 0 ? 1 : -1;
result.style.left = result.style.left + plus * width / 2 - offset[0];
}
break;
case 'l':
case 'r':
{
var _plus = offset[0] > 0 ? 1 : -1;
result.style.top = result.style.top + _plus * height / 2 - offset[1];
}
break;
}
}
}
return result;
};
_this.state = {
align: alignList.includes(props.align) ? props.align : 'b',
visible: 'visible' in props ? props.visible : props.defaultVisible
};
_this._onClose = _this._onClose.bind(_this);
_this._onPosition = _this._onPosition.bind(_this);
_this._onVisibleChange = _this._onVisibleChange.bind(_this);
return _this;
}
Balloon.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
var nextState = {};
if ('visible' in nextProps) {
nextState.visible = nextProps.visible;
}
if (!prevState.innerAlign && 'align' in nextProps && alignList.includes(nextProps.align) && nextProps.align !== prevState.align) {
nextState.align = nextProps.align;
nextState.innerAlign = false;
}
return nextState;
};
Balloon.prototype._onVisibleChange = function _onVisibleChange(visible, trigger) {
// Not Controlled
if (!('visible' in this.props)) {
this.setState({
visible: visible
});
}
this.props.onVisibleChange(visible, trigger);
if (!visible) {
this.props.onClose();
}
};
Balloon.prototype._onClose = function _onClose(e) {
this._onVisibleChange(false, 'closeClick');
//必须加上preventDefault,否则单测IE下报错,出现full page reload 异常
e.preventDefault();
};
Balloon.prototype._onPosition = function _onPosition(res) {
var rtl = this.props.rtl;
alignMap = this.props.alignEdge ? _alignMap.edgeMap : _alignMap.normalMap;
var newAlign = res.align.join(' ');
var resAlign = void 0;
var alignKey = 'align';
if (rtl) {
alignKey = 'rtlAlign';
}
for (var key in alignMap) {
if (alignMap[key][alignKey] === newAlign) {
resAlign = key;
break;
}
}
resAlign = resAlign || this.state.align;
if (resAlign !== this.state.align) {
this.setState({
align: resAlign,
innerAlign: true
});
}
};
Balloon.prototype.render = function render() {
var _props = this.props,
id = _props.id,
type = _props.type,
prefix = _props.prefix,
className = _props.className,
title = _props.title,
alignEdge = _props.alignEdge,
trigger = _props.trigger,
triggerType = _props.triggerType,
children = _props.children,
closable = _props.closable,
shouldUpdatePosition = _props.shouldUpdatePosition,
delay = _props.delay,
needAdjust = _props.needAdjust,
autoAdjust = _props.autoAdjust,
safeId = _props.safeId,
autoFocus = _props.autoFocus,
safeNode = _props.safeNode,
onClick = _props.onClick,
onHover = _props.onHover,
animation = _props.animation,
offset = _props.offset,
style = _props.style,
container = _props.container,
popupContainer = _props.popupContainer,
cache = _props.cache,
popupStyle = _props.popupStyle,
popupClassName = _props.popupClassName,
popupProps = _props.popupProps,
followTrigger = _props.followTrigger,
rtl = _props.rtl,
v2 = _props.v2,
arrowPointToCenter = _props.arrowPointToCenter,
_props$placementOffse = _props.placementOffset,
placementOffset = _props$placementOffse === undefined ? 0 : _props$placementOffse,
others = (0, _objectWithoutProperties3.default)(_props, ['id', 'type', 'prefix', 'className', 'title', 'alignEdge', 'trigger', 'triggerType', 'children', 'closable', 'shouldUpdatePosition', 'delay', 'needAdjust', 'autoAdjust', 'safeId', 'autoFocus', 'safeNode', 'onClick', 'onHover', 'animation', 'offset', 'style', 'container', 'popupContainer', 'cache', 'popupStyle', 'popupClassName', 'popupProps', 'followTrigger', 'rtl', 'v2', 'arrowPointToCenter', 'placementOffset']);
if (container) {
_util.log.deprecated('container', 'popupContainer', 'Balloon');
}
var align = this.state.align;
alignMap = alignEdge || v2 ? _alignMap.edgeMap : _alignMap.normalMap;
var _prefix = this.context.prefix || prefix;
var trOrigin = 'trOrigin';
if (rtl) {
trOrigin = 'rtlTrOrigin';
}
var _offset = [alignMap[align].offset[0] + offset[0], alignMap[align].offset[1] + offset[1]];
var transformOrigin = alignMap[align][trOrigin];
var _style = (0, _extends3.default)({ transformOrigin: transformOrigin }, style);
var content = _react2.default.createElement(
_inner2.default,
(0, _extends3.default)({}, _util.obj.pickOthers(Object.keys(Balloon.propTypes), others), {
id: id,
title: title,
prefix: _prefix,
closable: closable,
onClose: this._onClose,
className: className,
style: _style,
align: align,
type: type,
rtl: rtl,
alignEdge: alignEdge,
v2: v2
}),
children
);
var triggerProps = {};
triggerProps['aria-describedby'] = id;
triggerProps.tabIndex = '0';
var ariaTrigger = id ? _react2.default.cloneElement(trigger, triggerProps) : trigger;
var newTrigger = (0, _util2.getDisabledCompatibleTrigger)(_react2.default.isValidElement(ariaTrigger) ? ariaTrigger : _react2.default.createElement(
'span',
null,
ariaTrigger
));
var otherProps = {
delay: delay,
shouldUpdatePosition: shouldUpdatePosition,
needAdjust: needAdjust,
align: alignMap[align].align,
offset: _offset,
safeId: safeId,
onHover: onHover,
onPosition: this._onPosition
};
if (v2) {
delete otherProps.align;
delete otherProps.shouldUpdatePosition;
delete otherProps.needAdjust;
delete otherProps.offset;
delete otherProps.safeId;
delete otherProps.onHover;
delete otherProps.onPosition;
(0, _extends3.default)(otherProps, {
placement: align,
placementOffset: placementOffset + 12,
v2: true,
beforePosition: this.beforePosition,
autoAdjust: autoAdjust
});
}
return _react2.default.createElement(
Popup,
(0, _extends3.default)({}, popupProps, {
followTrigger: followTrigger,
trigger: newTrigger,
cache: cache,
triggerType: triggerType,
visible: this.state.visible,
onClick: onClick,
afterClose: this.props.afterClose,
onVisibleChange: this._onVisibleChange,
animation: animation,
autoFocus: triggerType === 'focus' ? false : autoFocus,
safeNode: safeNode,
container: popupContainer || container,
className: popupClassName,
style: popupStyle,
rtl: rtl
}, otherProps),
content
);
};
return Balloon;
}(_react2.default.Component), _class.contextTypes = {
prefix: _propTypes2.default.string
}, _class.propTypes = {
prefix: _propTypes2.default.string,
pure: _propTypes2.default.bool,
rtl: _propTypes2.default.bool,
/**
* 自定义类名
*/
className: _propTypes2.default.string,
/**
* 自定义内敛样式
*/
style: _propTypes2.default.object,
/**
* 浮层的内容
*/
children: _propTypes2.default.any,
size: _propTypes2.default.string,
/**
* 样式类型
*/
type: _propTypes2.default.oneOf(['normal', 'primary']),
/**
* 标题
* @version 1.23
*/
title: _propTypes2.default.node,
/**
* 弹层当前显示的状态
*/
visible: _propTypes2.default.bool,
/**
* 弹层默认显示的状态
*/
defaultVisible: _propTypes2.default.bool,
/**
* 弹层在显示和隐藏触发的事件
* @param {Boolean} visible 弹层是否隐藏和显示
* @param {String} type 触发弹层显示或隐藏的来源, closeClick 表示由自带的关闭按钮触发; fromTrigger 表示由trigger的点击触发; docClick 表示由document的点击触发
*/
onVisibleChange: _propTypes2.default.func,
alignEdge: _propTypes2.default.bool,
/**
* 开启 v2 版本
* @version 1.25
*/
v2: _propTypes2.default.bool,
/**
* [v2] 箭头是否指向目标元素的中心
* @version 1.25
*/
arrowPointToCenter: _propTypes2.default.bool,
/**
* [v2] 弹层偏离触发元素的像素值
*/
placementOffset: _propTypes2.default.number,
/**
* 是否显示关闭按钮
*/
closable: _propTypes2.default.bool,
/**
* 弹出层位置
* @enumdesc 上, 右, 下, 左, 上左, 上右, 下左, 下右, 左上, 左下, 右上, 右下
*/
align: _propTypes2.default.oneOf(alignList),
/**
* 弹层相对于trigger的定位的微调, 接收数组[hoz, ver], 表示弹层在 left / top 上的增量
* e.g. [100, 100] 表示往右(RTL 模式下是往左) 、下分布偏移100px
*/
offset: _propTypes2.default.array,
/**
* 触发元素
*/
trigger: _propTypes2.default.any,
/**
* 触发行为
* 鼠标悬浮, 鼠标点击('hover','click')或者它们组成的数组,如 ['hover', 'click'], 强烈不建议使用'focus',若弹窗内容有复杂交互请使用click
*/
triggerType: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.array]),
onClick: _propTypes2.default.func,
/**
* 任何visible为false时会触发的事件
*/
onClose: _propTypes2.default.func,
onHover: _propTypes2.default.func,
/**
* [v2] 是否进行自动位置调整,默认自动开启。
* @version 1.25
*/
autoAdjust: _propTypes2.default.bool,
needAdjust: _propTypes2.default.bool,
/**
* 弹层在触发以后的延时显示, 单位毫秒 ms
*/
delay: _propTypes2.default.number,
/**
* 浮层关闭后触发的事件, 如果有动画,则在动画结束后触发
*/
afterClose: _propTypes2.default.func,
shouldUpdatePosition: _propTypes2.default.bool,
/**
* 弹层出现后是否自动focus到内部第一个元素
*/
autoFocus: _propTypes2.default.bool,
/**
* 安全节点:对于triggetType为click的浮层,会在点击除了浮层外的其它区域时关闭浮层.safeNode用于添加不触发关闭的节点, 值可以是dom节点的id或者是节点的dom对象
*/
safeNode: _propTypes2.default.string,
/**
* 用来指定safeNode节点的id,和safeNode配合使用
*/
safeId: _propTypes2.default.string,
/**
* 配置动画的播放方式,格式是{in: '', out: ''}, 常用的动画class请查看Animate组件文档
* @param {String} in 进场动画
* @param {String} out 出场动画
*/
animation: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.bool]),
/**
* 弹层的dom节点关闭时是否删除
*/
cache: _propTypes2.default.bool,
/**
* 指定浮层渲染的父节点, 可以为节点id的字符串,也可以返回节点的函数。
*/
popupContainer: _propTypes2.default.any,
container: _propTypes2.default.any,
/**
* 弹层组件style,透传给Popup
*/
popupStyle: _propTypes2.default.object,
/**
* 弹层组件className,透传给Popup
*/
popupClassName: _propTypes2.default.string,
/**
* 弹层组件属性,透传给Popup
*/
popupProps: _propTypes2.default.object,
/**
* 是否跟随滚动
*/
followTrigger: _propTypes2.default.bool,
/**
* 弹层id, 传入值才会支持无障碍
*/
id: _propTypes2.default.string
}, _class.defaultProps = {
prefix: 'next-',
pure: false,
type: 'normal',
closable: true,
defaultVisible: false,
size: 'medium',
alignEdge: false,
arrowPointToCenter: false,
align: 'b',
offset: [0, 0],
trigger: _react2.default.createElement('span', null),
onClose: noop,
afterClose: noop,
onVisibleChange: noop,
needAdjust: false,
triggerType: 'hover',
safeNode: undefined,
safeId: null,
autoFocus: true,
animation: {
in: 'zoomIn zoomInBig',
out: 'zoomOut zoomOutBig'
},
cache: false,
popupStyle: {},
popupClassName: '',
popupProps: {}
}, _temp);
Balloon.displayName = 'Balloon';
exports.default = (0, _reactLifecyclesCompat.polyfill)(Balloon);
module.exports = exports['default'];