chayns-components
Version:
A set of beautiful React components for developing chayns® applications.
313 lines (309 loc) • 11.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _clsx = _interopRequireDefault(require("clsx"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _react = _interopRequireWildcard(require("react"));
var _Bubble = _interopRequireDefault(require("../../react-chayns-bubble/component/Bubble"));
var _Button = _interopRequireDefault(require("../../react-chayns-button/component/Button"));
var _Icon = _interopRequireDefault(require("../../react-chayns-icon/component/Icon"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/**
* @component
*/
let currentId = 0;
const PREFIX = 'CC_TOOLTIP_';
/**
* Wraps a child component and displays a message when the child is hovered or
* clicked on. Allows to be shown imperatively by calling `.show()` or `.hide()`
* on its reference.
*/
class Tooltip extends _react.Component {
constructor(props) {
super(props);
this.state = {
position: null,
x: 0,
y: 0
};
this.show = this.show.bind(this);
this.hide = this.hide.bind(this);
this.getContent = this.getContent.bind(this);
this.getPosition = this.getPosition.bind(this);
this.tooltipKey = `${PREFIX}${currentId++}`;
this.bubble = /*#__PURE__*/_react.default.createRef();
this.childrenWrapper = /*#__PURE__*/_react.default.createRef();
}
componentDidMount() {
this.getPosition();
}
componentDidUpdate(prevProps) {
const {
coordinates,
position
} = this.props;
if (prevProps.coordinates !== coordinates || prevProps.position !== position) {
this.getPosition();
}
}
getContent() {
const {
content
} = this.props;
if (content.html) {
return content.html;
}
const nodeArray = [/*#__PURE__*/_react.default.createElement("p", {
key: `p${this.tooltipKey}`
}, content.text)];
if (content.imageUrl) {
nodeArray.unshift( /*#__PURE__*/_react.default.createElement("div", {
key: `divImg${this.tooltipKey}`,
className: "cc__tooltip__image",
style: {
backgroundImage: `url(${content.imageUrl})`
}
}));
}
if (content.headline) {
nodeArray.unshift( /*#__PURE__*/_react.default.createElement("h5", {
key: `h5${this.tooltipKey}`
}, content.headline));
}
if (content.buttonText && content.buttonOnClick) {
nodeArray.push( /*#__PURE__*/_react.default.createElement("div", {
className: "cc__tooltip__button",
key: `divBtn${this.tooltipKey}`
}, /*#__PURE__*/_react.default.createElement(_Button.default, {
onClick: content.buttonOnClick
}, content.buttonText)));
}
return nodeArray;
}
async getPosition() {
var _chayns$env;
const {
position,
coordinates,
parent,
removeParentSpace
} = this.props;
const {
position: statePosition,
x: stateX,
y: stateY
} = this.state;
let x = coordinates ? coordinates.x : 0;
let top = coordinates ? coordinates.y : 0;
let bottom = coordinates ? coordinates.y : 0;
if (this.childrenWrapper && !coordinates) {
const rect = this.childrenWrapper.current.getBoundingClientRect();
x = rect.left + rect.width / 2;
top = rect.top;
bottom = rect.bottom;
}
let pos = position;
if (position === null) {
const posArray = x > window.innerWidth / 2 ? [Tooltip.position.TOP_LEFT, Tooltip.position.BOTTOM_LEFT] : [Tooltip.position.TOP_RIGHT, Tooltip.position.BOTTOM_RIGHT];
pos = (top + bottom) / 2 > window.innerHeight / 2 ? posArray[0] : posArray[1];
}
let y = _Bubble.default.isPositionBottom(pos) ? bottom : top;
if (typeof chayns !== 'undefined' && (_chayns$env = chayns.env) !== null && _chayns$env !== void 0 && _chayns$env.isApp) {
const {
pageYOffset
} = await chayns.getWindowMetrics();
y += pageYOffset;
}
if (removeParentSpace) {
const parentRect = (parent || document.getElementsByClassName('tapp')[0] || document.body).getBoundingClientRect();
x -= parentRect.left;
y -= parentRect.top;
}
if (statePosition !== pos || x !== stateX || y !== stateY) {
this.setState({
position: pos,
x,
y
});
}
}
show() {
this.getPosition();
if (this.bubble.current) {
this.bubble.current.show();
}
}
hide(ev) {
const {
stopPropagation
} = this.props;
if (ev && stopPropagation) {
ev.stopPropagation();
}
if (this.bubble.current) {
this.bubble.current.hide();
}
}
render() {
var _chayns$env$isIOS, _chayns$env2;
const {
children,
parent,
childrenStyle,
preventTriggerStyle,
childrenClassNames,
removeIcon,
bindListeners,
minWidth,
maxWidth,
hideOnChildrenLeave
} = this.props;
const {
position,
x,
y
} = this.state;
const isIOS = typeof chayns !== 'undefined' ? (_chayns$env$isIOS = (_chayns$env2 = chayns.env) === null || _chayns$env2 === void 0 ? void 0 : _chayns$env2.isIOS) !== null && _chayns$env$isIOS !== void 0 ? _chayns$env$isIOS : false : false;
const showRemoveIcon = removeIcon !== null && removeIcon !== void 0 ? removeIcon : isIOS;
return [position !== null ? /*#__PURE__*/_react.default.createElement(_Bubble.default, {
coordinates: {
x,
y
},
parent: parent,
position: position,
onMouseEnter: bindListeners ? this.show : null,
onMouseLeave: bindListeners ? this.hide : null,
style: {
minWidth,
maxWidth,
padding: '12px'
},
topDivStyle: {
...(!hideOnChildrenLeave || {
userSelect: 'none',
pointerEvents: 'none'
})
},
key: "bubble",
ref: this.bubble
}, showRemoveIcon ? /*#__PURE__*/_react.default.createElement("div", {
className: "cc__tooltip__icon",
onClick: this.hide
}, /*#__PURE__*/_react.default.createElement(_Icon.default, {
icon: "fa fa-times"
})) : null, this.getContent()) : null, /*#__PURE__*/_react.default.createElement("div", {
className: (0, _clsx.default)('cc__tooltip__children', childrenClassNames, !preventTriggerStyle && 'cc__tooltip__children--trigger'),
ref: this.childrenWrapper,
key: `cc__tooltip__children${this.tooltipKey}`,
style: childrenStyle,
onMouseEnter: !isIOS && bindListeners ? this.show : null,
onMouseLeave: bindListeners ? this.hide : null,
onClick: isIOS && bindListeners ? this.show : null
}, children)];
}
}
exports.default = Tooltip;
Tooltip.position = _Bubble.default.position;
Tooltip.propTypes = {
/**
* The content of the tooltip. Either specify an object with the accepted
* properties or render custom elements by passing an object like so:
* `{ html: <div /> }`.
*/
content: _propTypes.default.oneOfType([_propTypes.default.shape({
text: _propTypes.default.string.isRequired,
headline: _propTypes.default.string,
imageUrl: _propTypes.default.string,
buttonText: _propTypes.default.string,
buttonOnClick: _propTypes.default.func
}), _propTypes.default.shape({
html: _propTypes.default.node.isRequired
})]).isRequired,
/**
* The `ReactNode` the tooltip should refer to. If the `children` node is a
* `<span>` or `<p>` element, it will be decorated with a dotted underline.
*/
children: _propTypes.default.node,
/**
* Wether `mouseover` and `mouseleave` listeners should be added to the
* children elements, which makes the tooltip automatically appear on hover.
*/
bindListeners: _propTypes.default.bool,
/**
* The position of the tooltip. `0` is top left, `1` is bottom left, `2` is
* bottom right and `3` is top right.
*/
position: _propTypes.default.number,
/**
* The minimum width of the tooltip.
*/
minWidth: _propTypes.default.number,
/**
* The maximum width of the tooltip.
*/
maxWidth: _propTypes.default.number,
/**
* Wether the close icon in the top right corner of the tooltip should be
* shown.
*/
removeIcon: _propTypes.default.bool,
/**
* A DOM node the tooltip should be rendered into.
*/
parent: typeof Element !== 'undefined' ? _propTypes.default.instanceOf(Element) : () => {},
/**
* An object with coordinates at which the tooltip should point.
*/
coordinates: _propTypes.default.shape({
x: _propTypes.default.number.isRequired,
y: _propTypes.default.number.isRequired
}),
/**
* A React style object that is applied to the children.
*/
childrenStyle: _propTypes.default.objectOf(_propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number])),
/**
* A classname string that should be applied to the children.
*/
childrenClassNames: _propTypes.default.string,
/**
* Prevent adding an underline to the children.
*/
preventTriggerStyle: _propTypes.default.bool,
/**
* Hide the tooltip when the cursor leaves the children, even if the cursor
* is over the bubble.
*/
hideOnChildrenLeave: _propTypes.default.bool,
/**
* Removes any padding of the page from the tooltip position. This is only
* needed when the parent is padded to the page and is relatively
* positioned.
*/
removeParentSpace: _propTypes.default.bool,
/**
* Whether to stop propagation for click on close icon
*/
stopPropagation: _propTypes.default.bool
};
Tooltip.defaultProps = {
children: null,
bindListeners: false,
position: null,
minWidth: 100,
maxWidth: 250,
removeIcon: null,
parent: null,
coordinates: null,
childrenStyle: null,
childrenClassNames: null,
preventTriggerStyle: false,
hideOnChildrenLeave: false,
removeParentSpace: false,
stopPropagation: false
};
Tooltip.displayName = 'Tooltip';
//# sourceMappingURL=Tooltip.js.map