UNPKG

@controllable-ui/ngx-tooltip

Version:

> ✨ Check out the demo [here](https://ciprian-anin.github.io/controllable-ui-angular/).

806 lines 64.5 kB
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { input, ViewEncapsulation, ChangeDetectionStrategy, Component, computed, output, viewChild, signal, effect } from '@angular/core';

class NgxTooltipArrowComponent {
    arrowSize = input();
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: NgxTooltipArrowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.0.4", type: NgxTooltipArrowComponent, isStandalone: true, selector: "ngx-tooltip-arrow", inputs: { arrowSize: { classPropertyName: "arrowSize", publicName: "arrowSize", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n  class=\"ngxTooltip-arrow\"\n  [ngStyle]=\"{ 'width.px': arrowSize(), 'height.px': arrowSize() }\"\n>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -16 32 32\">\n    <path d=\"M16 0l16 16H0z\"></path>\n  </svg>\n</div>\n", styles: [".ngxTooltip-dialog-with-bridge{--arrow-offset: 16px}.ngxTooltip-placement-top-start .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) - var(--dialog-x) + var(--arrow-offset) / 2,var(--arrow-offset)),var(--dialog-width) - var(--arrow-offset));transform:rotate(-180deg)}.ngxTooltip-placement-top .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) + var(--relative-width) / 2 - (var(--dialog-x) + var(--dialog-width) / 2) + var(--dialog-width) / 2,var(--arrow-offset)),var(--dialog-width) - var(--arrow-offset));transform:rotate(-180deg) translate(50%)}.ngxTooltip-placement-top-end .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) + var(--relative-width) - var(--dialog-x) - var(--arrow-offset) / 2,var(--arrow-offset)),var(--dialog-width) - var(--arrow-offset));transform:rotate(-180deg) translate(100%)}.ngxTooltip-placement-top-start .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-top .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-top-end .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow{bottom:0;margin-bottom:var(--dialog-offset)}.ngxTooltip-placement-bottom-start .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) - var(--dialog-x) + var(--arrow-offset) / 2,var(--arrow-offset) / 2),var(--dialog-width) - var(--arrow-offset) / 2)}.ngxTooltip-placement-bottom .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) + var(--relative-width) / 2 - (var(--dialog-x) + var(--dialog-width) / 2) + var(--dialog-width) / 2,var(--arrow-offset)),var(--dialog-width) - var(--arrow-offset));transform:translate(-50%)}.ngxTooltip-placement-bottom-end .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) + var(--relative-width) - (var(--dialog-x)) - var(--arrow-offset) / 2,var(--arrow-offset) / 2),var(--dialog-width) - var(--arrow-offset) / 2);transform:translate(-100%)}.ngxTooltip-placement-bottom-start .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-bottom .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-bottom-end .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow{top:0;margin-top:var(--dialog-offset)}.ngxTooltip-placement-left-start .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-height) - (var(--relative-y) - var(--dialog-y)),var(--arrow-size) + 3px),var(--dialog-height) - 3px);transform:rotate(90deg) translate(100%)}.ngxTooltip-placement-left .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-height) - (var(--relative-y) + var(--relative-height) / 2 - (var(--dialog-y) + var(--dialog-height) / 2) + var(--dialog-height) / 2),var(--arrow-size) - 3px),var(--dialog-height) - var(--arrow-size) + 3px);transform:rotate(90deg) translate(50%)}.ngxTooltip-placement-left-end .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-y) + var(--dialog-height) - (var(--relative-y) + var(--relative-height)) + 3px,3px),var(--dialog-height) - var(--arrow-size) - 3px);transform:rotate(90deg);transform-origin:center}.ngxTooltip-placement-left-start .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-left .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-left-end .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow{right:0;margin-right:var(--dialog-offset)}.ngxTooltip-placement-right-start .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-height) - (var(--relative-y) - var(--dialog-y)),var(--arrow-size) + 3px),var(--dialog-height) - 3px);transform:rotate(-90deg) translate(-100%)}.ngxTooltip-placement-right .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-height) - (var(--relative-y) + var(--relative-height) / 2 - (var(--dialog-y) + var(--dialog-height) / 2) + var(--dialog-height) / 2),var(--arrow-size) - 3px),var(--dialog-height) - var(--arrow-size) + 3px);transform:rotate(-90deg) translate(-50%)}.ngxTooltip-placement-right-end .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-y) + var(--dialog-height) - (var(--relative-y) + var(--relative-height)) + 3px,3px),var(--dialog-height) - var(--arrow-size) - 3px);transform:rotate(-90deg);transform-origin:center}.ngxTooltip-placement-right-start .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-right .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-right-end .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow{left:0;margin-left:var(--dialog-offset)}.ngxTooltip-arrow{padding:0;margin:0;color:#616161eb;width:var(--arrow-offset);height:var(--arrow-offset);line-height:0;position:absolute;bottom:0;transform-origin:center}.ngxTooltip-arrow svg{fill:currentColor;filter:drop-shadow(0 -3px 3px rgba(0,0,0,.16));height:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: NgxTooltipArrowComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ngx-tooltip-arrow', imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n  class=\"ngxTooltip-arrow\"\n  [ngStyle]=\"{ 'width.px': arrowSize(), 'height.px': arrowSize() }\"\n>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -16 32 32\">\n    <path d=\"M16 0l16 16H0z\"></path>\n  </svg>\n</div>\n", styles: [".ngxTooltip-dialog-with-bridge{--arrow-offset: 16px}.ngxTooltip-placement-top-start .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) - var(--dialog-x) + var(--arrow-offset) / 2,var(--arrow-offset)),var(--dialog-width) - var(--arrow-offset));transform:rotate(-180deg)}.ngxTooltip-placement-top .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) + var(--relative-width) / 2 - (var(--dialog-x) + var(--dialog-width) / 2) + var(--dialog-width) / 2,var(--arrow-offset)),var(--dialog-width) - var(--arrow-offset));transform:rotate(-180deg) translate(50%)}.ngxTooltip-placement-top-end .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) + var(--relative-width) - var(--dialog-x) - var(--arrow-offset) / 2,var(--arrow-offset)),var(--dialog-width) - var(--arrow-offset));transform:rotate(-180deg) translate(100%)}.ngxTooltip-placement-top-start .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-top .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-top-end .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow{bottom:0;margin-bottom:var(--dialog-offset)}.ngxTooltip-placement-bottom-start .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) - var(--dialog-x) + var(--arrow-offset) / 2,var(--arrow-offset) / 2),var(--dialog-width) - var(--arrow-offset) / 2)}.ngxTooltip-placement-bottom .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) + var(--relative-width) / 2 - (var(--dialog-x) + var(--dialog-width) / 2) + var(--dialog-width) / 2,var(--arrow-offset)),var(--dialog-width) - var(--arrow-offset));transform:translate(-50%)}.ngxTooltip-placement-bottom-end .ngxTooltip-arrow{margin-left:min(max(var(--relative-x) + var(--relative-width) - (var(--dialog-x)) - var(--arrow-offset) / 2,var(--arrow-offset) / 2),var(--dialog-width) - var(--arrow-offset) / 2);transform:translate(-100%)}.ngxTooltip-placement-bottom-start .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-bottom .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-bottom-end .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow{top:0;margin-top:var(--dialog-offset)}.ngxTooltip-placement-left-start .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-height) - (var(--relative-y) - var(--dialog-y)),var(--arrow-size) + 3px),var(--dialog-height) - 3px);transform:rotate(90deg) translate(100%)}.ngxTooltip-placement-left .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-height) - (var(--relative-y) + var(--relative-height) / 2 - (var(--dialog-y) + var(--dialog-height) / 2) + var(--dialog-height) / 2),var(--arrow-size) - 3px),var(--dialog-height) - var(--arrow-size) + 3px);transform:rotate(90deg) translate(50%)}.ngxTooltip-placement-left-end .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-y) + var(--dialog-height) - (var(--relative-y) + var(--relative-height)) + 3px,3px),var(--dialog-height) - var(--arrow-size) - 3px);transform:rotate(90deg);transform-origin:center}.ngxTooltip-placement-left-start .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-left .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-left-end .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow{right:0;margin-right:var(--dialog-offset)}.ngxTooltip-placement-right-start .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-height) - (var(--relative-y) - var(--dialog-y)),var(--arrow-size) + 3px),var(--dialog-height) - 3px);transform:rotate(-90deg) translate(-100%)}.ngxTooltip-placement-right .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-height) - (var(--relative-y) + var(--relative-height) / 2 - (var(--dialog-y) + var(--dialog-height) / 2) + var(--dialog-height) / 2),var(--arrow-size) - 3px),var(--dialog-height) - var(--arrow-size) + 3px);transform:rotate(-90deg) translate(-50%)}.ngxTooltip-placement-right-end .ngxTooltip-arrow{margin-bottom:min(max(var(--dialog-y) + var(--dialog-height) - (var(--relative-y) + var(--relative-height)) + 3px,3px),var(--dialog-height) - var(--arrow-size) - 3px);transform:rotate(-90deg);transform-origin:center}.ngxTooltip-placement-right-start .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-right .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow,.ngxTooltip-placement-right-end .ngxTooltip-animated-inner-dialog-with-bridge .ngxTooltip-arrow{left:0;margin-left:var(--dialog-offset)}.ngxTooltip-arrow{padding:0;margin:0;color:#616161eb;width:var(--arrow-offset);height:var(--arrow-offset);line-height:0;position:absolute;bottom:0;transform-origin:center}.ngxTooltip-arrow svg{fill:currentColor;filter:drop-shadow(0 -3px 3px rgba(0,0,0,.16));height:auto}\n"] }]
        }] });

const generateRandomNumber = () => {
    const seed = new Date().getTime(); // Get current timestamp
    const random = Math.abs(Math.sin(seed) * 1000000); // Use sine function for randomness and scale it
    return Math.floor(random); // Return a positive integer
};
const getDocumentWidth = () => document.documentElement.clientWidth;
const getDocumentHeight = () => document.documentElement.clientHeight;
const nextTickRender = () => new Promise((resolve) => setTimeout(resolve));
const delay = (milliseconds, timeoutIDSignal) => new Promise((resolve) => setTimeout(resolve, milliseconds));
function getScrollableContainer(scrollableContainer) {
    return scrollableContainer ?? document.documentElement;
}

/**
 * In order to avoid the annoying flickering from top to bottom or from left to right
 * in case one side size has mare space than other, after we already have dialog placed on a side,
 * we should try to keep dialog on current placement until min size is hit.
 *
 * When it is first opened it should be positioned were is the most space and
 * it should remain there, decreasing height as much as we can
 * (until we hit min-height / min-width) and after trying to position it
 * on opposed side if there is more space (even if it needs a small decrease of height
 * on the opposed side, than the default height)
 * * (basically trying all placements in the order defined in placementsToBeTried)
 *
 */
function getDialogAvailablePositionConsideringKeepingCurrentPlacement({ placementsToBeTried, currentPlacement, dialogElement, relativeElement, dialogMaxHeight = Infinity, dialogMinHeight = 0, dialogMaxWidth = Infinity, dialogMinWidth = 0, }) {
    switch (currentPlacement) {
        case 'top-start':
        case 'top':
        case 'top-end': {
            // decrease height to fit on top; if min-height was hit try to place again on placementsToBeTried
            const maxAvailableSpaceOnTop = getMaxAvailableSpaceOnTop(relativeElement);
            return maxAvailableSpaceOnTop < dialogMinHeight
                ? getAvailablePlacementFromTheOnesToBeTried(placementsToBeTried, dialogElement, relativeElement)
                : maxAvailableSpaceOnTop > dialogMaxHeight
                    ? {
                        type: 'full-size-available',
                        placement: currentPlacement,
                    }
                    : {
                        type: 'partial-size-available',
                        placement: currentPlacement,
                        availableSize: maxAvailableSpaceOnTop,
                    };
        }
        case 'bottom-start':
        case 'bottom':
        case 'bottom-end': {
            // decrease height to fit on bottom; if min-height was hit try to place again on placementsToBeTried
            const maxAvailableSpaceOnBottom = getMaxAvailableSpaceOnBottom(relativeElement);
            return maxAvailableSpaceOnBottom < dialogMinHeight
                ? getAvailablePlacementFromTheOnesToBeTried(placementsToBeTried, dialogElement, relativeElement)
                : maxAvailableSpaceOnBottom > dialogMaxHeight
                    ? {
                        type: 'full-size-available',
                        placement: currentPlacement,
                    }
                    : {
                        type: 'partial-size-available',
                        placement: currentPlacement,
                        availableSize: maxAvailableSpaceOnBottom,
                    };
        }
        case 'left-start':
        case 'left':
        case 'left-end': {
            // decrease height to fit on left; if min-width was hit try to place again on placementsToBeTried
            const maxAvailableSpaceOnLeft = getMaxAvailableSpaceOnLeft(relativeElement);
            return maxAvailableSpaceOnLeft < dialogMinWidth
                ? getAvailablePlacementFromTheOnesToBeTried(placementsToBeTried, dialogElement, relativeElement)
                : maxAvailableSpaceOnLeft > dialogMaxWidth
                    ? {
                        type: 'full-size-available',
                        placement: currentPlacement,
                    }
                    : {
                        type: 'partial-size-available',
                        placement: currentPlacement,
                        availableSize: maxAvailableSpaceOnLeft,
                    };
        }
        case 'right-start':
        case 'right':
        case 'right-end': {
            // decrease height to fit on right; if min-width was hit try to place again on placementsToBeTried
            const maxAvailableSpaceOnRight = getMaxAvailableSpaceOnRight(relativeElement);
            return maxAvailableSpaceOnRight < dialogMinWidth
                ? getAvailablePlacementFromTheOnesToBeTried(placementsToBeTried, dialogElement, relativeElement)
                : maxAvailableSpaceOnRight > dialogMaxWidth
                    ? {
                        type: 'full-size-available',
                        placement: currentPlacement,
                    }
                    : {
                        type: 'partial-size-available',
                        placement: currentPlacement,
                        availableSize: maxAvailableSpaceOnRight,
                    };
        }
        default: {
            return getAvailablePlacementFromTheOnesToBeTried(placementsToBeTried, dialogElement, relativeElement);
        }
    }
}
function getAvailablePlacementFromTheOnesToBeTried(placementsToBeTried, dialogElement, relativeElement) {
    const dialogElementRect = dialogElement.getBoundingClientRect();
    const relativeElementRect = relativeElement.getBoundingClientRect();
    const placementWithFullAvailableSpace = placementsToBeTried.find((placementToBeTried) => {
        switch (placementToBeTried) {
            case 'top-start':
            case 'top':
            case 'top-end': {
                return relativeElementRect.top - dialogElementRect.height >= 0;
            }
            case 'bottom-start':
            case 'bottom':
            case 'bottom-end': {
                return (relativeElementRect.bottom + dialogElementRect.height <=
                    getDocumentHeight());
            }
            case 'left-start':
            case 'left':
            case 'left-end': {
                return relativeElementRect.left - dialogElementRect.width >= 0;
            }
            case 'right-start':
            case 'right':
            case 'right-end': {
                return (relativeElementRect.right + dialogElementRect.width <=
                    getDocumentWidth());
            }
        }
    });
    if (placementWithFullAvailableSpace) {
        return {
            type: 'full-size-available',
            placement: placementWithFullAvailableSpace,
        };
    }
    else {
        return {
            type: 'partial-size-available',
            ...getMaxPartialAvailableSpace(placementsToBeTried, relativeElement),
        };
    }
}
function getMaxPartialAvailableSpace(placementsToBeTried, relativeElement) {
    const availableSizeOfPlacementsToBeTried = placementsToBeTried.map((currentPlacementToBeTried) => ({
        placement: currentPlacementToBeTried,
        availableSize: computeMaxAvailableSizeOfDialogForPlacement(currentPlacementToBeTried, relativeElement),
    }));
    const placementWithMaxAvailableSpace = availableSizeOfPlacementsToBeTried.reduce((acc, value) => {
        return acc.availableSize >= value.availableSize ? acc : value;
    }, availableSizeOfPlacementsToBeTried[0]);
    return placementWithMaxAvailableSpace;
}
function getMaxAvailableSpaceOnTop(relativeElement) {
    const relativeElementRect = relativeElement.getBoundingClientRect();
    return relativeElementRect.top;
}
function getMaxAvailableSpaceOnBottom(relativeElement) {
    const relativeElementRect = relativeElement.getBoundingClientRect();
    return getDocumentHeight() - relativeElementRect.bottom;
}
function getMaxAvailableSpaceOnLeft(relativeElement) {
    const relativeElementRect = relativeElement.getBoundingClientRect();
    return relativeElementRect.left;
}
function getMaxAvailableSpaceOnRight(relativeElement) {
    const relativeElementRect = relativeElement.getBoundingClientRect();
    return getDocumentWidth() - relativeElementRect.right;
}
function computeMaxAvailableSizeOfDialogForPlacement(placement, relativeElement) {
    switch (placement) {
        case 'top-start':
        case 'top':
        case 'top-end': {
            return getMaxAvailableSpaceOnTop(relativeElement);
        }
        case 'bottom-start':
        case 'bottom':
        case 'bottom-end': {
            return getMaxAvailableSpaceOnBottom(relativeElement);
        }
        case 'left-start':
        case 'left':
        case 'left-end': {
            return getMaxAvailableSpaceOnLeft(relativeElement);
        }
        case 'right-start':
        case 'right':
        case 'right-end': {
            return getMaxAvailableSpaceOnRight(relativeElement);
        }
    }
}

function getBottomEndPositionStyle({ relativeElement, dialogElement, scrollableContainer, }) {
    const { right, bottom } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustBottomToBeAtMostAtTheBottomEdgeOfScrollableContainer(bottom, scrollableContainer)}px`,
        left: `${ensureAdjustXToHaveWidthInsideView(right - dialogElementRect.width, dialogElementRect.width, scrollableContainer)}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function getBottomPositionStyle({ relativeElement, dialogElement, scrollableContainer, }) {
    const { x, bottom, width } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustBottomToBeAtMostAtTheBottomEdgeOfScrollableContainer(bottom, scrollableContainer)}px`,
        left: `${ensureAdjustXToHaveWidthInsideView(x + width / 2 - dialogElementRect.width / 2, dialogElementRect.width, scrollableContainer)}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function getBottomStartPositionStyle({ relativeElement, dialogElement, scrollableContainer, }) {
    const { x, bottom } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustBottomToBeAtMostAtTheBottomEdgeOfScrollableContainer(bottom, scrollableContainer)}px`,
        left: `${ensureAdjustXToHaveWidthInsideView(x, dialogElementRect.width, scrollableContainer)}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function getRightEndPositionStyle({ relativeElement, dialogElement, scrollableContainer, }) {
    const { right, bottom } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustYToHaveHeightInsideView(bottom - dialogElementRect.height, dialogElementRect.height, scrollableContainer)}px`,
        left: `${ensureAdjustRightToBeAtMostAtTheRightEdgeOfScrollableContainer(right, scrollableContainer)}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function getRightPositionStyle({ relativeElement, dialogElement, scrollableContainer, }) {
    const { right, y, height } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustYToHaveHeightInsideView(y + height / 2 - dialogElementRect.height / 2, dialogElementRect.height, scrollableContainer)}px`,
        left: `${ensureAdjustRightToBeAtMostAtTheRightEdgeOfScrollableContainer(right, scrollableContainer)}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function getRightStartPositionStyle({ relativeElement, dialogElement, scrollableContainer, }) {
    const { right, y } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustYToHaveHeightInsideView(y, dialogElementRect.height, scrollableContainer)}px`,
        left: `${ensureAdjustRightToBeAtMostAtTheRightEdgeOfScrollableContainer(right, scrollableContainer)}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function getLeftEndPositionStyle({ relativeElement, dialogElement, scrollableContainer, }) {
    const { x, bottom } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustYToHaveHeightInsideView(bottom - dialogElementRect.height, dialogElementRect.height, scrollableContainer)}px`,
        left: `${ensureAdjustXToBeAtMostAtTheLeftEdgeOfScrollableContainer(x, scrollableContainer) - dialogElementRect.width}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function getLeftPositionStyle({ relativeElement, dialogElement, scrollableContainer, }) {
    const { x, y, height } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustYToHaveHeightInsideView(y + height / 2 - dialogElementRect.height / 2, dialogElementRect.height, scrollableContainer)}px`,
        left: `${ensureAdjustXToBeAtMostAtTheLeftEdgeOfScrollableContainer(x, scrollableContainer) - dialogElementRect.width}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function getLeftStartPositionStyle({ relativeElement, dialogElement, scrollableContainer, }) {
    const { x, y } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustYToHaveHeightInsideView(y, dialogElementRect.height, scrollableContainer)}px`,
        left: `${ensureAdjustXToBeAtMostAtTheLeftEdgeOfScrollableContainer(x, scrollableContainer) - dialogElementRect.width}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function getTopEndPositionStyle({ relativeElement, dialogElement, scrollableContainer, }) {
    const { y, right } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustYToBeAtMostAtTheTopEdgeOfScrollableContainer(y, scrollableContainer) - dialogElementRect.height}px`,
        left: `${ensureAdjustXToHaveWidthInsideView(right - dialogElementRect.width, dialogElementRect.width, scrollableContainer)}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function ensureAdjustXToHaveWidthInsideView(x, dialogWidth, scrollableContainer) {
    const rightEdgeOfView = scrollableContainer
        ? Math.min(getDocumentWidth(), scrollableContainer.getBoundingClientRect().right)
        : getDocumentWidth();
    const getLeftEdgeOfView = () => scrollableContainer
        ? Math.max(0, scrollableContainer.getBoundingClientRect().left)
        : 0;
    const sizeOutsideRightSide = x + dialogWidth - rightEdgeOfView;
    const adjustedX = sizeOutsideRightSide > 0
        ? Math.max(x - sizeOutsideRightSide, 0)
        : Math.max(x, getLeftEdgeOfView());
    return Math.round(adjustedX);
}
function ensureAdjustYToBeAtMostAtTheTopEdgeOfScrollableContainer(y, scrollableContainer) {
    return scrollableContainer
        ? Math.max(y, scrollableContainer?.getBoundingClientRect().y)
        : y;
}
function ensureAdjustBottomToBeAtMostAtTheBottomEdgeOfScrollableContainer(bottom, scrollableContainer) {
    return scrollableContainer
        ? Math.min(bottom, scrollableContainer.getBoundingClientRect().bottom)
        : bottom;
}
function ensureAdjustXToBeAtMostAtTheLeftEdgeOfScrollableContainer(x, scrollableContainer) {
    return scrollableContainer
        ? Math.max(x, scrollableContainer.getBoundingClientRect().x)
        : x;
}
function ensureAdjustRightToBeAtMostAtTheRightEdgeOfScrollableContainer(right, scrollableContainer) {
    return scrollableContainer
        ? Math.min(right, scrollableContainer.getBoundingClientRect().right)
        : right;
}
function ensureAdjustYToHaveHeightInsideView(y, dialogHeight, scrollableContainer) {
    const bottomEdgeOfView = scrollableContainer
        ? Math.min(getDocumentHeight(), scrollableContainer.getBoundingClientRect().bottom)
        : getDocumentHeight();
    const getTopEdgeOfView = () => scrollableContainer
        ? Math.max(0, scrollableContainer.getBoundingClientRect().top)
        : 0;
    const sizeOutside = y + dialogHeight - bottomEdgeOfView;
    const adjustedY = sizeOutside > 0
        ? Math.max(y - sizeOutside, 0)
        : Math.max(y, getTopEdgeOfView());
    return adjustedY;
}
function getTopStartPositionStyle({ dialogElement, relativeElement, scrollableContainer, }) {
    const { x, y } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustYToBeAtMostAtTheTopEdgeOfScrollableContainer(y, scrollableContainer) - dialogElementRect.height}px`,
        left: `${ensureAdjustXToHaveWidthInsideView(x, dialogElementRect.width, scrollableContainer)}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function getTopPositionStyle({ dialogElement, relativeElement, scrollableContainer, }) {
    const { x, y, width } = relativeElement.getBoundingClientRect();
    const dialogElementRect = dialogElement.getBoundingClientRect();
    return {
        top: `${ensureAdjustYToBeAtMostAtTheTopEdgeOfScrollableContainer(y, scrollableContainer) - dialogElementRect.height}px`,
        left: `${ensureAdjustXToHaveWidthInsideView(x + width / 2 - dialogElementRect.width / 2, dialogElementRect.width, scrollableContainer)}px`,
        right: 'auto',
        bottom: 'auto',
    };
}
function getDialogPositionStyle(availablePosition, dialogElement, relativeElement, scrollableContainer) {
    switch (availablePosition.placement) {
        case 'top-start':
            return getTopStartPositionStyle({
                dialogElement,
                relativeElement,
                scrollableContainer,
            });
        case 'top':
            return getTopPositionStyle({
                dialogElement,
                relativeElement,
                scrollableContainer,
            });
        case 'top-end':
            return getTopEndPositionStyle({
                relativeElement,
                dialogElement,
                scrollableContainer,
            });
        case 'bottom-start':
            return getBottomStartPositionStyle({
                dialogElement,
                relativeElement,
                scrollableContainer,
            });
        case 'bottom':
            return getBottomPositionStyle({
                dialogElement,
                relativeElement,
                scrollableContainer,
            });
        case 'bottom-end':
            return getBottomEndPositionStyle({
                dialogElement,
                relativeElement,
                scrollableContainer,
            });
        case 'left-start':
            return getLeftStartPositionStyle({
                dialogElement,
                relativeElement,
                scrollableContainer,
            });
        case 'left':
            return getLeftPositionStyle({
                dialogElement,
                relativeElement,
                scrollableContainer,
            });
        case 'left-end':
            return getLeftEndPositionStyle({
                dialogElement,
                relativeElement,
                scrollableContainer,
            });
        case 'right-start':
            return getRightStartPositionStyle({
                dialogElement,
                relativeElement,
                scrollableContainer,
            });
        case 'right':
            return getRightPositionStyle({
                dialogElement,
                relativeElement,
                scrollableContainer,
            });
        case 'right-end':
            return getRightEndPositionStyle({
                dialogElement,
                relativeElement,
                scrollableContainer,
            });
    }
}

const defaultOrderOfPlacementsToBeTried = {
    'top-start': ['top-start', 'bottom-start', 'left', 'right'],
    top: ['top', 'bottom', 'left', 'right'],
    'top-end': ['top-end', 'bottom-end', 'left', 'right'],
    'left-start': ['left-start', 'right-start', 'top', 'bottom'],
    left: ['left', 'right', 'top', 'bottom'],
    'left-end': ['left-end', 'right-end', 'top', 'bottom'],
    'right-start': ['right-start', 'left-start', 'top', 'bottom'],
    right: ['right', 'left', 'top', 'bottom'],
    'right-end': ['right-end', 'left-end', 'top', 'bottom'],
    'bottom-start': ['bottom-start', 'top-start', 'left', 'right'],
    bottom: ['bottom', 'top', 'left', 'right'],
    'bottom-end': ['bottom-end', 'top-end', 'left', 'right'],
};
class NgxTooltipComponent {
    open = input();
    preferredPlacement = input('bottom-start');
    orderOfPlacementsToBeTried = input();
    orderOfPlacementsToBeTriedComputed = computed(() => this.orderOfPlacementsToBeTried() ||
        defaultOrderOfPlacementsToBeTried[this.preferredPlacement()]);
    enterDelay = input(100);
    leaveDelay = input(150);
    triggerActions = input(['hover', 'focus']);
    arrow = input(false);
    arrowSize = computed(() => (this.arrow() ? 12 : 0));
    dialogOffset = input(5);
    computedDialogOffset = computed(() => this.arrow()
        ? this.dialogOffset() - this.arrowSize() / 2
        : this.dialogOffset());
    bridgeSize = computed(() => this.computedDialogOffset() + this.arrowSize());
    scrollableContainer = input();
    tooltipRootClass = input();
    tooltipClass = input();
    /**
     * default - Dialog placement will be recomputed immediately after we remain
     * without necessary space for dialog on current placement.
     *
     * considerKeepingCurrentPlacement - Keep current placement of dialog as time as it remains in
     * min & max sizes boundaries.
     */
    placementStrategy = input('default');
    /**
     *
     * `dialogMinMaxSizes`:
     *   > is used when placementStrategy has value considerKeepingCurrentPlacement
     *   > In case we need to keep current position, we will use maximum & minimum sizes
     *   > of dialog to check if it fits in current placement, without going over its minimum sizes.
     *   > In case we don't have minimum size available for current placement,
     *   > than will be tried next place from `orderOfPlacementsToBeTried`.
     *      *   > Maximum size is used to make sure to not have a bigger maximum size on dialog popover.
     *   > (we make sure to override the maximum size in case the available space is smaller than the dialog size)
     */
    dialogMinMaxSizes = input();
    onOpen$ = output();
    onClose$ = output();
    tooltipId = generateRandomNumber();
    relativeElementRef = viewChild('relativeElementRef');
    dialogWithBridgeRef = viewChild('dialogWithBridgeRef');
    dialogRef = viewChild('dialogRef');
    dialogIsOpenLocalState = signal(this.open());
    dialogPositionStyle = signal({
        currentPlacement: undefined,
        value: {},
        maxHeight: '',
        maxWidth: '',
    });
    closeDialogTimeoutID = signal(undefined);
    openDialogTimeoutID = signal(undefined);
    dialogAnimationState = signal('initial');
    constructor() {
        effect((onCleanup) => {
            if (this.dialogIsOpenLocalState() &&
                this.triggerActions()?.includes('click')) {
                window.addEventListener('click', this.handleClickOutsideClose);
                onCleanup(() => {
                    window.removeEventListener('click', this.handleClickOutsideClose);
                });
            }
        });
        effect((onCleanup) => {
            if (this.dialogIsOpenLocalState()) {
                const scrollableContainer = getScrollableContainer(this.scrollableContainer()?.nativeElement);
                scrollableContainer.addEventListener('scroll', this.positionDialog);
                onCleanup(() => {
                    scrollableContainer.removeEventListener('scroll', this.positionDialog);
                });
            }
        });
    }
    positionDialog = async () => {
        if (this.dialogWithBridgeRef() &&
            this.dialogRef() &&
            this.relativeElementRef()) {
            // compute placement of dialog using the dialogRef which doesn't include bridge,
            // which is unknown before knowing the next dialog placement.
            // We use dialogOffset to properly take the bridge into account when computing the available space & placement
            const availablePosition = this.placementStrategy() === 'considerKeepingCurrentPlacement'
                ? getDialogAvailablePositionConsideringKeepingCurrentPlacement({
                    placementsToBeTried: this.orderOfPlacementsToBeTriedComputed(),
                    dialogElement: this.dialogRef().nativeElement,
                    relativeElement: this.relativeElementRef().nativeElement,
                    currentPlacement: this.dialogPositionStyle().currentPlacement,
                    ...this.dialogMinMaxSizes?.(),
                })
                : getAvailablePlacementFromTheOnesToBeTried(this.orderOfPlacementsToBeTriedComputed(), this.dialogRef().nativeElement, this.relativeElementRef().nativeElement);
            if (availablePosition.type === 'partial-size-available') {
                // in case of partial size available to be displayed,
                // apply the new height or width on element before computing
                // its position for available placement location
                // (for ex. if placement is left this will make sure to always
                // place on left center based on new dialog height obtained
                // after reducing the width of it)
                switch (availablePosition.placement) {
                    case 'top-start':
                    case 'top':
                    case 'top-end':
                    case 'bottom-start':
                    case 'bottom':
                    case 'bottom-end':
                        // Note: maxHeight will be set on .ngxTooltip-tooltip
                        this.dialogPositionStyle.set({
                            ...this.dialogPositionStyle(),
                            maxHeight: `${availablePosition.availableSize - this.bridgeSize()}px`,
                        });
                        break;
                    case 'left-start':
                    case 'left':
                    case 'left-end':
                    case 'right-start':
                    case 'right':
                    case 'right-end':
                        // Note: maxWidth will be set on .ngxTooltip-dialog-with-bridge
                        this.dialogPositionStyle.set({
                            ...this.dialogPositionStyle(),
                            maxWidth: `${availablePosition.availableSize}px`,
                        });
                        break;
                }
                await nextTickRender(); // wait for new width/height to be rendered,
                // to be able to compute properly, the position of dialog for
                // available placement location
            }
            this.dialogPositionStyle.set({
                ...this.dialogPositionStyle(),
                currentPlacement: availablePosition.placement,
            });
            await nextTickRender(); // wait for the placement class to be rendered,
            // in order to have the bridge (padding) applied
            const dialogPositionStyleProps = getDialogPositionStyle(availablePosition, this.dialogWithBridgeRef().nativeElement, // dialogWithBridgeRef have the bridge in place in this point
            // so we can properly compute the position, taking into account the bridge
            this.relativeElementRef().nativeElement, this.scrollableContainer()?.nativeElement);
            this.dialogPositionStyle.set({
                ...this.dialogPositionStyle(),
                value: {
                    ...this.dialogPositionStyle().value,
                    ...dialogPositionStyleProps,
                    '--scrollbar-height': `${window.innerHeight - document.documentElement.clientHeight}px`,
                    // visibility: "visible",
                },
            });
            await nextTickRender(); // wait for the dialog to be rendered on the computed placement
            this.dialogPositionStyle.set({
                ...this.dialogPositionStyle(),
                value: {
                    ...this.dialogPositionStyle().value,
                    ...(this.arrow()
                        ? {
                            ...(() => {
                                const { x, y, width, height, right, bottom } = this.relativeElementRef()?.nativeElement.getBoundingClientRect() ??
                                    {};
                                const scrollableContainerRect = getScrollableContainer(this.scrollableContainer()?.nativeElement).getBoundingClientRect();
                                return {
                                    '--relative-x': `${Math.max(x, scrollableContainerRect.x)}px`,
                                    '--relative-y': `${Math.max(y, scrollableContainerRect.y)}px`,
                                    '--relative-width': `${Math.min(width, Math.max(0, width -
                                        Math.max(0, right - scrollableContainerRect.right) -
                                        Math.max(0, scrollableContainerRect.x - x)))}px`,
                                    '--relative-height': `${Math.min(height, Math.max(0, height -
                                        Math.max(0, bottom - scrollableContainerRect.bottom) -
                                        Math.max(0, scrollableContainerRect.y - y)))}px`,
                                };
                            })(),
                            ...(() => {
                                const { x, y, width, height } = this.dialogRef()?.nativeElement.getBoundingClientRect() ??
                                    {};
                                return {
                                    '--dialog-x': `${x}px`,
                                    '--dialog-y': `${y}px`,
                                    '--dialog-width': `${width}px`,
                                    '--dialog-height': `${height}px`,
                                };
                            })(),
                        }
                        : {}),
                },
            });
        }
    };
    scheduleDialogOpen = async () => {
        // ! check again to make sure we open dialog just if external
        // ! state specify now that the dialog should be opened
        // This check is needed because due to asynchronously downloading
        // the function, it might be downloaded later than scheduleDialogClose
        // an in that case close would take place before scheduleDialogOpen,
        // and this will end up, having dialog open, even if external state
        // specify that it should be closed
        if (this.open()) {
            this.dialogPositionStyle.set({
                ...this.dialogPositionStyle(),
                value: {
                    ...this.dialogPositionStyle().value,
                    visibility: 'hidden',
                },
            });
            this.openDialogTimeoutID.set(setTimeout(async () => {
                // ! check again to make sure we open dialog just if external
                // ! state specify now that the dialog should be opened
                if (this.open()) {
                    await nextTickRender(); // wait for dialog to have `visibility: hidden` set
                    // before showing it
                    // This is important in order to avoid the display of it on a position
                    // inappropriate with requested/available placement
                    // * (at this moment we don't have the dialog sizes,
                    // * and it is not positioned on requested/available placement)
                    const positionDialogAndMakeItVisible = new ResizeObserver(async () => {
                        await this.positionDialog();
                        await this.positionDialog(); // call a second time to make sure that the size of dialog is computed properly
                        // (the first time when we call positionDialog the browser doesn't compute the height/width of dialog properly)
                        this.dialogPositionStyle.set({
                            ...this.dialogPositionStyle(),
                            value: {
                                ...this.dialogPositionStyle().value,
                                visibility: 'visible',
                            },
                        });
                        this.dialogAnimationState.set('show');
                        positionDialogAndMakeItVisible.disconnect();
                    });
                    if (this.dialogRef()) {
                        positionDialogAndMakeItVisible.observe(this.dialogRef().nativeElement);
                        this.dialogWithBridgeRef()?.nativeElement.showPopover();
                        this.dialogIsOpenLocalState.set(true);
                    }
                }
            }, this.enterDelay()));
        }
    };
    closeDialog = () => {
        // ! check again to make sure we close dialog just if external
        // ! state specify now that the dialog should be closed
        if (!this.open()) {
            this.dialogWithBridgeRef()?.nativeElement.hidePopover();
            this.dialogIsOpenLocalState.set(false);
            this.dialogPositionStyle.set({
                ...this.dialogPositionStyle(),
                currentPlacement: undefined,
                value: {},
                maxHeight: '',
                maxWidth: '',
            });
            const scrollableContainer = getScrollableContainer(this.scrollableContainer()?.nativeElement);
            scrollableContainer.removeEventListener('scroll', this.positionDialog);
        }
    };
    scheduleDialogClose = () => {
        // check again to make sure we close dialog just if external
        // state specify now that the dialog should be closed
        if (!this.open()) {
            this.dialogAnimationState.set('hide');
            this.closeDialogTimeoutID.set(setTimeout(() => {
                this.closeDialog();
            }, this.leaveDelay()));
        }
    };
    cancelDialogOpen = () => {
        clearTimeout(this.openDialogTimeoutID());
        this.openDialogTimeoutID.set(undefined);
        this.dialogAnimationState.set('hide');
    };
    cancelDialogClose = () => {
        clearTimeout(this.closeDialogTimeoutID());
        this.closeDialogTimeoutID.set(undefined);
        this.dialogAnimationState.set('show');
    };
    handleClickOutsideClose = async (event) => {
        if (this.dialogWithBridgeRef()?.nativeElement !== event.target &&
            !this.dialogWithBridgeRef()?.nativeElement.contains(event.target) &&
            this.relativeElementRef()?.nativeElement !== event.target &&
            !this.relativeElementRef()?.nativeElement.contains(event.target)) {
            this.onClose$?.emit();
        }
    };
    handleOpenAction = () => {
        this.onOpen$?.emit();
    };
    async ngOnChanges(changes) {
        if ('open' in changes) {
            await this.toggleVisibility();
        }
    }
    toggleVisibility = async () => {
        const shouldDialogOpen = this.open();
        if (shouldDialogOpen) {
            this.cancelDialogClose();
            await this.scheduleDialogOpen();
        }
        else {
            this.cancelDialogOpen();
            if (this.dialogIsOpenLocalState()) {
                this.scheduleDialogClose();
            }
        }
    };
    handleRelativeElementMouseOrFocusLeave = (event) => {
        if (this.dialogWithBridgeRef()?.nativeElement !== event.relatedTarget &&
            (!(event.relatedTarget instanceof Node) ||
                !this.dialogWithBridgeRef()?.nativeElement.contains(event.relatedTarget))) {
            this.onClose$.emit();
        }
    };
    handleMouseOrFocusLeaveDialog = async (event) => {
        if (this.relativeElementRef()?.nativeElement !== event.relatedTarget &&
            (!(event.relatedTarget instanceof Node) ||
                !this.relativeElementRef()?.nativeElement.contains(event.relatedTarget))) {
            this.onClose$.emit();
        }
    };
    handleMouseEnter = async () => {
        this.onOpen$?.emit(); // emit open to parent to make sure it will have open state also
        await this.cancelDialogClose();
    };
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: NgxTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: NgxTooltipComponent, isStandalone: true, selector: "ngx-tooltip", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, preferredPlacement: { classPropertyName: "preferredPlacement", publicName: "preferredPlacement", isSignal: true, isRequired: false, transformFunction: null }, orderOfPlacementsToBeTried: { classPropertyName: "orderOfPlacementsToBeTried", publicName: "orderOfPlacementsToBeTried", isSignal: true, isRequired: false, transformFunction: null }, enterDelay: { classPropertyName: "enterDelay", publicName: "enterDelay", isSignal: true, isRequired: false, transformFunction: null }, leaveDelay: { classPropertyName: "leaveDelay", publicName: "leaveDelay", isSignal: true, isRequired: false, transformFunction: null }, triggerActions: { classPropertyName: "triggerActions", publicName: "triggerActions", isSignal: true, isRequired: false, transformFunction: null }, arrow: { classPropertyName: "arrow", publicName: "arrow", isSignal: true, isRequired: false, transformFunction: null }, dialogOffset: { classPropertyName: "dialogOffset", publicName: "dialogOffset", isSignal: true, isRequired: false, transformFunction: null }, scrollableContainer: { classPropertyName: "scrollableContainer", publicName: "scrollableContainer", isSignal: true, isRequired: false, transformFunction: null }, tooltipRootClass: { classPropertyName: "tooltipRootClass", publicName: "tooltipRootClass", isSignal: true, isRequired: false, transformFunction: null }, tooltipClass: { classPropertyName: "tooltipClass", publicName: "tooltipClass", isSignal: true, isRequired: false, transformFunction: null }, placementStrategy: { classPropertyName: "placementStrategy", publicName: "placementStrategy", isSignal: true, isRequired: false, transformFunction: null }, dialogMinMaxSizes: { classPropertyName: "dialogMinMaxSizes", publicName: "dialogMinMaxSizes", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onOpen$: "onOpen$", onClose$: "onClose$" }, viewQueries: [{ propertyName: "relativeElementRef", first: true, predicate: ["relativeElementRef"], descendants: true, isSignal: true }, { propertyName: "dialogWithBridgeRef", first: true, predicate: ["dialogWithBridgeRef"], descendants: true, isSignal: true }, { propertyName: "dialogRef", first: true, predicate: ["dialogRef"], descendants: true, isSignal: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"ngxTooltip-root-container\">\n  <div\n    #relativeElementRef\n    class=\"ngxTooltip-relative-element\"\n    [attr.popovertarget]=\"tooltipId\"\n    (mouseenter)=\"\n      triggerActions().includes('hover') ? handleOpenAction() : undefined\n    \"\n    (mouseleave)=\"\n      triggerActions().includes('hover')\n        ? handleRelativeElementMouseOrFocusLeave($event)\n        : undefined\n    \"\n    (focusin)=\"\n      triggerActions().includes('focus') ? handleOpenAction() : undefined\n    \"\n    (focusout)=\"\n      triggerActions().includes('focus')\n        ? handleRelativeElementMouseOrFocusLeave($event)\n        : undefined\n    \"\n    (click)=\"\n      triggerActions().includes('click') ? handleOpenAction() : undefined\n    \"\n  >\n    <ng-content select=\".relative-element\"></ng-content>\n  </div>\n\n  <div\n    class=\"ngxTooltip-dialog-with-bridge {{ tooltipRootClass() }}\"\n    [ngClass]=\"[\n      dialogPositionStyle().currentPlacement\n        ? 'ngxTooltip-placement-' + dialogPositionStyle().currentPlacement\n        : '',\n      dialogAnimationState() === 'initial' ? 'ngxTooltip-initial' : '',\n      dialogAnimationState() === 'show' ? 'ngxTooltip-show' : '',\n      dialogAnimationState() === 'hide' ? 'ngxTooltip-hide' : ''\n    ]\"\n    #dialogWithBridgeRef\n    popover=\"manual\"\n    [attr.id]=\"tooltipId\"\n    role=\"tooltip\"\n    [attr.data-dialog-placement]=\"preferredPlacement()\"\n    [ngStyle]=\"{\n      'visibility': dialogPositionStyle().value['visibility'] ?? '',\n      'bottom': dialogPositionStyle().value['bottom'] ?? '',\n      'top': dialogPositionStyle().value['top'] ?? '',\n      'left': dialogPositionStyle().value['left'] ?? '',\n      'right': dialogPositionStyle().value['right'] ?? '',\n      '--scrollbar-height': dialogPositionStyle().value['--scrollbar-height'] ?? '',\n      '--relative-x': dialogPositionStyle().value['--relative-x'] ?? '',\n      '--relative-y': dialogPositionStyle().value['--relative-y'] ?? '',\n      '--relative-width': dialogPositionStyle().value['--relative-width'] ?? '',\n      '--relative-height': dialogPositionStyle().value['--relative-height'] ?? '',\n      '--dialog-x': dialogPositionStyle().value['--dialog-x'] ?? '',\n      '--dialog-y': dialogPositionStyle().value['--dialog-y'] ?? '',\n      '--dialog-width': dialogPositionStyle().value['--dialog-width'] ?? '',\n      '--dialog-height': dialogPositionStyle().value['--dialog-height'] ?? '',\n      'max-width': dialogPositionStyle().maxWidth,\n      '--dialog-offset.px': (computedDialogOffset()),\n      '--close-timeout.ms': leaveDelay(),\n      '--arrow-size.px': arrow() ? arrowSize() : 0,\n    }\"\n    (mouseenter)=\"\n      triggerActions().includes('hover') ? handleMouseEnter() : undefined\n    \"\n    (mouseleave)=\"\n      triggerActions().includes('hover')\n        ? handleMouseOrFocusLeaveDialog($event)\n        : undefined\n    \"\n  >\n    <div\n      class=\"ngxTooltip-inner-dialog-with-bridge\"\n      #dialogRef\n      (focusout)=\"\n        triggerActions().includes('focus')\n          ? handleMouseOrFocusLeaveDialog($event)\n          : undefined\n      \"\n    >\n      <div class=\"ngxTooltip-animated-inner-dialog-with-bridge\">\n        <div\n          class=\"ngxTooltip-tooltip tooltipClass\"\n          [ngStyle]=\"{\n            'max-height':\n              dialogPositionStyle().maxHeight !== ''\n                ? dialogPositionStyle().maxHeight\n                : dialogMinMaxSizes()?.dialogMaxHeight !== undefined\n                ? dialogMinMaxSizes()?.dialogMaxHeight + 'px'\n                : ''\n          }\"\n        >\n          <ng-content select=\".message\"></ng-content>\n        </div>\n\n        @if (arrow()) {\n        <ngx-tooltip-arrow [arrowSize]=\"arrowSize()\" />\n        }\n      </div>\n    </div>\n  </div>\n</div>\n", styles: [":host{width:auto;display:block}.ngxTooltip-root-container{display:flex;width:100%}.ngxTooltip-dialog-with-bridge,.ngxTooltip-inner-dialog-with-bridge{border:unset;padding:unset;background:transparent;overflow:hidden}.ngxTooltip-show .ngxTooltip-animated-inner-dialog-with-bridge{animation:ngxTooltip-show .15s cubic-bezier(0,0,.2,1) forwards}.ngxTooltip-hide .ngxTooltip-animated-inner-dialog-with-bridge{animation:ngxTooltip-hide .15s cubic-bezier(0,0,.2,1) forwards;animation-delay:calc(var(--close-timeout) - .15s)}.ngxTooltip-tooltip{display:flex;width:fit-content;max-width:600px;max-height:calc(100vh - 1px - var(--scrollbar-height));height:100%;padding:4px 8px;border:unset;border-radius:4px;margin:0;overflow-wrap:break-word;font-size:12px;color:#fff;background-color:#616161eb;transform-origin:center top}.ngxTooltip-tooltip:first-child{overflow:auto}.ngxTooltip-placement-top-start .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-top .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-top-end .ngxTooltip-animated-inner-dialog-with-bridge{padding-bottom:calc(var(--dialog-offset) + var(--arrow-size))}.ngxTooltip-placement-bottom-start .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-bottom .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-bottom-end .ngxTooltip-animated-inner-dialog-with-bridge{padding-top:calc(var(--dialog-offset) + var(--arrow-size))}.ngxTooltip-placement-left-start .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-left .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-left-end .ngxTooltip-animated-inner-dialog-with-bridge{padding-right:calc(var(--dialog-offset) + var(--arrow-size))}.ngxTooltip-placement-right-start .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-right .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-right-end .ngxTooltip-animated-inner-dialog-with-bridge{padding-left:calc(var(--dialog-offset) + var(--arrow-size))}.ngxTooltip-relative-element{display:inline-block;width:100%;height:100%}@keyframes ngxTooltip-show{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes ngxTooltip-hide{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.8)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: NgxTooltipArrowComponent, selector: "ngx-tooltip-arrow", inputs: ["arrowSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: NgxTooltipComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ngx-tooltip', imports: [CommonModule, NgxTooltipArrowComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"ngxTooltip-root-container\">\n  <div\n    #relativeElementRef\n    class=\"ngxTooltip-relative-element\"\n    [attr.popovertarget]=\"tooltipId\"\n    (mouseenter)=\"\n      triggerActions().includes('hover') ? handleOpenAction() : undefined\n    \"\n    (mouseleave)=\"\n      triggerActions().includes('hover')\n        ? handleRelativeElementMouseOrFocusLeave($event)\n        : undefined\n    \"\n    (focusin)=\"\n      triggerActions().includes('focus') ? handleOpenAction() : undefined\n    \"\n    (focusout)=\"\n      triggerActions().includes('focus')\n        ? handleRelativeElementMouseOrFocusLeave($event)\n        : undefined\n    \"\n    (click)=\"\n      triggerActions().includes('click') ? handleOpenAction() : undefined\n    \"\n  >\n    <ng-content select=\".relative-element\"></ng-content>\n  </div>\n\n  <div\n    class=\"ngxTooltip-dialog-with-bridge {{ tooltipRootClass() }}\"\n    [ngClass]=\"[\n      dialogPositionStyle().currentPlacement\n        ? 'ngxTooltip-placement-' + dialogPositionStyle().currentPlacement\n        : '',\n      dialogAnimationState() === 'initial' ? 'ngxTooltip-initial' : '',\n      dialogAnimationState() === 'show' ? 'ngxTooltip-show' : '',\n      dialogAnimationState() === 'hide' ? 'ngxTooltip-hide' : ''\n    ]\"\n    #dialogWithBridgeRef\n    popover=\"manual\"\n    [attr.id]=\"tooltipId\"\n    role=\"tooltip\"\n    [attr.data-dialog-placement]=\"preferredPlacement()\"\n    [ngStyle]=\"{\n      'visibility': dialogPositionStyle().value['visibility'] ?? '',\n      'bottom': dialogPositionStyle().value['bottom'] ?? '',\n      'top': dialogPositionStyle().value['top'] ?? '',\n      'left': dialogPositionStyle().value['left'] ?? '',\n      'right': dialogPositionStyle().value['right'] ?? '',\n      '--scrollbar-height': dialogPositionStyle().value['--scrollbar-height'] ?? '',\n      '--relative-x': dialogPositionStyle().value['--relative-x'] ?? '',\n      '--relative-y': dialogPositionStyle().value['--relative-y'] ?? '',\n      '--relative-width': dialogPositionStyle().value['--relative-width'] ?? '',\n      '--relative-height': dialogPositionStyle().value['--relative-height'] ?? '',\n      '--dialog-x': dialogPositionStyle().value['--dialog-x'] ?? '',\n      '--dialog-y': dialogPositionStyle().value['--dialog-y'] ?? '',\n      '--dialog-width': dialogPositionStyle().value['--dialog-width'] ?? '',\n      '--dialog-height': dialogPositionStyle().value['--dialog-height'] ?? '',\n      'max-width': dialogPositionStyle().maxWidth,\n      '--dialog-offset.px': (computedDialogOffset()),\n      '--close-timeout.ms': leaveDelay(),\n      '--arrow-size.px': arrow() ? arrowSize() : 0,\n    }\"\n    (mouseenter)=\"\n      triggerActions().includes('hover') ? handleMouseEnter() : undefined\n    \"\n    (mouseleave)=\"\n      triggerActions().includes('hover')\n        ? handleMouseOrFocusLeaveDialog($event)\n        : undefined\n    \"\n  >\n    <div\n      class=\"ngxTooltip-inner-dialog-with-bridge\"\n      #dialogRef\n      (focusout)=\"\n        triggerActions().includes('focus')\n          ? handleMouseOrFocusLeaveDialog($event)\n          : undefined\n      \"\n    >\n      <div class=\"ngxTooltip-animated-inner-dialog-with-bridge\">\n        <div\n          class=\"ngxTooltip-tooltip tooltipClass\"\n          [ngStyle]=\"{\n            'max-height':\n              dialogPositionStyle().maxHeight !== ''\n                ? dialogPositionStyle().maxHeight\n                : dialogMinMaxSizes()?.dialogMaxHeight !== undefined\n                ? dialogMinMaxSizes()?.dialogMaxHeight + 'px'\n                : ''\n          }\"\n        >\n          <ng-content select=\".message\"></ng-content>\n        </div>\n\n        @if (arrow()) {\n        <ngx-tooltip-arrow [arrowSize]=\"arrowSize()\" />\n        }\n      </div>\n    </div>\n  </div>\n</div>\n", styles: [":host{width:auto;display:block}.ngxTooltip-root-container{display:flex;width:100%}.ngxTooltip-dialog-with-bridge,.ngxTooltip-inner-dialog-with-bridge{border:unset;padding:unset;background:transparent;overflow:hidden}.ngxTooltip-show .ngxTooltip-animated-inner-dialog-with-bridge{animation:ngxTooltip-show .15s cubic-bezier(0,0,.2,1) forwards}.ngxTooltip-hide .ngxTooltip-animated-inner-dialog-with-bridge{animation:ngxTooltip-hide .15s cubic-bezier(0,0,.2,1) forwards;animation-delay:calc(var(--close-timeout) - .15s)}.ngxTooltip-tooltip{display:flex;width:fit-content;max-width:600px;max-height:calc(100vh - 1px - var(--scrollbar-height));height:100%;padding:4px 8px;border:unset;border-radius:4px;margin:0;overflow-wrap:break-word;font-size:12px;color:#fff;background-color:#616161eb;transform-origin:center top}.ngxTooltip-tooltip:first-child{overflow:auto}.ngxTooltip-placement-top-start .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-top .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-top-end .ngxTooltip-animated-inner-dialog-with-bridge{padding-bottom:calc(var(--dialog-offset) + var(--arrow-size))}.ngxTooltip-placement-bottom-start .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-bottom .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-bottom-end .ngxTooltip-animated-inner-dialog-with-bridge{padding-top:calc(var(--dialog-offset) + var(--arrow-size))}.ngxTooltip-placement-left-start .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-left .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-left-end .ngxTooltip-animated-inner-dialog-with-bridge{padding-right:calc(var(--dialog-offset) + var(--arrow-size))}.ngxTooltip-placement-right-start .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-right .ngxTooltip-animated-inner-dialog-with-bridge,.ngxTooltip-placement-right-end .ngxTooltip-animated-inner-dialog-with-bridge{padding-left:calc(var(--dialog-offset) + var(--arrow-size))}.ngxTooltip-relative-element{display:inline-block;width:100%;height:100%}@keyframes ngxTooltip-show{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes ngxTooltip-hide{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.8)}}\n"] }]
        }], ctorParameters: () => [] });

/*
 * Public API Surface of ngx-tooltip
 */

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

export { NgxTooltipComponent, defaultOrderOfPlacementsToBeTried };
//# sourceMappingURL=controllable-ui-ngx-tooltip.mjs.map