<commit_before>import * as React from 'react';
import * as classNames from 'classnames';
import * as d3 from 'd3';
import { ITooltipProps } from './Tooltip.props';
import './Tooltip.scss';

const padding = { top: 5, right: 5, bottom: 5, left: 5 };
const TEXT_Y_TRANSLATE = 3.3;    // constant that best approximates text position inside rectangle
const TIP_ARROW_HEIGHT = 8;

const pathLine = d3.line().x((d: any) => d.x).y((d: any) => d.y);

export class Tooltip extends React.PureComponent<ITooltipProps, any> {
    public static defaultProps = {
        tipBorderColor: '#05486C'
    };

    constructor(props: ITooltipProps) {
        super(props);

        this.state = {
            arrowPoints: '0,0 0,0 0,0',
            width: 0,
            height: 0,
            textYPosition: 0,
            translateX: 0,
            translateY: 0,
            pathPoints: []
        };
    }

    public componentWillReceiveProps(nextProps: ITooltipProps, nextState: any) {
        const x = nextProps.x - this.state.width / 2;
        const y = nextProps.y - this.state.height - TIP_ARROW_HEIGHT;
        this.setState({ translateX: x, translateY: y });
    }

    public render() {
        const tipClass = classNames('tip', this.props.id);
        const translate = 'translate(' + this.state.translateX + ',' + this.state.translateY + ')';
        const visibility = this.props.visible ? 'block' : 'none';
        
        return (
            <g className={classNames(tipClass, 'tip-container')} style={{ display: visibility}} transform={translate}>
                <polygon className={classNames(tipClass, 'tip-pol')} 
                    points={this.state.arrowPoints}/>
                <rect className={classNames(tipClass, 'tip-rect')} 
                    height={this.state.height} 
                    width={this.state.width}/>
                <path d={pathLine(this.state.pathPoints)} style={{ fill: 'none', stroke: this.props.tipBorderColor, strokeWidth: 1 }} />
                <text className={classNames(tipClass, 'tip-text')} 
                        dx={padding.right} 
                        dy={this.state.textYPosition} 
                        ref={(element: SVGTextElement) => this.init(element)}
                >{this.props.text}</text>
            </g>
        );
    }

    private init(element: SVGTextElement) {
        if (element === null) { return; }

        const dimensions = element.getBBox();
        const width = dimensions.width + padding.left + padding.right;
        const height = dimensions.height + padding.top + padding.bottom;
        const yPosition = height - TEXT_Y_TRANSLATE - padding.bottom;

        const center = width / 2;
        const xLeft = center - 6.5;
        const xRight = center + 6.5;
        const arrowHeight = height + TIP_ARROW_HEIGHT;

        const points = xLeft + ',' + (height) + ' ' + center + ',' + arrowHeight + ' ' + xRight + ',' + (height);

        const x = this.props.x - width / 2;<commit_msg>Added constant<commit_after>import * as React from 'react';
import * as classNames from 'classnames';
import * as d3 from 'd3';
import { ITooltipProps } from './Tooltip.props';
import './Tooltip.scss';

const padding = { top: 5, right: 5, bottom: 5, left: 5 };
const TEXT_Y_TRANSLATE = 3.3;    // constant that best approximates text position inside rectangle
const TIP_ARROW_HEIGHT = 8;
const ARROW_WIDTH_FROM_CENTER = 6.5;

const pathLine = d3.line().x((d: any) => d.x).y((d: any) => d.y);

export class Tooltip extends React.PureComponent<ITooltipProps, any> {
    public static defaultProps = {
        tipBorderColor: '#05486C'
    };

    constructor(props: ITooltipProps) {
        super(props);

        this.state = {
            arrowPoints: '0,0 0,0 0,0',
            width: 0,
            height: 0,
            textYPosition: 0,
            translateX: 0,
            translateY: 0,
            pathPoints: []
        };
    }

    public componentWillReceiveProps(nextProps: ITooltipProps, nextState: any) {
        const x = nextProps.x - this.state.width / 2;
        const y = nextProps.y - this.state.height - TIP_ARROW_HEIGHT;
        this.setState({ translateX: x, translateY: y });
    }

    public render() {
        const tipClass = classNames('tip', this.props.id);
        const translate = 'translate(' + this.state.translateX + ',' + this.state.translateY + ')';
        const visibility = this.props.visible ? 'block' : 'none';
        
        return (
            <g className={classNames(tipClass, 'tip-container')} style={{ display: visibility}} transform={translate}>
                <polygon className={classNames(tipClass, 'tip-pol')} 
                    points={this.state.arrowPoints}/>
                <rect className={classNames(tipClass, 'tip-rect')} 
                    height={this.state.height} 
                    width={this.state.width}/>
                <path d={pathLine(this.state.pathPoints)} style={{ fill: 'none', stroke: this.props.tipBorderColor, strokeWidth: 1 }} />
                <text className={classNames(tipClass, 'tip-text')} 
                        dx={padding.right} 
                        dy={this.state.textYPosition} 
                        ref={(element: SVGTextElement) => this.init(element)}
                >{this.props.text}</text>
            </g>
        );
    }

    private init(element: SVGTextElement) {
        if (element === null) { return; }

        const dimensions = element.getBBox();
        const width = dimensions.width + padding.left + padding.right;
        const height = dimensions.height + padding.top + padding.bottom;
        const yPosition = height - TEXT_Y_TRANSLATE - padding.bottom;

        const center = width / 2;
        const xLeft = center - ARROW_WIDTH_FROM_CENTER;
        const xRight = center + ARROW_WIDTH_FROM_CENTER;
        const arrowHeight = height + TIP_ARROW_HEIGHT;

        const points = xLeft + ',' + (height) + ' ' + center + ',' + arrowHeight + ' ' + xRight + ',' + (height);

        const x = this.props.x - width / 2;
{'fraction_non_alphanumeric': 0.1327037773359841, 'fraction_numerical': 0.010934393638170975, 'mean_word_length': 2.1723594324750395, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7538518', 'n_tokens_mistral': 1825, 'n_tokens_neox': 1740, 'n_words': 419}