import * as i0 from '@angular/core';
import { Component, input, Directive, Input, HostListener, NgModule } from '@angular/core';
import { getElementPositionInfo, getElementLeftoverContentAvailable, isNullOrUndefined } from '@seniorsistemas/angular-components/utils';
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i1$1 from '@seniorsistemas/angular-components/common';

class TooltipComponent {
    tooltip = '';
    position = 'top';
    left = 0;
    top = 0;
    visible = false;
    escape = false;
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: TooltipComponent, selector: "ng-component", ngImport: i0, template: "<div\n    id=\"tooltip\"\n    class=\"tooltip\"\n    [ngClass]=\"['tooltip--' + position]\"\n    [class.tooltip--visible]=\"visible\"\n    [ngStyle]=\"{\n        left: left + 'px',\n        top: top + 'px',\n    }\"\n>\n    @if (escape) {\n        <span class=\"tooltip__content\">\n            {{ tooltip }}\n        </span>\n    } @else {\n        <span\n            class=\"tooltip__content\"\n            [innerHTML]=\"tooltip\"\n        >\n        </span>\n    }\n</div>\n", styles: [".tooltip{background-color:#000;border-radius:2px;color:#fff;font-family:Open Sans,sans-serif;font-size:14px;font-weight:400;line-height:21px;opacity:0;padding:8px;position:fixed;transform:translate(-50%);text-align:center;max-width:220px;word-wrap:break-word;z-index:99999;position:absolute}.tooltip--visible{opacity:1;transition:opacity .3s}.tooltip:before{content:\"\";height:0;position:absolute;width:0}.tooltip--bottom{margin-top:5px;transform:translate(-50%)}.tooltip--bottom:before{border:5px solid transparent;border-bottom:5px solid black;left:calc(50% - 5px);top:-10px}.tooltip--top{margin-bottom:5px;transform:translate(-50%,-100%)}.tooltip--top:before{border:5px solid transparent;border-top:5px solid black;left:calc(50% - 5px);bottom:-10px}.tooltip--left{margin-right:28px;transform:translate(calc(-100% - 7px),-50%)}.tooltip--left:before{border:5px solid transparent;border-left:5px solid black;right:-10px;bottom:calc(50% - 5px)}.tooltip--right{margin-left:7px;transform:translateY(-50%)}.tooltip--right:before{border:5px solid transparent;border-right:5px solid black;left:-10px;bottom:calc(50% - 5px)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipComponent, decorators: [{
            type: Component,
            args: [{ template: "<div\n    id=\"tooltip\"\n    class=\"tooltip\"\n    [ngClass]=\"['tooltip--' + position]\"\n    [class.tooltip--visible]=\"visible\"\n    [ngStyle]=\"{\n        left: left + 'px',\n        top: top + 'px',\n    }\"\n>\n    @if (escape) {\n        <span class=\"tooltip__content\">\n            {{ tooltip }}\n        </span>\n    } @else {\n        <span\n            class=\"tooltip__content\"\n            [innerHTML]=\"tooltip\"\n        >\n        </span>\n    }\n</div>\n", styles: [".tooltip{background-color:#000;border-radius:2px;color:#fff;font-family:Open Sans,sans-serif;font-size:14px;font-weight:400;line-height:21px;opacity:0;padding:8px;position:fixed;transform:translate(-50%);text-align:center;max-width:220px;word-wrap:break-word;z-index:99999;position:absolute}.tooltip--visible{opacity:1;transition:opacity .3s}.tooltip:before{content:\"\";height:0;position:absolute;width:0}.tooltip--bottom{margin-top:5px;transform:translate(-50%)}.tooltip--bottom:before{border:5px solid transparent;border-bottom:5px solid black;left:calc(50% - 5px);top:-10px}.tooltip--top{margin-bottom:5px;transform:translate(-50%,-100%)}.tooltip--top:before{border:5px solid transparent;border-top:5px solid black;left:calc(50% - 5px);bottom:-10px}.tooltip--left{margin-right:28px;transform:translate(calc(-100% - 7px),-50%)}.tooltip--left:before{border:5px solid transparent;border-left:5px solid black;right:-10px;bottom:calc(50% - 5px)}.tooltip--right{margin-left:7px;transform:translateY(-50%)}.tooltip--right:before{border:5px solid transparent;border-right:5px solid black;left:-10px;bottom:calc(50% - 5px)}\n"] }]
        }] });

class TooltipDirective {
    elementRef;
    appRef;
    debounceUtils;
    renderer;
    viewContainerRef;
    tooltip;
    tooltipPosition = 'top';
    showDelay = 500;
    displayTime;
    tooltipEvent = 'hover';
    escape = false;
    visible = true;
    mobileBehavior = 'pressing';
    focusedInputRef = null;
    checkTruncatedText = input(false);
    componentRef = null;
    showTimeout;
    touchTimeout;
    tooltipDivElement = null;
    debounceCreateTooltipFunction;
    tooltipCreatedByFocus = false;
    constructor(elementRef, appRef, debounceUtils, renderer, viewContainerRef) {
        this.elementRef = elementRef;
        this.appRef = appRef;
        this.debounceUtils = debounceUtils;
        this.renderer = renderer;
        this.viewContainerRef = viewContainerRef;
        this.debounceCreateTooltipFunction = this.debounceUtils.debounceLeading(() => this._createTooltip(true, true));
    }
    ngOnInit() {
        this.validatePosition();
        this.updateTooltipVisibilityWhenFocusOnInput();
    }
    ngOnDestroy() {
        this.destroy();
    }
    /**
     * Manipula a visibilidade do tooltip quando houver uma referência de input.
     */
    updateTooltipVisibilityWhenFocusOnInput() {
        if (this.focusedInputRef) {
            const inputFocus = this.focusedInputRef;
            const icon = this.getIconFromFocusedInput();
            this.renderer.listen(inputFocus, 'focus', () => {
                if (icon) {
                    this._createTooltip(false, false);
                    this.tooltipCreatedByFocus = true;
                }
            });
            this.renderer.listen(inputFocus, 'blur', () => {
                if (icon) {
                    this.removeTooltip(icon);
                    this.destroy();
                    this.tooltipCreatedByFocus = false;
                }
            });
        }
    }
    /**
     * Obtém o elemento do ícone associado ao label do input em focus.
     * @returns O ícone do input em focus.
     */
    getIconFromFocusedInput() {
        return this.elementRef.nativeElement;
    }
    /**
     * Remove o tooltip associado ao ícone do input em focus.
     * @param icon O ícone do input em focus.
     */
    removeTooltip(icon) {
        const tooltip = icon.querySelector('.tooltip');
        if (tooltip) {
            tooltip.remove();
        }
    }
    // whenever the component with the tooltip is clicked I destroy the tooltip.
    // whenever a key is pressed on the component with the tooltip I destroy the tooltip.
    onClick() {
        if (this.tooltipEvent === 'hover' &&
            !navigator.userAgent.match(/Android/i) &&
            !navigator.userAgent.match(/iPhone/i)) {
            this.destroy();
        }
    }
    onFocus() {
        if (this.tooltipEvent === 'focus') {
            this._createTooltip(true, true);
        }
    }
    onBlur() {
        if (this.tooltipEvent === 'focus') {
            this.destroy();
        }
    }
    onMouseEnter() {
        if (this.tooltipEvent === 'hover' || this.focusedInputRef) {
            this.debounceCreateTooltipFunction();
        }
    }
    onMouseLeave() {
        if ((this.tooltipEvent === 'hover' || this.focusedInputRef) && !this.tooltipCreatedByFocus) {
            this.destroy();
        }
    }
    onTouchStart() {
        if (this.tooltipEvent === 'hover') {
            window.clearTimeout(this.touchTimeout);
            const _delay = this.mobileBehavior === 'pressing' ? this.showDelay : 0;
            this.touchTimeout = window.setTimeout(() => {
                this._createTooltip(true, true);
            }, _delay);
        }
    }
    onTouchEnd() {
        if (this.tooltipEvent === 'hover') {
            if (this.mobileBehavior === 'pressing') {
                window.clearTimeout(this.touchTimeout);
                this.destroy();
            }
        }
    }
    validatePosition() {
        const containsPosition = ['top', 'right', 'bottom', 'left'].includes(this.tooltipPosition);
        if (!containsPosition) {
            this.tooltipPosition = 'top';
            throw new Error(`Tooltip ${this.tooltipPosition} position is unexpected`);
        }
    }
    getDomElement() {
        this.componentRef = this.viewContainerRef.createComponent(TooltipComponent);
        return this.componentRef.location.nativeElement;
    }
    _createTooltip(useShowDelay = false, autoDestroy = true) {
        const hasText = (this.tooltip || '').length > 0;
        const hasComponentRef = this.componentRef !== null;
        if (!hasText || hasComponentRef) {
            return;
        }
        const blockIfIsNotTruncatedContent = this.checkTruncatedText() ? !this.contentIsTruncated : false;
        if (blockIfIsNotTruncatedContent) {
            return;
        }
        const domElement = this.getDomElement();
        document.body.appendChild(domElement);
        this.tooltipDivElement = domElement.querySelector('.tooltip');
        this.setTooltipComponentProperties();
        const _showDelay = useShowDelay ? this.showDelay : 0;
        setTimeout(() => {
            this.showTooltip();
        }, _showDelay);
        this.renderer.listen(window, 'scroll', () => {
            this.setTooltipPositionProperty();
        });
        if (autoDestroy && this.displayTime) {
            setTimeout(() => {
                this.destroy();
            }, this.displayTime);
        }
    }
    showTooltip() {
        if (this.componentRef) {
            this.componentRef.instance.visible = this.visible;
            this.setTooltipPositionProperty();
        }
    }
    setTooltipPositionProperty() {
        if (!this.componentRef) {
            return;
        }
        const anchorSize = 5;
        const { left, right } = this.elementRef.nativeElement.getBoundingClientRect();
        const tooltipElementPosition = getElementPositionInfo(this.tooltipDivElement);
        const elementLeftover = getElementLeftoverContentAvailable(this.elementRef.nativeElement);
        const elementTriggerPosition = getElementPositionInfo(this.elementRef.nativeElement);
        const horizontalPositions = ['left', 'right'];
        const isPositionHorizontal = horizontalPositions.includes(this.tooltipPosition);
        const distanceToBorders = isPositionHorizontal
            ? tooltipElementPosition.elementWidth
            : tooltipElementPosition.elementHorizontalCenter;
        const canSetAtTop = elementLeftover.freeDistanceToTop > tooltipElementPosition.elementHeight;
        const canSetAtLeft = elementLeftover.freeDistanceToLeft > distanceToBorders;
        const canSetAtRight = elementLeftover.freeDistanceToRight > distanceToBorders;
        const canSetAtBottom = elementLeftover.freeDistanceToBottom > tooltipElementPosition.elementHeight;
        const topVertical = elementTriggerPosition.top + elementTriggerPosition.elementVerticalCenter;
        const checkTopPosition = () => {
            return canSetAtTop && canSetAtLeft && canSetAtRight;
        };
        const checkBottomPosition = () => {
            return canSetAtBottom && canSetAtLeft && canSetAtRight;
        };
        const checkLeftPosition = () => {
            return canSetAtLeft && canSetAtTop && canSetAtBottom;
        };
        const checkRightPosition = () => {
            return canSetAtRight && canSetAtTop && canSetAtBottom;
        };
        const setTopPosition = () => {
            return {
                left: left + (right - left) / 2,
                top: elementTriggerPosition.top - anchorSize,
            };
        };
        const setBottomPosition = () => {
            return {
                left: left + (right - left) / 2,
                top: elementTriggerPosition.top + elementTriggerPosition.elementHeight,
            };
        };
        const setLeftPosition = () => {
            return {
                left: left,
                top: topVertical,
            };
        };
        const setRightPosition = () => {
            return {
                left: right,
                top: topVertical,
            };
        };
        const positions = [
            {
                pos: 'top',
                check: checkTopPosition,
                set: setTopPosition,
            },
            {
                pos: 'bottom',
                check: checkBottomPosition,
                set: setBottomPosition,
            },
            {
                pos: 'left',
                check: checkLeftPosition,
                set: setLeftPosition,
            },
            {
                pos: 'right',
                check: checkRightPosition,
                set: setRightPosition,
            },
        ];
        const positionDefined = positions.find((position) => position.pos === this.tooltipPosition);
        let validPosition = positionDefined;
        const canUseDefinedPosition = positionDefined?.check();
        if (canUseDefinedPosition) {
            validPosition = positionDefined;
        }
        else if (!canUseDefinedPosition) {
            const validAlternativePosition = positions.find((position) => position.check());
            if (validAlternativePosition) {
                validPosition = validAlternativePosition;
            }
        }
        const _position = validPosition.set();
        const positionLeft = _position.left;
        const positionTop = _position.top;
        this.componentRef.instance.left = Math.round(positionLeft);
        this.componentRef.instance.top = Math.round(positionTop);
        this.componentRef.instance.position = validPosition.pos;
    }
    setTooltipComponentProperties() {
        if (!this.componentRef)
            return;
        this.componentRef.instance.tooltip = this.tooltip;
        this.componentRef.instance.escape = this.escape;
    }
    destroy() {
        if (!isNullOrUndefined(this.componentRef)) {
            window.clearTimeout(this.showTimeout);
            this.appRef.detachView(this.componentRef.hostView);
            this.componentRef.destroy();
            this.componentRef = null;
            this.tooltipDivElement = null;
        }
    }
    get contentIsTruncated() {
        const element = this.elementRef.nativeElement;
        const truncatedByVertical = element.scrollHeight > element.clientHeight;
        const truncatedByHorizontal = element.scrollWidth > element.clientWidth;
        return truncatedByHorizontal || truncatedByVertical;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipDirective, deps: [{ token: i0.ElementRef }, { token: i0.ApplicationRef }, { token: i1$1.DebounceUtils }, { token: i0.Renderer2 }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.14", type: TooltipDirective, isStandalone: true, selector: "[sTooltip]", inputs: { tooltip: { classPropertyName: "tooltip", publicName: "sTooltip", isSignal: false, isRequired: false, transformFunction: null }, tooltipPosition: { classPropertyName: "tooltipPosition", publicName: "tooltipPosition", isSignal: false, isRequired: false, transformFunction: null }, showDelay: { classPropertyName: "showDelay", publicName: "showDelay", isSignal: false, isRequired: false, transformFunction: null }, displayTime: { classPropertyName: "displayTime", publicName: "displayTime", isSignal: false, isRequired: false, transformFunction: null }, tooltipEvent: { classPropertyName: "tooltipEvent", publicName: "tooltipEvent", isSignal: false, isRequired: false, transformFunction: null }, escape: { classPropertyName: "escape", publicName: "escape", isSignal: false, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: false, isRequired: false, transformFunction: null }, mobileBehavior: { classPropertyName: "mobileBehavior", publicName: "mobileBehavior", isSignal: false, isRequired: false, transformFunction: null }, focusedInputRef: { classPropertyName: "focusedInputRef", publicName: "focusedInputRef", isSignal: false, isRequired: false, transformFunction: null }, checkTruncatedText: { classPropertyName: "checkTruncatedText", publicName: "checkTruncatedText", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick()", "keydown": "onClick()", "focus": "onFocus()", "blur": "onBlur()", "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "wheel": "onMouseLeave()", "touchstart": "onTouchStart()", "touchend": "onTouchEnd()" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[sTooltip]',
                    standalone: true,
                }]
        }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ApplicationRef }, { type: i1$1.DebounceUtils }, { type: i0.Renderer2 }, { type: i0.ViewContainerRef }], propDecorators: { tooltip: [{
                type: Input,
                args: ['sTooltip']
            }], tooltipPosition: [{
                type: Input
            }], showDelay: [{
                type: Input
            }], displayTime: [{
                type: Input
            }], tooltipEvent: [{
                type: Input
            }], escape: [{
                type: Input
            }], visible: [{
                type: Input
            }], mobileBehavior: [{
                type: Input
            }], focusedInputRef: [{
                type: Input
            }], onClick: [{
                type: HostListener,
                args: ['click']
            }, {
                type: HostListener,
                args: ['keydown']
            }], onFocus: [{
                type: HostListener,
                args: ['focus']
            }], onBlur: [{
                type: HostListener,
                args: ['blur']
            }], onMouseEnter: [{
                type: HostListener,
                args: ['mouseenter']
            }], onMouseLeave: [{
                type: HostListener,
                args: ['mouseleave']
            }, {
                type: HostListener,
                args: ['wheel']
            }], onTouchStart: [{
                type: HostListener,
                args: ['touchstart']
            }], onTouchEnd: [{
                type: HostListener,
                args: ['touchend']
            }] } });

class TooltipModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: TooltipModule, declarations: [TooltipComponent], imports: [CommonModule, TooltipDirective], exports: [TooltipDirective] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipModule, imports: [CommonModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [CommonModule, TooltipDirective],
                    declarations: [TooltipComponent],
                    exports: [TooltipDirective],
                }]
        }] });

/**
 * Generated bundle index. Do not edit.
 */

export { TooltipDirective, TooltipModule };
//# sourceMappingURL=seniorsistemas-angular-components-tooltip.mjs.map
