wix-style-react
Version:
wix-style-react
442 lines (389 loc) • 15.6 kB
JavaScript
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
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 _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
var _class, _temp;
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return 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; }
import noop from 'lodash/noop';
import React from 'react';
import PropTypes from 'prop-types';
import WixComponent from '../../BaseComponents/WixComponent';
import styles from './Tooltip.scss';
import Popper from 'popper.js';
import classNames from 'classnames';
var TooltipRefreshRate = 20;
var Tooltip = (_temp = _class = function (_WixComponent) {
_inherits(Tooltip, _WixComponent);
function Tooltip(props) {
_classCallCheck(this, Tooltip);
var _this = _possibleConstructorReturn(this, (Tooltip.__proto__ || Object.getPrototypeOf(Tooltip)).call(this, props));
_this.placementFlipMap = {
top: 'bottom',
left: 'right',
right: 'left',
bottom: 'top'
};
_this.alignmentMap = {
top: 'start',
right: 'end',
bottom: 'end',
left: 'start',
center: ''
};
_this.state = {
placement: _this.getPopperPlacement(props.placement, props.alignment),
active: props.active
};
_this.handlePopperUpdate = _this.handlePopperUpdate.bind(_this);
_this.handleHideTrigger = _this.handleHideTrigger.bind(_this);
_this.handleShowTrigger = _this.handleShowTrigger.bind(_this);
return _this;
}
_createClass(Tooltip, [{
key: 'componentElements',
value: function componentElements() {
return [this.target.children[0], this.content.children[0]];
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
_get(Tooltip.prototype.__proto__ || Object.getPrototypeOf(Tooltip.prototype), 'componentDidMount', this).call(this);
var placement = this.state.placement;
var target = this.target.children[0];
var content = this.content.children[0];
this.popper = new Popper(target, content, {
placement: placement,
modifiers: {
applyStyle: { enabled: false }
},
onUpdate: this.handlePopperUpdate,
onCreate: this.handlePopperUpdate
});
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
_get(Tooltip.prototype.__proto__ || Object.getPrototypeOf(Tooltip.prototype), 'componentWillUnmount', this).call(this);
this.popper.destroy();
clearInterval(this.scheduleInterval);
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
this.handleNextActive(nextProps);
this.handleNextMoveBy(nextProps);
}
//Schedule popper updates periodically, only when the tooltip is visible (for
//tooltip repositioning - e.g. when the target dimensions change).
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps) {
var _this2 = this;
_get(Tooltip.prototype.__proto__ || Object.getPrototypeOf(Tooltip.prototype), 'componentDidUpdate', this).call(this, prevProps);
if (this.state.active && !this.scheduleInterval) {
this.scheduleInterval = setInterval(function () {
_this2.popper.scheduleUpdate();
}, TooltipRefreshRate);
this.props.onShow();
} else if (!this.state.active) {
clearInterval(this.scheduleInterval);
this.scheduleInterval = null;
}
}
}, {
key: 'onClickOutside',
value: function onClickOutside(e) {
if (this.props.shouldCloseOnClickOutside) {
this.hide();
} else {
this.props.onClickOutside(e);
}
}
}, {
key: 'hide',
value: function hide() {
this.toggleActive(false);
}
}, {
key: 'toggleActive',
value: function toggleActive(active) {
this.setState({ active: active });
}
}, {
key: 'handleNextMoveBy',
value: function handleNextMoveBy(nextProps) {
var hasChanged = nextProps.moveBy.x !== this.props.moveBy.x || nextProps.moveBy.y !== this.props.moveBy.y;
if (hasChanged) {
this.moveBy = nextProps.moveBy;
this.popper.update();
}
}
}, {
key: 'handleNextActive',
value: function handleNextActive(nextProps) {
var nextActive = nextProps.active;
var currentlyActive = this.props.active;
if (nextProps.showTrigger === 'custom' && nextActive && !currentlyActive) {
this.toggleActive(true);
} else if (nextProps.hideTrigger === 'custom' && !nextActive && currentlyActive) {
this.toggleActive(false);
}
}
}, {
key: 'handlePopperUpdate',
value: function handlePopperUpdate(data) {
var hasChangedPlacement = data.placement !== this.state.placement;
if (hasChangedPlacement) {
this.setState({
placement: data.placement
});
}
this.setState({ popperData: data });
}
}, {
key: 'handleTrigger',
value: function handleTrigger() {
var originalCallback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : noop;
var triggerType = arguments[1];
var _props = this.props,
showTrigger = _props.showTrigger,
hideTrigger = _props.hideTrigger;
var active = this.state.active;
if (showTrigger === hideTrigger && showTrigger === triggerType) {
if (active) {
this.handleHideTrigger();
} else {
this.handleShowTrigger();
}
} else if (showTrigger === triggerType) {
this.handleShowTrigger();
} else if (hideTrigger === triggerType) {
this.handleHideTrigger();
}
originalCallback();
}
}, {
key: 'handleHideTrigger',
value: function handleHideTrigger() {
this.handleToggleWithDelay(false);
}
}, {
key: 'handleShowTrigger',
value: function handleShowTrigger() {
this.handleToggleWithDelay(true);
}
}, {
key: 'handleToggleWithDelay',
value: function handleToggleWithDelay(toggle) {
var _this3 = this;
clearTimeout(this.mouseTimeout);
this.mouseTimeout = setTimeout(function () {
_this3.toggleActive(toggle);
}, toggle ? this.props.showDelay : this.props.hideDelay);
}
}, {
key: 'getPopperPlacement',
value: function getPopperPlacement(placement, alignment) {
var popperAlignment = this.alignmentMap[alignment];
if (alignment) {
return placement + '-' + popperAlignment;
}
return placement;
}
}, {
key: 'getArrowPlacement',
value: function getArrowPlacement(popperPlacement) {
var overrideArrowPlacement = this.props.arrowPlacement;
return overrideArrowPlacement || this.placementFlipMap[popperPlacement];
}
}, {
key: 'placementWithoutAlignment',
value: function placementWithoutAlignment(placement) {
return placement.replace(/-.*/, '');
}
}, {
key: 'getPopperStyle',
value: function getPopperStyle() {
var data = this.state.popperData;
if (!data) {
return {};
}
var left = Math.round(data.offsets.popper.left);
var top = Math.round(data.offsets.popper.top);
var transform = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
return {
position: data.offsets.popper.position,
transform: transform,
WebkitTransform: transform,
left: this.props.moveBy.x,
top: this.props.moveBy.y
};
}
}, {
key: 'getArrowStyle',
value: function getArrowStyle() {
var _props2 = this.props,
moveArrowTo = _props2.moveArrowTo,
arrowStyle = _props2.arrowStyle;
var placement = this.placementWithoutAlignment(this.props.placement);
var isVertical = placement === 'top' || placement === 'bottom';
var isHorizontal = placement === 'left' || placement === 'right';
if (moveArrowTo) {
var repositionStyle = {};
if (isVertical) {
if (moveArrowTo > 0) {
repositionStyle.left = moveArrowTo;
repositionStyle.right = 'inherit';
} else {
repositionStyle.right = -1 * moveArrowTo;
repositionStyle.left = 'inherit';
}
} else if (isHorizontal) {
if (moveArrowTo > 0) {
repositionStyle.top = moveArrowTo;
repositionStyle.bottom = 'inherit';
} else {
repositionStyle.bottom = -1 * moveArrowTo;
repositionStyle.top = 'inherit';
}
}
return _extends({}, repositionStyle, arrowStyle);
}
return arrowStyle;
}
}, {
key: 'render',
value: function render() {
var _this4 = this;
var _props3 = this.props,
theme = _props3.theme,
bounce = _props3.bounce,
disabled = _props3.disabled,
maxWidth = _props3.maxWidth,
zIndex = _props3.zIndex,
textAlign = _props3.textAlign,
size = _props3.size,
targetStyle = _props3.targetStyle;
var placement = this.placementWithoutAlignment(this.state.placement);
var arrowPlacement = this.getArrowPlacement(placement);
var active = this.state.active;
active = active && !disabled;
var clonedTarget = React.cloneElement(this.props.children, {
onMouseEnter: function onMouseEnter() {
return _this4.handleTrigger(_this4.props.children.props.onMouseEnter, 'mouseenter');
},
onMouseLeave: function onMouseLeave() {
return _this4.handleTrigger(_this4.props.children.props.onMouseLeave, 'mouseleave');
},
onClick: function onClick() {
return _this4.handleTrigger(_this4.props.children.props.onClick, 'click');
},
onFocus: function onFocus() {
return _this4.handleTrigger(_this4.props.children.props.onFocus, 'focus');
},
onBlur: function onBlur() {
return _this4.handleTrigger(_this4.props.children.props.onBlur, 'blur');
}
});
var popperStyle = this.getPopperStyle();
var arrowStyle = this.getArrowStyle();
return React.createElement(
'div',
{ className: styles.root, style: targetStyle },
React.createElement(
'div',
{
ref: function ref(r) {
return _this4.target = r;
},
'data-hook': 'target',
className: 'targetWrapper'
},
clonedTarget
),
React.createElement(
'div',
{ ref: function ref(r) {
return _this4.content = r;
} },
React.createElement(
'div',
{
className: classNames(styles.tooltip, _defineProperty({}, styles.active, active)),
style: _extends({ zIndex: zIndex }, popperStyle),
'data-hook': 'tooltip'
},
React.createElement(
'div',
{
className: classNames(_defineProperty({}, styles['bounce-' + arrowPlacement], bounce))
},
React.createElement(
'div',
{
className: classNames(styles.tooltipInner, styles[theme], styles[placement], styles[size], _defineProperty({}, styles.active, active)),
style: { maxWidth: maxWidth },
'data-hook': 'tooltip-inner'
},
React.createElement(
'div',
{ 'data-hook': 'tooltip-content', style: { textAlign: textAlign } },
this.props.content
),
React.createElement('div', {
className: classNames(styles.arrow, styles[arrowPlacement]),
style: arrowStyle
})
)
)
)
)
);
}
}]);
return Tooltip;
}(WixComponent), _class.propTypes = {
content: PropTypes.any.isRequired,
children: PropTypes.node.isRequired,
placement: PropTypes.oneOf(['top', 'right', 'bottom', 'left']),
alignment: PropTypes.oneOf(['top', 'right', 'bottom', 'left', 'center']),
theme: PropTypes.oneOf(['light', 'dark', 'error']),
showDelay: PropTypes.number,
hideDelay: PropTypes.number,
showTrigger: PropTypes.oneOf(['custom', 'mouseenter', 'mouseleave', 'click', 'focus', 'blur']),
hideTrigger: PropTypes.oneOf(['custom', 'mouseenter', 'mouseleave', 'click', 'focus', 'blur']),
active: PropTypes.bool,
arrowPlacement: PropTypes.string,
arrowStyle: PropTypes.object,
moveBy: PropTypes.object,
disabled: PropTypes.bool,
maxWidth: PropTypes.string,
zIndex: PropTypes.number,
textAlign: PropTypes.string,
moveArrowTo: PropTypes.number,
targetStyle: PropTypes.any,
bounce: PropTypes.bool,
shouldCloseOnClickOutside: PropTypes.bool,
onClickOutside: PropTypes.func,
onShow: PropTypes.func,
size: PropTypes.oneOf(['normal', 'large'])
}, _class.defaultProps = {
placement: 'top',
theme: 'light',
showDelay: 200,
hideDelay: 500,
showTrigger: 'mouseenter',
hideTrigger: 'mouseleave',
active: false,
moveBy: { x: 0, y: 0 },
disabled: false,
maxWidth: '1200px',
zIndex: 2000,
textAlign: 'center',
onClickOutside: noop,
onShow: noop,
size: 'normal'
}, _temp);
export { Tooltip as default };