mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-08 22:33:24 +00:00
132 lines
3.4 KiB
JavaScript
132 lines
3.4 KiB
JavaScript
import React from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import TranslatedComponent from './TranslatedComponent';
|
|
|
|
/**
|
|
* Document Root Tooltip
|
|
*/
|
|
export default class Tooltip extends TranslatedComponent {
|
|
|
|
static propTypes = {
|
|
rect: PropTypes.object.isRequired,
|
|
options: PropTypes.object
|
|
};
|
|
|
|
static defaultProps = {
|
|
options: {}
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param {Object} props React Component properties
|
|
*/
|
|
constructor(props) {
|
|
super(props);
|
|
this._adjustDimensions = this._adjustDimensions.bind(this);
|
|
this.state = this._initialDimensions(props);
|
|
}
|
|
|
|
/**
|
|
* Get position and reset width/height
|
|
* @param {Object} props React Component properties
|
|
* @return {Object} Dimenions / state
|
|
*/
|
|
_initialDimensions(props) {
|
|
let { options, rect } = props;
|
|
let orientation = options.orientation || 'n';
|
|
let top, left;
|
|
|
|
switch (orientation) {
|
|
case 's':
|
|
top = Math.round(rect.top + rect.height);
|
|
left = Math.round(rect.left + (rect.width / 2));
|
|
break;
|
|
case 'n':
|
|
top = Math.round(rect.top);
|
|
left = Math.round(rect.left + (rect.width / 2));
|
|
break;
|
|
case 'e':
|
|
top = Math.round(rect.top + (rect.height / 2));
|
|
left = Math.round(rect.left + rect.width);
|
|
break;
|
|
case 'w':
|
|
top = Math.round(rect.top + (rect.height / 2));
|
|
left = Math.round(rect.left);
|
|
}
|
|
|
|
return { top, left, arrLeft: left, width: null, height: null, orientation };
|
|
}
|
|
|
|
/**
|
|
* Adjusts the position and size of the tooltip if its content
|
|
* appear outside of the windows left or right border
|
|
* @param {DomElement} elem Tooltip contents container
|
|
*/
|
|
_adjustDimensions() {
|
|
if (this.elem) {
|
|
let o = this.state.orientation;
|
|
let rect = this.elem.getBoundingClientRect();
|
|
|
|
// Round widthand height to nearest even number to avoid translate3d text blur
|
|
// caused by fractional pixels
|
|
let width = Math.ceil(rect.width / 2) * 2;
|
|
|
|
this.setState({
|
|
width,
|
|
height: Math.round(rect.height / 2) * 2
|
|
});
|
|
|
|
if (o == 'n' || o == 's') {
|
|
let docWidth = document.documentElement.clientWidth;
|
|
|
|
if (rect.left < 0) {
|
|
this.setState({ left: Math.round(width / 4) * 2 });
|
|
} else if ((rect.left + width) > docWidth) {
|
|
this.setState({ left: docWidth - Math.round(width / 4) * 2 });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*Potentially adjust component dimensions after mount
|
|
*/
|
|
componentDidMount() {
|
|
this._adjustDimensions();
|
|
}
|
|
|
|
/**
|
|
* Reset width and height on propChange
|
|
* @param {Object} nextProps Incoming/Next properties
|
|
*/
|
|
componentWillReceiveProps(nextProps) {
|
|
this.setState(this._initialDimensions(nextProps));
|
|
}
|
|
|
|
/**
|
|
* Potentially adjust component dimensions on re-render
|
|
*/
|
|
componentDidUpdate() {
|
|
this._adjustDimensions();
|
|
}
|
|
|
|
/**
|
|
* Renders the component
|
|
* @return {React.Component} Tooltip
|
|
*/
|
|
render() {
|
|
if (!this.props.children) { // If no content is provided
|
|
return null;
|
|
}
|
|
let { top, left, arrLeft, width, height, orientation } = this.state;
|
|
|
|
return <div style={{ fontSize: this.context.sizeRatio + 'em' }}>
|
|
<div className={ 'arr ' + orientation} style={{ top, left: arrLeft }} />
|
|
<div className={ 'tip ' + orientation} style={{ top, left, width, height }} ref={(elem) => this.elem = elem}>
|
|
{this.props.children}
|
|
</div>
|
|
</div>;
|
|
}
|
|
|
|
}
|