UNPKG

@progress/kendo-angular-tooltip

Version:

Kendo UI Tooltip for Angular - A highly customizable and easily themeable tooltip from the creators developers trust for professional Angular components.

2,543 lines • 97.3 kB
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import * as i0 from '@angular/core';
import { forwardRef, Directive, Input, Optional, isDevMode, EventEmitter, Component, HostBinding, Output, ViewChild, ContentChild, ElementRef, Injectable, InjectionToken, Inject, NgModule } from '@angular/core';
import * as i1 from '@progress/kendo-angular-l10n';
import { ComponentMessages, LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
import { PreventableEvent, focusableSelector, Keys, isDocumentAvailable, closest, hasObservers, ResizeBatchService } from '@progress/kendo-angular-common';
import * as i1$1 from '@progress/kendo-angular-popup';
import { PopupService } from '@progress/kendo-angular-popup';
import { take, auditTime, filter } from 'rxjs/operators';
import { Subscription, BehaviorSubject, Subject, combineLatest, fromEvent } from 'rxjs';
import { validatePackage } from '@progress/kendo-licensing';
import { NgIf, NgStyle, NgClass, NgTemplateOutlet } from '@angular/common';
import { xIcon } from '@progress/kendo-svg-icons';
import { IconWrapperComponent, IconsService } from '@progress/kendo-angular-icons';

/**
 * @hidden
 */
class LocalizedMessagesDirective extends ComponentMessages {
    service;
    /**
     * The title of the close button.
     */
    closeTitle;
    constructor(service) {
        super();
        this.service = service;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LocalizedMessagesDirective, isStandalone: true, selector: "[kendoTooltipLocalizedMessages]", inputs: { closeTitle: "closeTitle" }, providers: [
            {
                provide: ComponentMessages,
                useExisting: forwardRef(() => LocalizedMessagesDirective)
            }
        ], usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedMessagesDirective, decorators: [{
            type: Directive,
            args: [{
                    providers: [
                        {
                            provide: ComponentMessages,
                            useExisting: forwardRef(() => LocalizedMessagesDirective)
                        }
                    ],
                    selector: `[kendoTooltipLocalizedMessages]`,
                    standalone: true
                }]
        }], ctorParameters: function () { return [{ type: i1.LocalizationService }]; }, propDecorators: { closeTitle: [{
                type: Input
            }] } });

/**
 * @hidden
 */
const ERRORS = {
    popover: `Invalid value provided for the 'popover' property. The accepted data types are 'PopoverComponent' or 'PopoverFn'.`,
    templateData: `templateData must be a function, but received`,
    showOn: `Invalid value provided for the 'showOn' property. The available options are 'click', 'hover', 'focus' or 'none'.`
};

/**
 * Arguments for the `show` event. The `show` event fires when a popover is about
 * to be opened. If you cancel the event, the opening is prevented.
 */
class PopoverShowEvent extends PreventableEvent {
    /**
     * The host element related to the popover.
     */
    anchor;
    /**
     * @hidden
     * Constructs the event arguments for the `show` event.
     * @param anchor - The host element related to the popover.
     */
    constructor(anchor) {
        super();
        this.anchor = anchor;
    }
}
/**
 * Arguments for the `hide` event. The `hide` event fires when a popover is about
 * to be closed. If you cancel the event, the popover stays open.
 */
class PopoverHideEvent extends PreventableEvent {
    /**
     * The host element related to the popover.
     */
    anchor;
    /**
     * The popover element.
     */
    popover;
    /**
     * @hidden
     * Constructs the event arguments for the `hide` event.
     * @param anchor - The host element related to the popover.
     * @param popover - The popover element.
     */
    constructor(anchor, popover) {
        super();
        this.anchor = anchor;
        this.popover = popover;
    }
}
/**
 * Arguments for the `shown` event. The `shown` event fires after the popover has opened and its opening animation has finished.
 */
class PopoverShownEvent {
    /**
     * The host element related to the popover.
     */
    anchor;
    /**
     * The popover element.
     */
    popover;
    /**
     * @hidden
     * Constructs the event arguments for the `shown` event.
     * @param anchor - The host element related to the popover.
     * @param popover - The popover element.
     */
    constructor(anchor, popover) {
        this.anchor = anchor;
        this.popover = popover;
    }
}
/**
 * Arguments for the `hidden` event. The `hidden` event fires after the popover has closed and its closing animation has finished.
 */
class PopoverHiddenEvent {
    /**
     * The host element related to the popover.
     */
    anchor;
    /**
     * @hidden
     * Constructs the event arguments for the `hidden` event.
     * @param anchor - The host element related to the popover.
     */
    constructor(anchor) {
        this.anchor = anchor;
    }
}

/**
 * @hidden
 */
let idx = 0;
/**
 * @hidden
 */
let popoverTitleIdx = 0;
/**
 * @hidden
 */
let popoverBodyIdx = 0;
/**
 * @hidden
 */
const getId = (prefix, idSource) => {
    switch (idSource) {
        case 'popoverTitle':
            return `${prefix}-${++popoverTitleIdx}`;
        case 'popoverBody':
            return `${prefix}-${++popoverBodyIdx}`;
        default:
            return `${prefix}-${++idx}`;
    }
};
/**
 * @hidden
 */
function align(position, offset) {
    let anchorAlign = {};
    let popupAlign = {};
    let popupMargin = {};
    switch (position) {
        case 'top':
            anchorAlign = { horizontal: 'center', vertical: 'top' };
            popupAlign = { horizontal: 'center', vertical: 'bottom' };
            popupMargin = { horizontal: 0, vertical: offset };
            break;
        case 'bottom':
            anchorAlign = { horizontal: 'center', vertical: 'bottom' };
            popupAlign = { horizontal: 'center', vertical: 'top' };
            popupMargin = { horizontal: 0, vertical: offset };
            break;
        case 'right':
            anchorAlign = { horizontal: 'right', vertical: 'center' };
            popupAlign = { horizontal: 'left', vertical: 'center' };
            popupMargin = { horizontal: offset, vertical: 0 };
            break;
        case 'left':
            anchorAlign = { horizontal: 'left', vertical: 'center' };
            popupAlign = { horizontal: 'right', vertical: 'center' };
            popupMargin = { horizontal: offset, vertical: 0 };
            break;
        default: break;
    }
    return {
        anchorAlign,
        popupAlign,
        popupMargin
    };
}
/**
 * @hidden
 */
function collision(inputcollision, position) {
    if (inputcollision) {
        return inputcollision;
    }
    if (position === 'top' || position === 'bottom') {
        return { horizontal: 'fit', vertical: 'flip' };
    }
    return { horizontal: 'flip', vertical: 'fit' };
}
function isDocumentNode(container) {
    return container.nodeType === 9;
}
/**
 * @hidden
 */
function closestBySelector(element, selector) {
    if (element.closest) {
        return element.closest(selector);
    }
    const matches = Element.prototype.matches ?
        (el, sel) => el.matches(sel)
        : (el, sel) => el.msMatchesSelector(sel);
    let node = element;
    while (node && !isDocumentNode(node)) {
        if (matches(node, selector)) {
            return node;
        }
        node = node.parentNode;
    }
}
/**
 * @hidden
 */
function contains(container, child) {
    if (!container) {
        return false;
    }
    if (isDocumentNode(container)) {
        return false;
    }
    if (container.contains) {
        return container.contains(child);
    }
    if (container.compareDocumentPosition) {
        return !!(container.compareDocumentPosition(child) & Node.DOCUMENT_POSITION_CONTAINED_BY);
    }
}
/**
 * @hidden
 */
const hasParent = (node, parent) => {
    while (node && node !== parent) {
        node = node.parentNode;
    }
    return node;
};
/**
 * @hidden
 */
function getCenterOffset(item, dir, size) {
    const rect = item.getBoundingClientRect();
    return rect[dir] + (rect[size] / 2);
}
/**
 * @hidden
 */
function containsItem(collection, item) {
    return collection.indexOf(item) !== -1;
}
/**
 * @hidden
 */
function getAllFocusableChildren(parent) {
    return parent.querySelectorAll(focusableSelector);
}
/**
 * @hidden
 */
function getFirstAndLastFocusable(parent) {
    const all = getAllFocusableChildren(parent);
    const firstFocusable = all.length > 0 ? all[0] : parent;
    const lastFocusable = all.length > 0 ? all[all.length - 1] : parent;
    return [firstFocusable, lastFocusable];
}

/**
 * @hidden
 */
const packageMetadata = {
    name: '@progress/kendo-angular-tooltip',
    productName: 'Kendo UI for Angular',
    productCode: 'KENDOUIANGULAR',
    productCodes: ['KENDOUIANGULAR'],
    publishDate: 1743579699,
    version: '18.4.0',
    licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
};

/**
 * Represents a template that defines the content of the Popover title.
 *
 * To define the template, nest an `<ng-template>` tag
 * with the `kendoPopoverTitleTemplate` directive inside the `<kendo-popover>` tag.
 */
class PopoverTitleTemplateDirective {
    templateRef;
    constructor(templateRef) {
        this.templateRef = templateRef;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverTitleTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: PopoverTitleTemplateDirective, isStandalone: true, selector: "[kendoPopoverTitleTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverTitleTemplateDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[kendoPopoverTitleTemplate]',
                    standalone: true
                }]
        }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
                    type: Optional
                }] }]; } });

/**
 * Represents a template that defines the content of the Popover body.
 *
 * To define the template, nest an `<ng-template>` tag
 * with the `kendoPopoverBodyTemplate` directive inside the `<kendo-popover>` tag.
 */
class PopoverBodyTemplateDirective {
    templateRef;
    constructor(templateRef) {
        this.templateRef = templateRef;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverBodyTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: PopoverBodyTemplateDirective, isStandalone: true, selector: "[kendoPopoverBodyTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverBodyTemplateDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[kendoPopoverBodyTemplate]',
                    standalone: true
                }]
        }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
                    type: Optional
                }] }]; } });

/**
 * Represents a template that defines the content of the Popover actions.
 *
 * To define the template, nest an `<ng-template>` tag
 * with the `kendoPopoverActionsTemplate` directive inside the `<kendo-popover>` tag.
 */
class PopoverActionsTemplateDirective {
    templateRef;
    constructor(templateRef) {
        this.templateRef = templateRef;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverActionsTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: PopoverActionsTemplateDirective, isStandalone: true, selector: "[kendoPopoverActionsTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverActionsTemplateDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[kendoPopoverActionsTemplate]',
                    standalone: true
                }]
        }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
                    type: Optional
                }] }]; } });

/* eslint-disable @typescript-eslint/no-explicit-any */
/**
 * Represents the [Kendo UI Popover component for Angular]({% slug overview_popover %}).
 * Used to display additional information that is related to a target element.
 *
 * @example
 * ```ts-no-run
 * <kendo-popover>
 *    <ng-template kendoPopoverTitleTemplate>Foo Title</ng-template>
 *    <ng-template kendoPopoverBodyTemplate>Foo Body</ng-template>
 *    <ng-template kendoPopoverActionsTemplate>Foo Actions</ng-template>
 * </kendo-popover>
 * ```
 */
class PopoverComponent {
    localization;
    renderer;
    element;
    zone;
    /**
     * @hidden
     */
    anchor;
    /**
     * Specifies the position of the Popover in relation to its anchor element. [See example]({% slug positioning_popover %})
     *
     * The possible options are:
     * `top`
     * `bottom`
     * `right` (Default)
     * `left`
     */
    position = 'right';
    /**
     * Specifies the distance from the Popover to its anchor element in pixels.
     *
     * @default `6`
     */
    set offset(value) {
        this._offset = value;
    }
    get offset() {
        const calloutBuffer = 14;
        return this.callout
            ? calloutBuffer + this._offset
            : this._offset;
    }
    /**
     * Determines the width of the popover. Numeric values are treated as pixels.
     * @default 'auto'
     */
    set width(value) {
        this._width = typeof value === 'number' ? `${value}px` : value;
    }
    get width() {
        return this._width;
    }
    /**
     * Determines the height of the popover. Numeric values are treated as pixels.
     * @default 'auto'
     */
    set height(value) {
        this._height = typeof value === 'number' ? `${value}px` : value;
    }
    get height() {
        return this._height;
    }
    /**
     * @hidden
     */
    direction;
    /**
     * Specifies the main header text of the Popover.
     *
     * If a `titleTemplate` is provided it would take precedence over the title.
     */
    title;
    /**
     * @hidden
     * Specifies the secondary header text of the Popover.
     *
     * If a `titleTemplate` is provided it would take precedence over the subtitle.
     */
    subtitle;
    /**
     * Represents the text that will be rendered in the Popover body section.
     *
     * If a `bodyTemplate` is provided it would take precedence over this text.
     */
    body;
    /**
     * Determines whether a callout will be rendered along the Popover. [See example]({% slug callout_popover %})
     *
     * @default true
     */
    callout = true;
    /**
     * Enables and configures the Popover animation. [See example]({% slug animations_popover %})
     *
     * The possible options are:
     *
     * * `boolean`&mdash;Enables the default animation
     * * `PopoverAnimation`&mdash;A configuration object which allows setting the `direction`, `duration` and `type` of the animation.
     *
     * @default false
     */
    animation = false;
    /**
     * Defines a callback function which returns custom data passed to the Popover templates.
     * It exposes the current anchor element as an argument. [See example](slug:templates_popover#toc-passing-data-to-templates)
     */
    set templateData(fn) {
        if (isDevMode && typeof fn !== 'function') {
            throw new Error(`${ERRORS.templateData} ${JSON.stringify(fn)}.`);
        }
        this._templateData = fn;
    }
    get templateData() {
        return this._templateData;
    }
    /**
     * @hidden
     * Determines the visibility of the Popover.
     */
    visible = false;
    /**
     * @hidden
     */
    get isHidden() {
        return !this.visible;
    }
    /**
     * @hidden
     */
    get hasAttributeHidden() {
        return !this.visible;
    }
    /**
     * Fires before the Popover is about to be shown ([see example]({% slug events_popover %})).
     * The event is preventable. If canceled, the Popover will not be displayed. [See example]({% slug events_popover %})
     */
    show = new EventEmitter();
    /**
     * Fires after the Popover has been shown and the animation has ended. [See example]({% slug events_popover %})
     */
    shown = new EventEmitter();
    /**
     * Fires when the Popover is about to be hidden ([see example]({% slug events_popover %})).
     * The event is preventable. If canceled, the Popover will remain visible.
     */
    hide = new EventEmitter();
    /**
     * Fires after the Popover has been hidden and the animation has ended. [See example]({% slug events_popover %})
     */
    hidden = new EventEmitter();
    /**
     * @hidden
     */
    closeOnKeyDown = new EventEmitter();
    /**
     * @hidden
     */
    popoverWrapper;
    /**
     * @hidden
     */
    titleTemplateWrapper;
    /**
     * @hidden
     */
    bodyTemplateWrapper;
    /**
     * @hidden
     */
    titleTemplate;
    /**
     * @hidden
     */
    bodyTemplate;
    /**
     * @hidden
     */
    actionsTemplate;
    /**
     * @hidden
     */
    contextData;
    /**
     * @hidden
     */
    _width = 'auto';
    /**
     * @hidden
     */
    _height = 'auto';
    /**
     * @hidden
     */
    popoverId = '';
    _offset = 6;
    subs = new Subscription();
    constructor(localization, renderer, element, zone) {
        this.localization = localization;
        this.renderer = renderer;
        this.element = element;
        this.zone = zone;
        validatePackage(packageMetadata);
    }
    ngOnInit() {
        this.popoverId = getId('k-popover');
        this.subs.add(this.localization.changes.subscribe(({ rtl }) => { this.direction = rtl ? 'rtl' : 'ltr'; }));
        this.subs.add(this.renderer.listen(this.element.nativeElement, 'keydown', event => this.onKeyDown(event)));
    }
    ngAfterViewInit() {
        this.zone.onStable.pipe(take(1)).subscribe(() => {
            if (this.visible) {
                const wrapper = this.popoverWrapper.nativeElement;
                const focusablePopoverChildren = getAllFocusableChildren(wrapper);
                if (focusablePopoverChildren.length > 0) {
                    focusablePopoverChildren[0].focus();
                }
                this.setAriaAttributes(wrapper, focusablePopoverChildren);
            }
        });
    }
    ngOnDestroy() {
        this.subs.unsubscribe();
    }
    /**
     * @hidden
     */
    getCalloutPosition() {
        switch (this.position) {
            case 'top': return { 'k-callout-s': true };
            case 'bottom': return { 'k-callout-n': true };
            case 'left': return { 'k-callout-e': true };
            case 'right': return { 'k-callout-w': true };
            default: return { 'k-callout-s': true };
        }
    }
    /**
     * @hidden
     */
    onKeyDown(event) {
        const keyCode = event.keyCode;
        const target = event.target;
        if (keyCode === Keys.Tab) {
            this.keepFocusWithinComponent(target, event);
        }
        if (keyCode === Keys.Escape) {
            this.closeOnKeyDown.emit();
        }
    }
    _templateData = () => null;
    keepFocusWithinComponent(target, event) {
        const wrapper = this.popoverWrapper.nativeElement;
        const [firstFocusable, lastFocusable] = getFirstAndLastFocusable(wrapper);
        const tabAfterLastFocusable = !event.shiftKey && target === lastFocusable;
        const shiftTabAfterFirstFocusable = event.shiftKey && target === firstFocusable;
        if (tabAfterLastFocusable) {
            event.preventDefault();
            firstFocusable.focus();
        }
        if (shiftTabAfterFirstFocusable) {
            event.preventDefault();
            lastFocusable.focus();
        }
    }
    setAriaAttributes(wrapper, focusablePopoverChildren) {
        if (this.titleTemplate) {
            const titleRef = this.titleTemplateWrapper.nativeElement;
            const focusableHeaderChildren = getAllFocusableChildren(titleRef).length > 0;
            if (focusableHeaderChildren) {
                const headerId = getId('k-popover-header', 'popoverTitle');
                this.renderer.setAttribute(titleRef, 'id', headerId);
                this.renderer.setAttribute(wrapper, 'aria-labelledby', headerId);
            }
        }
        if (this.bodyTemplate) {
            const bodyRef = this.bodyTemplateWrapper.nativeElement;
            const focusableBodyChildren = getAllFocusableChildren(bodyRef).length > 0;
            if (focusableBodyChildren) {
                const bodyId = getId('k-popover-body', 'popoverBody');
                this.renderer.setAttribute(bodyRef, 'id', bodyId);
                this.renderer.setAttribute(wrapper, 'aria-describedby', bodyId);
            }
        }
        this.renderer.setAttribute(wrapper, 'id', this.popoverId);
        this.renderer.setAttribute(wrapper, 'role', focusablePopoverChildren.length > 0 ? 'dialog' : 'tooltip');
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverComponent, deps: [{ token: i1.LocalizationService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: PopoverComponent, isStandalone: true, selector: "kendo-popover", inputs: { position: "position", offset: "offset", width: "width", height: "height", title: "title", subtitle: "subtitle", body: "body", callout: "callout", animation: "animation", templateData: "templateData" }, outputs: { show: "show", shown: "shown", hide: "hide", hidden: "hidden", closeOnKeyDown: "closeOnKeyDown" }, host: { properties: { "attr.dir": "this.direction", "class.k-hidden": "this.isHidden", "attr.aria-hidden": "this.hasAttributeHidden", "style.width": "this._width", "style.height": "this._height" } }, providers: [
            LocalizationService,
            {
                provide: L10N_PREFIX,
                useValue: 'kendo.popover'
            }
        ], queries: [{ propertyName: "titleTemplate", first: true, predicate: PopoverTitleTemplateDirective, descendants: true }, { propertyName: "bodyTemplate", first: true, predicate: PopoverBodyTemplateDirective, descendants: true }, { propertyName: "actionsTemplate", first: true, predicate: PopoverActionsTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "popoverWrapper", first: true, predicate: ["popoverWrapper"], descendants: true }, { propertyName: "titleTemplateWrapper", first: true, predicate: ["titleTemplateWrapper"], descendants: true }, { propertyName: "bodyTemplateWrapper", first: true, predicate: ["bodyTemplateWrapper"], descendants: true }], ngImport: i0, template: `
    <div #popoverWrapper *ngIf="visible" class="k-popover k-popup" [ngStyle]="{'width': width, 'height': height}">
        <div class="k-popover-callout" [ngClass]="getCalloutPosition()" *ngIf="callout"></div>

        <div class="k-popover-inner" *ngIf="callout; else noCallout">
            <ng-container *ngTemplateOutlet="noCallout"></ng-container>
        </div>

        <ng-template #noCallout>
            <div #titleTemplateWrapper *ngIf="titleTemplate || title" class="k-popover-header">
                <ng-template *ngIf="titleTemplate"
                    [ngTemplateOutlet]="titleTemplate?.templateRef"
                    [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
                </ng-template>
                <ng-container *ngIf="title && !titleTemplate">
                    {{ title }}
                </ng-container>
            </div>

            <div #bodyTemplateWrapper *ngIf="bodyTemplate || body" class="k-popover-body">
                <ng-template *ngIf="bodyTemplate"
                    [ngTemplateOutlet]="bodyTemplate?.templateRef"
                    [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
                </ng-template>
                <ng-container *ngIf="body && !bodyTemplate">
                    {{ body }}
                </ng-container>
            </div>

            <div *ngIf="actionsTemplate" class="k-popover-actions k-actions k-actions-stretched k-actions-horizontal">
                <ng-template *ngIf="actionsTemplate"
                    [ngTemplateOutlet]="actionsTemplate?.templateRef"
                    [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
                </ng-template>
            </div>
        </ng-template>
    </div>
    `, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'kendo-popover',
                    providers: [
                        LocalizationService,
                        {
                            provide: L10N_PREFIX,
                            useValue: 'kendo.popover'
                        }
                    ],
                    template: `
    <div #popoverWrapper *ngIf="visible" class="k-popover k-popup" [ngStyle]="{'width': width, 'height': height}">
        <div class="k-popover-callout" [ngClass]="getCalloutPosition()" *ngIf="callout"></div>

        <div class="k-popover-inner" *ngIf="callout; else noCallout">
            <ng-container *ngTemplateOutlet="noCallout"></ng-container>
        </div>

        <ng-template #noCallout>
            <div #titleTemplateWrapper *ngIf="titleTemplate || title" class="k-popover-header">
                <ng-template *ngIf="titleTemplate"
                    [ngTemplateOutlet]="titleTemplate?.templateRef"
                    [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
                </ng-template>
                <ng-container *ngIf="title && !titleTemplate">
                    {{ title }}
                </ng-container>
            </div>

            <div #bodyTemplateWrapper *ngIf="bodyTemplate || body" class="k-popover-body">
                <ng-template *ngIf="bodyTemplate"
                    [ngTemplateOutlet]="bodyTemplate?.templateRef"
                    [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
                </ng-template>
                <ng-container *ngIf="body && !bodyTemplate">
                    {{ body }}
                </ng-container>
            </div>

            <div *ngIf="actionsTemplate" class="k-popover-actions k-actions k-actions-stretched k-actions-horizontal">
                <ng-template *ngIf="actionsTemplate"
                    [ngTemplateOutlet]="actionsTemplate?.templateRef"
                    [ngTemplateOutletContext]="{ $implicit: anchor, data: contextData }">
                </ng-template>
            </div>
        </ng-template>
    </div>
    `,
                    standalone: true,
                    imports: [NgIf, NgStyle, NgClass, NgTemplateOutlet]
                }]
        }], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.NgZone }]; }, propDecorators: { position: [{
                type: Input
            }], offset: [{
                type: Input
            }], width: [{
                type: Input
            }], height: [{
                type: Input
            }], direction: [{
                type: HostBinding,
                args: ['attr.dir']
            }], title: [{
                type: Input
            }], subtitle: [{
                type: Input
            }], body: [{
                type: Input
            }], callout: [{
                type: Input
            }], animation: [{
                type: Input
            }], templateData: [{
                type: Input
            }], isHidden: [{
                type: HostBinding,
                args: ['class.k-hidden']
            }], hasAttributeHidden: [{
                type: HostBinding,
                args: ['attr.aria-hidden']
            }], show: [{
                type: Output
            }], shown: [{
                type: Output
            }], hide: [{
                type: Output
            }], hidden: [{
                type: Output
            }], closeOnKeyDown: [{
                type: Output
            }], popoverWrapper: [{
                type: ViewChild,
                args: ['popoverWrapper']
            }], titleTemplateWrapper: [{
                type: ViewChild,
                args: ['titleTemplateWrapper']
            }], bodyTemplateWrapper: [{
                type: ViewChild,
                args: ['bodyTemplateWrapper']
            }], titleTemplate: [{
                type: ContentChild,
                args: [PopoverTitleTemplateDirective, { static: false }]
            }], bodyTemplate: [{
                type: ContentChild,
                args: [PopoverBodyTemplateDirective, { static: false }]
            }], actionsTemplate: [{
                type: ContentChild,
                args: [PopoverActionsTemplateDirective, { static: false }]
            }], _width: [{
                type: HostBinding,
                args: ['style.width']
            }], _height: [{
                type: HostBinding,
                args: ['style.height']
            }] } });

/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-explicit-any */
const validShowOptions = ['hover', 'click', 'none', 'focus'];
/**
 * @hidden
 */
class PopoverDirectivesBase {
    ngZone;
    popupService;
    renderer;
    /**
     * Specifies the popover instance that will be rendered.
     * Accepts a [`PopoverComponent`]({% slug api_tooltip_popovercomponent %}) instance or
     * a [`PopoverFn`]({% slug api_tooltip_popoverfn %}) callback which returns a [`PopoverComponent`]({% slug api_tooltip_popovercomponent %}) instance
     * depending on the current anchor element.
     *
     * [See example](slug:templates_popover#toc-passing-data-to-templates)
     */
    set popover(value) {
        if (value instanceof PopoverComponent || typeof value === `function`) {
            this._popover = value;
        }
        else {
            if (isDevMode) {
                throw new Error(ERRORS.popover);
            }
        }
    }
    get popover() {
        return this._popover;
    }
    /**
     * The event on which the Popover will be shown
     *
     * The supported values are:
     * - `click` (default) &mdash;The Popover will be shown when its `anchor` element is clicked.
     * - `hover`&mdash;The Popover will be shown when its `anchor` element is hovered.
     * - `focus`&mdash;The Popover will be shown when its `anchor` element is focused.
     * - `none`&mdash;The Popover will not be shown on user interaction. It could be rendered via the Popover API methods.
     */
    set showOn(value) {
        if (isDevMode && !containsItem(validShowOptions, value)) {
            throw new Error(ERRORS.showOn);
        }
        this._showOn = value;
    }
    get showOn() {
        return this._showOn;
    }
    /**
     * @hidden
     */
    anchor = null;
    popupRef;
    disposeHoverOverListener;
    disposeHoverOutListener;
    disposeClickListener;
    disposePopupHoverOutListener;
    disposePopupHoverInListener;
    disposePopupFocusOutListener;
    subs = new Subscription();
    _popoverService;
    _hideSub;
    _focusInsideSub;
    _popover;
    _showOn = 'click';
    _popupOpenSub;
    _popupCloseSub;
    _popupSubs;
    constructor(ngZone, popupService, renderer) {
        this.ngZone = ngZone;
        this.popupService = popupService;
        this.renderer = renderer;
    }
    ngAfterViewInit() {
        if (!isDocumentAvailable()) {
            return;
        }
        this.manageEvents();
    }
    ngOnDestroy() {
        this.closePopup();
        this.subs.unsubscribe();
        this._popupSubs && this._popupSubs.unsubscribe();
        if (this.disposeHoverOverListener) {
            this.disposeHoverOverListener();
        }
        if (this.disposeHoverOutListener) {
            this.disposeHoverOutListener();
        }
        if (this.disposeClickListener) {
            this.disposeClickListener();
        }
        if (this._focusInsideSub) {
            this._focusInsideSub.unsubscribe();
        }
        if (this._hideSub) {
            this._hideSub.unsubscribe();
        }
        if (this._popupOpenSub) {
            this._popupOpenSub.unsubscribe();
        }
        if (this._popupCloseSub) {
            this._popupCloseSub.unsubscribe();
        }
    }
    /**
     * Hides the Popover ([See example]({% slug programmaticcontrol_popover %})).
     */
    hide() {
        this.closePopup();
    }
    /**
     * @hidden
     */
    closePopup() {
        if (this.popupRef) {
            if (this.anchor) {
                this.renderer.removeAttribute(this.anchor, 'aria-describedby');
            }
            this.popupRef.close();
            this.popupRef = null;
            if (this.disposePopupHoverOutListener) {
                this.disposePopupHoverOutListener();
            }
            if (this.disposePopupHoverInListener) {
                this.disposePopupHoverInListener();
            }
            if (this.disposePopupFocusOutListener) {
                this.disposePopupFocusOutListener();
            }
            this._popupSubs.unsubscribe();
        }
    }
    /**
     * @hidden
     */
    openPopup(anchor) {
        this.anchor = anchor instanceof ElementRef ? anchor.nativeElement : anchor;
        const popoverComp = this.popover instanceof PopoverComponent ? this.popover : this.popover(this.anchor);
        const alignSettings = align(popoverComp.position, popoverComp.offset);
        const anchorAlign = alignSettings.anchorAlign;
        const popupAlign = alignSettings.popupAlign;
        const popupMargin = alignSettings.popupMargin;
        const _animation = popoverComp.animation;
        this.popupRef = this.popupService.open({
            anchor: { nativeElement: this.anchor },
            animate: _animation,
            content: PopoverComponent,
            popupAlign,
            anchorAlign,
            margin: popupMargin,
            collision: { horizontal: 'fit', vertical: 'fit' }
        });
        const popupInstance = this.popupRef.content.instance;
        this._popupSubs = new Subscription();
        if (anchor) {
            this._popupSubs.add(this.renderer.listen(this.anchor, 'keydown', event => this.onKeyDown(event)));
            this.renderer.setAttribute(this.anchor, 'aria-describedby', popupInstance.popoverId);
        }
        this._popupSubs.add(popupInstance.closeOnKeyDown.subscribe(() => {
            this.anchor.focus();
            this.hide();
        }));
        this.applySettings(this.popupRef.content, popoverComp);
        this.monitorPopup();
        this.initializeCompletionEvents(popoverComp, this.anchor);
    }
    /**
     * @hidden
     */
    isPrevented(anchorElement, show) {
        const popoverComp = this.popover instanceof PopoverComponent ? this.popover : this.popover(anchorElement);
        let eventArgs;
        // eslint-disable-next-line prefer-const
        eventArgs = this.initializeEvents(popoverComp, eventArgs, show, anchorElement);
        return eventArgs.isDefaultPrevented();
    }
    /**
     * @hidden
     */
    monitorPopup() {
        if (this.showOn === 'hover') {
            this.ngZone.runOutsideAngular(() => {
                const popup = this.popupRef.popupElement;
                this.disposePopupHoverInListener = this.renderer.listen(popup, 'mouseenter', _ => {
                    this.ngZone.run(_ => this._popoverService.emitPopoverState(true));
                });
                this.disposePopupHoverOutListener = this.renderer.listen(popup, 'mouseleave', _ => {
                    this.ngZone.run(_ => this._popoverService.emitPopoverState(false));
                });
            });
        }
        if (this.showOn === 'focus') {
            this.ngZone.runOutsideAngular(() => {
                const popup = this.popupRef.popupElement;
                this.disposePopupFocusOutListener = this.renderer.listen(popup, 'focusout', (e) => {
                    const isInsidePopover = closest(e.relatedTarget, (node) => node.classList && node.classList.contains('k-popover'));
                    if (!isInsidePopover) {
                        this.ngZone.run(_ => this._popoverService.emitFocusInsidePopover(false));
                    }
                });
            });
        }
    }
    applySettings(contentComponent, popover) {
        const content = contentComponent.instance;
        content.visible = true;
        content.anchor = this.anchor;
        content.position = popover.position;
        content.offset = popover.offset;
        content.width = popover.width;
        content.height = popover.height;
        content.title = popover.title;
        content.body = popover.body;
        content.callout = popover.callout;
        content.animation = popover.animation;
        content.contextData = popover.templateData(this.anchor);
        content.titleTemplate = popover.titleTemplate;
        content.bodyTemplate = popover.bodyTemplate;
        content.actionsTemplate = popover.actionsTemplate;
        this.popupRef.content.changeDetectorRef.detectChanges();
    }
    manageEvents() {
        this.ngZone.runOutsideAngular(() => {
            switch (this.showOn) {
                case 'hover':
                    this.subscribeToShowEvents([{
                            name: 'mouseenter', handler: this.mouseenterHandler
                        }, {
                            name: 'mouseleave', handler: this.mouseleaveHandler
                        }]);
                    break;
                case 'focus':
                    this.subscribeToShowEvents([{
                            name: 'focus', handler: this.focusHandler
                        }, {
                            name: 'blur', handler: this.blurHandler
                        }]);
                    break;
                case 'click':
                    this.subscribeClick();
                    break;
                default:
                    break;
            }
        });
    }
    /**
     * @hidden
     */
    initializeEvents(popoverComp, eventArgs, show, anchorElement) {
        if (show) {
            eventArgs = new PopoverShowEvent(anchorElement);
            if (this.shouldEmitEvent(!!this.popupRef, 'show', popoverComp)) {
                this.ngZone.run(() => popoverComp.show.emit(eventArgs));
            }
        }
        else {
            eventArgs = new PopoverHideEvent(anchorElement, this.popupRef);
            if (this.shouldEmitEvent(!!this.popupRef, 'hide', popoverComp)) {
                this.ngZone.run(() => popoverComp.hide.emit(eventArgs));
            }
        }
        return eventArgs;
    }
    onKeyDown(event) {
        const keyCode = event.keyCode;
        if (keyCode === Keys.Escape) {
            this.hide();
        }
    }
    initializeCompletionEvents(popoverComp, _anchor) {
        if (this.shouldEmitCompletionEvents('shown', popoverComp)) {
            this.popupRef.popupOpen.subscribe(() => {
                const eventArgs = new PopoverShownEvent(_anchor, this.popupRef);
                popoverComp.shown.emit(eventArgs);
            });
        }
        if (this.shouldEmitCompletionEvents('hidden', popoverComp)) {
            this.popupRef.popupClose.subscribe(() => {
                this.ngZone.run(_ => {
                    const eventArgs = new PopoverHiddenEvent(_anchor);
                    popoverComp.hidden.emit(eventArgs);
                });
            });
        }
    }
    shouldEmitEvent(hasPopup, event, popoverComp) {
        if ((event === 'show' && !hasPopup && hasObservers(popoverComp[event]))
            || (event === 'hide' && hasPopup && hasObservers(popoverComp[event]))) {
            return true;
        }
        return false;
    }
    shouldEmitCompletionEvents(event, popoverComp) {
        if ((hasObservers(popoverComp[event]) && !this._popupOpenSub)
            || (hasObservers(popoverComp[event]) && !this._popupCloseSub)) {
            return true;
        }
        return false;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverDirectivesBase, deps: [{ token: i0.NgZone }, { token: i1$1.PopupService }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: PopoverDirectivesBase, inputs: { popover: "popover", showOn: "showOn" }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverDirectivesBase, decorators: [{
            type: Directive,
            args: [{}]
        }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i1$1.PopupService }, { type: i0.Renderer2 }]; }, propDecorators: { popover: [{
                type: Input
            }], showOn: [{
                type: Input
            }] } });

/**
 * @hidden
 */
class PopoverService {
    ngZone;
    _pointerOverPopup = new BehaviorSubject(null);
    _pointerOverAnchor = new BehaviorSubject(null);
    _focusInsidePopover = new BehaviorSubject(null);
    _hidePopover = new Subject();
    _isOrigin;
    originAnchor;
    currentAnchor;
    subs = new Subscription();
    constructor(ngZone) {
        this.ngZone = ngZone;
        this.monitor();
    }
    ngOnDestroy() {
        this.subs.unsubscribe();
    }
    get isPopoverHovered() {
        return this._pointerOverPopup.asObservable();
    }
    emitPopoverState(isHovered) {
        this.ngZone.run(_ => this._pointerOverPopup.next(isHovered));
    }
    get isAnchorHovered() {
        return this._pointerOverAnchor.asObservable();
    }
    emitAnchorState(isHovered, anchor) {
        this._isOrigin = this.originAnchor === anchor;
        this.currentAnchor = anchor;
        if (isHovered) {
            this.originAnchor = anchor;
        }
        this.ngZone.run(_ => this._pointerOverAnchor.next(isHovered));
    }
    get isFocusInsidePopover() {
        return this._focusInsidePopover.asObservable();
    }
    emitFocusInsidePopover(isFocused) {
        this.ngZone.run(_ => this._focusInsidePopover.next(isFocused));
        this._focusInsidePopover.next(null);
    }
    get hidePopover() {
        return this._hidePopover.asObservable();
    }
    monitor() {
        this.subs.add(combineLatest(this.isPopoverHovered, this.isAnchorHovered).pipe(
        // `auditTime` is used because the `mouseleave` event is emitted before `mouseenter`
        // i.e. there is a millisecond in which the pointer leaves the first target (e.g. anchor) and hasn't reached the second one (e.g. popup)
        // resulting in both observables emitting `false`
        auditTime(20)).subscribe(val => {
            const [isPopoverHovered, isAnchorHovered] = val;
            this._hidePopover.next([isPopoverHovered, isAnchorHovered, this._isOrigin, this.currentAnchor]);
        }));
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverService, decorators: [{
            type: Injectable
        }], ctorParameters: function () { return [{ type: i0.NgZone }]; } });

/* eslint-disable @typescript-eslint/no-explicit-any */
/**
 * Represents the [`kendoPopoverAnchor`](slug:configuration_popover#toc-popover-anchor) directive.
 * It is used to target an element, which should display a popover on interaction.
 *
 * @example
 * ```ts-no-run
 * <button kendoPopoverAnchor [popover]="myPopover">Show Popover</button>
 * ```
 */
class PopoverAnchorDirective extends PopoverDirectivesBase {
    hostEl;
    ngZone;
    popupService;
    renderer;
    popoverService;
    constructor(hostEl, ngZone, popupService, renderer, popoverService) {
        super(ngZone, popupService, renderer);
        this.hostEl = hostEl;
        this.ngZone = ngZone;
        this.popupService = popupService;
        this.renderer = renderer;
        this.popoverService = popoverService;
        this._popoverService = this.popoverService;
    }
    ngOnChanges(changes) {
        if (changes['showOn'] && !changes['showOn'].isFirstChange()) {
            this.subs.unsubscribe();
            if (this.disposeClickListener) {
                this.disposeClickListener();
            }
            this.subs = new Subscription();
            this.manageEvents();
        }
    }
    /**
     * Shows the Popover. [See example]({% slug programmaticcontrol_popover %})
     */
    show() {
        if (this.popupRef) {
            return;
        }
        this.ngZone.run(() => {
            this.openPopup(this.hostEl);
        });
        this.popupRef.popupAnchorViewportLeave
            .pipe(take(1))
            .subscribe(() => this.hide());
    }
    /**
     * Toggles the visibility of the Popover. [See example]({% slug programmaticcontrol_popover %})
     */
    toggle() {
        if (this.popupRef) {
            this.hide();
        }
        else {
            this.show();
        }
    }
    subscribeToShowEvents(arr) {
        const hostEl = this.hostEl.nativeElement;
        this.subs.add(this.renderer.listen(hostEl, arr[0].name, () => {
            this.popoverService.emitAnchorState(true, hostEl);
            arr[0].handler();
        }));
        this.subs.add(this.renderer.listen(hostEl, arr[1].name, (e) => {
            this.popoverService.emitAnchorState(false, null);
            arr[1].handler({ domEvent: e });
        }));
    }
    subscribeClick() {
        if (this.disposeClickListener) {
            this.disposeClickListener();
        }
        this.disposeClickListener = this.renderer.listen(document, 'click', (e) => {
            this.onClick(e);
        });
    }
    mouseenterHandler = () => {
        this.controlVisibility(this.hostEl.nativeElement, true);
    };
    mouseleaveHandler = () => {
        if (this.isPrevented(this.hostEl.nativeElement, false)) {
            return;
        }
        if (!this._hideSub) {
            this._hideSub = this.popoverService.hidePopover.subscribe((val) => {
                const [isPopoverHovered, isAnchorHovered] = val;
                if (!isPopoverHovered && !isAnchorHovered) {
                    this.hide();
                }
            });
        }
    };
    focusHandler = () => {
        this.controlVisibility(this.hostEl.nativeElement, true);
    };
    blurHandler = (args) => {
        const event = args.domEvent;
        if (this.isPrevented(this.hostEl.nativeElement, false)) {
            return;
        }
        // from anchor to popup focus check
        const isFocusInside = !!closest(event.relatedTarget, (node) => node.classList && node.classList.contains('k-popover'));
        if (!isFocusInside) {
            this.hide();
        }
        if (!this._focusInsideSub) {
            // inside popup focus check
            this._focusInsideSub = this.popoverService.isFocusInsidePopover.pipe(filter(v => v !== null)).subscribe((val) => {
                if (!val) {
                    this.hide();
                }
            });
        }
    };
    /**
     * @hidden
     */
    onClick(event) {
        const isInsidePopup = !!closest(event.target, (node) => node.classList && node.classList.contains('k-popup'));
        const isAnchor = !!closest(event.target, (node) => node === this.hostEl.nativeElement);
        if (isInsidePopup || (this.popupRef && isAnchor)) {
            return;
        }
        if (isAnchor) {
            // on opening
            this.controlVisibility(this.hostEl.nativeElement, true);
        }
        else {
            // on closing
            this.controlVisibility(this.hostEl.nativeElement, false);
        }
    }
    controlVisibility(anchor, show) {
        if (this.isPrevented(anchor, show)) {
            return;
        }
        if (show) {
            this.show();
        }
        else {
            this.hide();
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverAnchorDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i1$1.PopupService }, { token: i0.Renderer2 }, { token: PopoverService }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: PopoverAnchorDirective, isStandalone: true, selector: "[kendoPopoverAnchor]", providers: [PopoverService], exportAs: ["kendoPopoverAnchor"], usesInheritance: true, usesOnChanges: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverAnchorDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[kendoPopoverAnchor]',
                    exportAs: 'kendoPopoverAnchor',
                    providers: [PopoverService],
                    standalone: true
                }]
        }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i1$1.PopupService }, { type: i0.Renderer2 }, { type: PopoverService }]; } });

/* eslint-disable @typescript-eslint/no-explicit-any */
/**
 * Represents the [`kendoPopoverContainer`](slug:configuration_popover#toc-popover-container) directive.
 * It is used to filter and target multiple elements, which should display a popover on interaction.
 *
 * @example
 * ```ts-no-run
 * <div kendoPopoverContainer [popover]="myPopover" filter=".has-popover">
 *     <button class="has-popover">Show Popover</button>
 *     <button>Button Without Popover</button>
 *     <button class="has-popover">Show Popover</button>
 * </div>
 * ```
 */
class PopoverContainerDirective extends PopoverDirectivesBase {
    wrapperEl;
    ngZone;
    popupService;
    renderer;
    popoverService;
    /**
     * Specifies a selector for the elements that should display a popover.
     *
     * The possible values include any valid query selector.
     * [See example](slug:configuration_popover#toc-popover-container)
     */
    filter;
    constructor(wrapperEl, ngZone, popupService, renderer, popoverService) {
        super(ngZone, popupService, renderer);
        this.wrapperEl = wrapperEl;
        this.ngZone = ngZone;
        this.popupService = popupService;
        this.renderer = renderer;
        this.popoverService = popoverService;
        this._popoverService = this.popoverService;
    }
    /**
     * Shows the Popover.
     *
     * @param anchor&mdash;Specifies the element that will be used as an anchor. The Popover opens relative to that element. [See example]({% slug programmaticcontrol_popover %})
     */
    show(anchor) {
        if (this.popupRef) {
            return;
        }
        this.ngZone.run(() => {
            this.openPopup(anchor);
        });
        this.popupRef.popupAnchorViewportLeave
            .pipe(take(1))
            .subscribe(() => this.hide());
    }
    /**
     * Toggles the visibility of the Popover. [See example]({% slug programmaticcontrol_popover %})
     *
     * @param anchor&mdash;Specifies the element that will be used as an anchor. The Popover opens relative to that element.
     */
    toggle(anchor) {
        const previousAnchor = this.popupRef && this.popupRef.content.instance.anchor;
        if (this.popupRef) {
            this.hide();
            if (previousAnchor !== anchor) {
                this.show(anchor);
            }
        }
        else {
            this.show(anchor);
        }
    }
    subscribeClick() {
        if (this.disposeClickListener) {
            this.disposeClickListener();
        }
        this.disposeClickListener = this.renderer.listen(document, 'click', (e) => {
            const filterElement = closestBySelector(e.target, this.filter);
            this.clickHandler(filterElement, e);
        });
    }
    mouseenterHandler = (anchor) => {
        this.controlVisibility(anchor, true);
    };
    mouseleaveHandler = (args) => {
        const anchor = args.anchor;
        if (this.isPrevented(anchor, false)) {
            return;
        }
        if (!this._hideSub) {
            this._hideSub = this.popoverService.hidePopover.subscribe((val) => {
                const [isPopoverHovered, , isOriginAnchor, currentAnchor] = val;
                if (!isPopoverHovered && !isOriginAnchor) {
                    this.hide();
                    if (!isOriginAnchor && currentAnchor) {
                        this.show(currentAnchor);
                    }
                }
            });
        }
    };
    focusHandler = (anchor) => {
        this.controlVisibility(anchor, true);
    };
    blurHandler = (args) => {
        const anchor = args.anchor;
        const event = args.domEvent;
        if (this.isPrevented(anchor, false)) {
            return;
        }
        // from anchor to popup focus check
        const isFocusInside = !!closest(event.relatedTarget, (node) => node.classList && node.classList.contains('k-popover'));
        if (!isFocusInside) {
            this.hide();
        }
        if (!this._focusInsideSub) {
            // inside popup focus check
            this._focusInsideSub = this.popoverService.isFocusInsidePopover.pipe(filter(v => v !== null)).subscribe((val) => {
                if (!val && !isFocusInside) {
                    this.hide();
                }
            });
        }
    };
    subscribeToShowEvents(arr) {
        const filteredElements = Array.from(document.querySelectorAll(this.filter));
        filteredElements.forEach((el) => {
            this.subs.add(this.renderer.listen(el, arr[0].name, () => {
                this.popoverService.emitAnchorState(true, el);
                arr[0].handler(el);
            }));
            this.subs.add(this.renderer.listen(el, arr[1].name, (e) => {
                this.popoverService.emitAnchorState(false, null);
                arr[1].handler({ anchor: el, domEvent: e });
            }));
        });
    }
    clickHandler(anchor, event) {
        const isInsidePopup = !!closest(event.target, (node) => node.classList && node.classList.contains('k-popup'));
        const popupRefAnchor = this.popupRef && this.popupRef.content.instance.anchor;
        const isOriginAnchor = !!closest(event.target, (node) => node === (popupRefAnchor ? popupRefAnchor : anchor));
        if (this.showOn !== 'click' || isInsidePopup || (this.popupRef && isOriginAnchor)) {
            return;
        }
        if (!anchor && this.popupRef) {
            this.controlVisibility(anchor, false);
            return;
        }
        if (isOriginAnchor) {
            this.controlVisibility(anchor, true);
        }
        else if (this.popupRef) {
            this.controlVisibility(anchor, false);
            this.controlVisibility(anchor, true);
        }
    }
    controlVisibility(anchor, show) {
        if (this.isPrevented(anchor, show)) {
            return;
        }
        if (show) {
            this.show(anchor);
        }
        else {
            this.hide();
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverContainerDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i1$1.PopupService }, { token: i0.Renderer2 }, { token: PopoverService }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: PopoverContainerDirective, isStandalone: true, selector: "[kendoPopoverContainer]", inputs: { filter: "filter" }, providers: [PopoverService], exportAs: ["kendoPopoverContainer"], usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverContainerDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[kendoPopoverContainer]',
                    exportAs: 'kendoPopoverContainer',
                    providers: [PopoverService],
                    standalone: true
                }]
        }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i1$1.PopupService }, { type: i0.Renderer2 }, { type: PopoverService }]; }, propDecorators: { filter: [{
                type: Input
            }] } });

/**
 * @hidden
 */
class TooltipContentComponent {
    content;
    localizationService;
    /**
     * @hidden
     */
    xIcon = xIcon;
    /**
     * @hidden
     */
    direction;
    close = new EventEmitter();
    get cssClasses() {
        return 'k-tooltip';
    }
    hostRole = 'tooltip';
    get hostId() {
        return this.tooltipId;
    }
    get className() {
        return this.closable;
    }
    get cssPosition() {
        return 'relative';
    }
    tooltipWidth = null;
    tooltipHeight = null;
    titleTemplate;
    anchor;
    closable;
    templateRef;
    templateString;
    closeTitle;
    callout = true;
    position;
    /**
     * @hidden
     */
    tooltipId;
    dynamicRTLSubscription;
    constructor(content, localizationService) {
        this.content = content;
        this.localizationService = localizationService;
        this.direction = localizationService.rtl ? 'rtl' : 'ltr';
    }
    ngOnInit() {
        this.tooltipId = getId('tooltip');
        this.dynamicRTLSubscription = this.localizationService.changes
            .subscribe(({ rtl }) => this.direction = rtl ? 'rtl' : 'ltr');
    }
    ngOnDestroy() {
        if (this.dynamicRTLSubscription) {
            this.dynamicRTLSubscription.unsubscribe();
        }
    }
    get closeButtonTitle() {
        return this.closeTitle || this.localizationService.get('closeTitle');
    }
    calloutPositionClass() {
        return {
            'top': 'k-callout-s',
            'left': 'k-callout-e',
            'bottom': 'k-callout-n',
            'right': 'k-callout-w'
        }[this.position];
    }
    onCloseClick(event) {
        event.preventDefault();
        this.close.emit();
    }
    updateCalloutPosition(position, isFlip) {
        if (!this.callout) {
            return;
        }
        const callout = this.content.nativeElement.querySelector('.k-callout');
        const isVertical = position === 'top' || position === 'bottom';
        const size = isVertical ? 'width' : 'height';
        const dir = isVertical ? 'left' : 'top';
        const offsetProperty = isVertical ? 'marginLeft' : 'marginTop';
        const calloutSize = callout.getBoundingClientRect()[size];
        const anchorCenter = getCenterOffset(this.anchor.nativeElement, dir, size);
        const contentCenter = getCenterOffset(this.content.nativeElement, dir, size);
        const diff = Math.abs(contentCenter - anchorCenter);
        if (diff > 1 || diff === 0 || Math.round(diff) === 0) {
            const newMargin = contentCenter - anchorCenter + (calloutSize / 2);
            callout.style[offsetProperty] = `${-newMargin}px`;
        }
        const calloutStyles = this.calloutStyles(position, calloutSize, isFlip);
        Object.keys(calloutStyles).forEach((style) => {
            callout.style[style] = calloutStyles[style];
        });
    }
    calloutStyles = (position, calloutSize, isFlip) => {
        const styles = {};
        const isVertical = position === 'top' || position === 'bottom';
        const flipDeg = '180deg';
        const zeroDeg = '0deg';
        if (!isFlip) {
            styles.transform = isVertical ? `rotateX(${zeroDeg})` : `rotateY(${zeroDeg})`;
            return styles;
        }
        if (position === 'top') {
            styles.bottom = 'unset';
        }
        else if (position === 'bottom') {
            styles.top = 'unset';
        }
        else if (position === 'left') {
            styles.right = 'unset';
        }
        else if (position === 'right') {
            styles.left = 'unset';
        }
        styles[position] = `${-calloutSize}px`;
        styles.transform = isVertical ? `rotateX(${flipDeg})` : `rotateY(${flipDeg})`;
        return styles;
    };
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipContentComponent, deps: [{ token: i0.ElementRef }, { token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TooltipContentComponent, isStandalone: true, selector: "kendo-tooltip", inputs: { tooltipWidth: "tooltipWidth", tooltipHeight: "tooltipHeight", titleTemplate: "titleTemplate", anchor: "anchor", closable: "closable", templateRef: "templateRef", templateString: "templateString" }, outputs: { close: "close" }, host: { properties: { "attr.dir": "this.direction", "class": "this.cssClasses", "attr.role": "this.hostRole", "attr.id": "this.hostId", "class.k-tooltip-closable": "this.className", "style.position": "this.cssPosition", "style.width.px": "this.tooltipWidth", "style.height.px": "this.tooltipHeight" } }, providers: [
            LocalizationService,
            {
                provide: L10N_PREFIX,
                useValue: 'kendo.tooltip'
            }
        ], ngImport: i0, template: `
        <ng-container kendoTooltipLocalizedMessages
            i18n-closeTitle="kendo.tooltip.closeTitle|The title of the close button"
            closeTitle="Close"
        >
        </ng-container>

        <div class="k-tooltip-content">
            <div class="k-tooltip-title" *ngIf="titleTemplate">
                <ng-template
                    [ngIf]="titleTemplate"
                    [ngTemplateOutlet]="titleTemplate"
                    [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
                </ng-template>
            </div>

            <ng-template
                [ngIf]="templateRef"
                [ngTemplateOutlet]="templateRef"
                [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
            </ng-template>
            <ng-template
                [ngIf]="templateString">
                {{ templateString }}
            </ng-template>
        </div>

        <div *ngIf="closable" [attr.aria-hidden]="true" class="k-tooltip-button" (click)="onCloseClick($event)">
            <a href="#" [attr.title]="closeButtonTitle" class="k-icon">
                <kendo-icon-wrapper
                    name="x"
                    [svgIcon]="xIcon">
                </kendo-icon-wrapper>
            </a>
        </div>

        <div class="k-callout" *ngIf="callout" [ngClass]="calloutPositionClass()"></div>
    `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoTooltipLocalizedMessages]", inputs: ["closeTitle"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipContentComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'kendo-tooltip',
                    template: `
        <ng-container kendoTooltipLocalizedMessages
            i18n-closeTitle="kendo.tooltip.closeTitle|The title of the close button"
            closeTitle="Close"
        >
        </ng-container>

        <div class="k-tooltip-content">
            <div class="k-tooltip-title" *ngIf="titleTemplate">
                <ng-template
                    [ngIf]="titleTemplate"
                    [ngTemplateOutlet]="titleTemplate"
                    [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
                </ng-template>
            </div>

            <ng-template
                [ngIf]="templateRef"
                [ngTemplateOutlet]="templateRef"
                [ngTemplateOutletContext]="{ $implicit: anchor, anchor: anchor }">
            </ng-template>
            <ng-template
                [ngIf]="templateString">
                {{ templateString }}
            </ng-template>
        </div>

        <div *ngIf="closable" [attr.aria-hidden]="true" class="k-tooltip-button" (click)="onCloseClick($event)">
            <a href="#" [attr.title]="closeButtonTitle" class="k-icon">
                <kendo-icon-wrapper
                    name="x"
                    [svgIcon]="xIcon">
                </kendo-icon-wrapper>
            </a>
        </div>

        <div class="k-callout" *ngIf="callout" [ngClass]="calloutPositionClass()"></div>
    `,
                    providers: [
                        LocalizationService,
                        {
                            provide: L10N_PREFIX,
                            useValue: 'kendo.tooltip'
                        }
                    ],
                    standalone: true,
                    imports: [LocalizedMessagesDirective, NgIf, NgTemplateOutlet, IconWrapperComponent, NgClass]
                }]
        }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.LocalizationService }]; }, propDecorators: { direction: [{
                type: HostBinding,
                args: ['attr.dir']
            }], close: [{
                type: Output
            }], cssClasses: [{
                type: HostBinding,
                args: ['class']
            }], hostRole: [{
                type: HostBinding,
                args: ['attr.role']
            }], hostId: [{
                type: HostBinding,
                args: ['attr.id']
            }], className: [{
                type: HostBinding,
                args: ['class.k-tooltip-closable']
            }], cssPosition: [{
                type: HostBinding,
                args: ['style.position']
            }], tooltipWidth: [{
                type: HostBinding,
                args: ['style.width.px']
            }, {
                type: Input
            }], tooltipHeight: [{
                type: HostBinding,
                args: ['style.height.px']
            }, {
                type: Input
            }], titleTemplate: [{
                type: Input
            }], anchor: [{
                type: Input
            }], closable: [{
                type: Input
            }], templateRef: [{
                type: Input
            }], templateString: [{
                type: Input
            }] } });

/**
 * Obsolete. Provide the TooltipSettings class instead.
 *
 * @hidden
 */
const TOOLTIP_SETTINGS = new InjectionToken('kendo-ui-tooltip-settings');
/**
 * Provides a global configuration for the Kendo UI Tooltip. Once injected through
 * the `AppComponent` constructor, the configuration properties can be overridden.
 *
 * @example
 * ```ts-no-run
 * import { TooltipSettings } from '@progress/kendo-angular-tooltip';
 *
 * _@Component({
 *    selector: 'my-app',
 *    template: `
 *      <div kendoTooltip>
 *          <button title="Saves the current document">Save</button>
 *      </div>`,
 *    providers: [{
 *        provide: TooltipSettings,
 *        useFactory: (): TooltipSettings => ({
 *          // Override default values of tooltips if wanted
 *          position: 'right'
 *        })
 *    }]
 * })
 * export class AppComponent { }
 * ```
 */
class TooltipSettings {
    /**
     * Specifies if the Тooltip will display a callout arrow.
     *
     * The possible values are:
     * * `true` (default)
     * * `false`
     */
    callout;
    /**
     * Specifies the title of the close button.
     */
    closeTitle;
    /**
     * Specifies the position of the Tooltip that is
     * relative to the anchor element.
     *
     * The possible values are:
     * * `top` (default)
     * * `bottom`
     * * `left`
     * * `right`
     */
    position;
    /**
     * Specifies when the Тooltip will be rendered.
     *
     * The possible values are:
     * * `hover` (default)
     * * `click`
     * * `none`
     */
    showOn;
    /**
     * Specifies the delay in milliseconds before the Tooltip is shown.
     * * `100` (default) milliseconds.
     */
    showAfter;
    /**
     * @hidden
     */
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    constructor() { }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipSettings, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipSettings });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipSettings, decorators: [{
            type: Injectable
        }], ctorParameters: function () { return []; } });

/**
 * Represents the [Kendo UI Tooltip directive for Angular]({% slug overview_tooltip %}).
 * Used to display additional information that is related to an element.
 *
 * @example
 * ```ts-no-run
 * <div kendoTooltip>
 *    <a title="Tooltip title" href="foo">foo</a>
 * </div>
 * ```
 */
class TooltipDirective {
    tooltipWrapper;
    ngZone;
    renderer;
    popupService;
    /**
     * Specifies a selector for elements within a container which will display a tooltip
     * ([see example]({% slug anchorelements_tooltip %})). The possible values include any
     * DOM `selector`. The default value is `[title]`.
     */
    filter = '[title]';
    /**
     * Specifies the position of the Tooltip that is relative to the
     * anchor element ([see example]({% slug positioning_tooltip %})).
     *
     * The possible values are:
     * * `top` (default)
     * * `bottom`
     * * `left`
     * * `right`
     */
    position = 'top';
    /**
     * Renders the passed template as a header title of the Tooltip
     * ([see example]({% slug anchorelements_tooltip %})).
     */
    titleTemplate;
    /**
     * Specifies when the Тooltip will be rendered
     * ([see example]({% slug programmaticopening_tooltip %})).
     *
     * The possible values are:
     * * `hover` (default)
     * * `click`
     * * `none`
     */
    showOn;
    /**
     * Specifies the delay in milliseconds before the Tooltip is shown.
     * * `100` (default) milliseconds.
     */
    showAfter = 100;
    /**
     * Specifies if the Тooltip will display a callout arrow.
     *
     * The possible values are:
     * * `true` (default)
     * * `false`
     */
    callout = true;
    /**
     * Specifies if the Тooltip will display a **Close** button
     * ([see example]({% slug closable_tooltip %})).
     *
     * The possible values are:
     * * `true`
     * * `false`
     */
    closable = false;
    /**
     * Specifies the offset in pixels between the Tooltip and the anchor. Defaults to `6` pixels.
     * If the `callout` property is set to `true`, the offset is rendered from the callout arrow.
     * If the `callout` property is set to `false`, the offset is rendered from the content of the Tooltip.
     */
    offset = 6;
    /**
     * Specifies the width of the Тooltip ([see example]({% slug anchorelements_tooltip %})).
     */
    tooltipWidth;
    /**
     * Specifies the height of the Тooltip.
     */
    tooltipHeight;
    /**
     * Specifies a CSS class that will be added to the Tooltip.
     */
    tooltipClass;
    /**
     * @hidden
     * Specifies a CSS class that will be added to the kendo-tooltip element.
     */
    tooltipContentClass;
    /**
     * Provides screen boundary detection when the Тooltip is shown.
     */
    collision;
    /**
     * Specifies the title of the close button.
     */
    closeTitle;
    /**
     * Sets the content of the Tooltip as a template reference
     * ([see example]({% slug templates_tooltip %})).
     */
    set tooltipTemplate(value) {
        this.template = value;
    }
    get tooltipTemplate() {
        return this.template;
    }
    popupRef;
    template;
    showTimeout;
    anchor = null;
    mouseOverSubscription;
    mouseOutSubscription;
    mouseClickSubscription;
    anchorTitleSubscription;
    popupPositionChangeSubscription;
    popupMouseOutSubscription;
    keyboardNavigationSubscription = new Subscription();
    closeClickSubscription;
    validPositions = ['top', 'bottom', 'right', 'left'];
    validShowOptions = ['hover', 'click', 'none'];
    constructor(tooltipWrapper, ngZone, renderer, popupService, settings, legacySettings) {
        this.tooltipWrapper = tooltipWrapper;
        this.ngZone = ngZone;
        this.renderer = renderer;
        this.popupService = popupService;
        validatePackage(packageMetadata);
        Object.assign(this, settings, legacySettings);
        this.ngZone.runOutsideAngular(() => {
            const wrapper = this.tooltipWrapper.nativeElement;
            this.anchorTitleSubscription = fromEvent(wrapper, 'mouseover')
                .pipe(filter(() => this.filter !== ''))
                .subscribe((e) => {
                const filterElement = closestBySelector(e.target, this.filter);
                if (filterElement) {
                    this.hideElementTitle({ nativeElement: filterElement });
                }
            });
            this.mouseOverSubscription = fromEvent(wrapper, 'mouseover')
                .pipe(filter(() => this.filter !== ''))
                .subscribe(e => this.onMouseOver(e));
            this.mouseOutSubscription = fromEvent(wrapper, 'mouseout')
                .subscribe(e => this.onMouseOut(e));
        });
    }
    /**
     * Shows the Tooltip.
     * @param anchor&mdash; ElementRef|Element.
     * Specifies the element that will be used as an anchor. The Tooltip opens relative to that element.
     */
    show(anchor) {
        if (this.popupRef) {
            return;
        }
        if (anchor instanceof Element) {
            anchor = { nativeElement: anchor };
        }
        this.anchor = anchor;
        if (this.showOn === 'hover') {
            if (this.popupRef) {
                return;
            }
            clearTimeout(this.showTimeout);
            this.showTimeout = setTimeout(() => this.showContent(this.anchor), this.showAfter);
        }
        else {
            this.hideElementTitle(this.anchor);
            this.showContent(this.anchor);
        }
    }
    /**
     * Hides the Tooltip.
     */
    hide() {
        clearTimeout(this.showTimeout);
        const anchor = this.anchor && this.anchor.nativeElement;
        if (anchor && anchor.getAttribute('data-title')) {
            if (!anchor.getAttribute('title') && anchor.hasAttribute('title')) {
                anchor.setAttribute('title', anchor.getAttribute('data-title'));
            }
            anchor.setAttribute('data-title', '');
        }
        if (this.popupMouseOutSubscription) {
            this.popupMouseOutSubscription.unsubscribe();
        }
        if (this.closeClickSubscription) {
            this.closeClickSubscription.unsubscribe();
        }
        this.closePopup();
    }
    /**
     * Toggle visibility of the Tooltip.
     *
     * @param anchor&mdash; ElementRef|Element. Specifies the element that will be used as an anchor.
     * @param show&mdash; Optional. Boolean. Specifies if the Tooltip will be rendered.
     */
    toggle(anchor, show) {
        const previousAnchor = this.anchor && this.anchor.nativeElement;
        if (anchor instanceof Element) {
            anchor = { nativeElement: anchor };
        }
        if (previousAnchor !== anchor.nativeElement) {
            this.hide();
        }
        if (previousAnchor === anchor.nativeElement && this.showOn === 'click') {
            this.hide();
        }
        if (typeof show === 'undefined') {
            show = !this.popupRef;
        }
        if (show) {
            this.show(anchor);
        }
        else {
            this.hide();
        }
    }
    ngOnInit() {
        if (this.showOn === undefined) {
            this.showOn = 'hover';
        }
        this.keyboardNavigationSubscription.add(this.renderer.listen(this.tooltipWrapper.nativeElement, 'keydown', event => this.onKeyDown(event)));
        this.verifyProperties();
    }
    ngOnChanges(changes) {
        if (changes.showOn && isDocumentAvailable()) {
            this.subscribeClick();
        }
    }
    ngAfterViewChecked() {
        if (!this.popupRef) {
            return;
        }
        if (this.anchor &&
            !hasParent(this.anchor.nativeElement || this.anchor, this.tooltipWrapper.nativeElement)) {
            this.anchor = null;
            this.hide();
        }
    }
    ngOnDestroy() {
        this.hide();
        this.template = null;
        this.anchorTitleSubscription.unsubscribe();
        this.mouseOverSubscription.unsubscribe();
        this.mouseOutSubscription.unsubscribe();
        this.keyboardNavigationSubscription.unsubscribe();
        if (this.mouseClickSubscription) {
            this.mouseClickSubscription.unsubscribe();
        }
        if (this.popupPositionChangeSubscription) {
            this.popupPositionChangeSubscription.unsubscribe();
        }
        if (this.popupMouseOutSubscription) {
            this.popupMouseOutSubscription.unsubscribe();
        }
    }
    showContent(anchorRef) {
        if (!anchorRef.nativeElement.getAttribute('data-title') && !this.template) {
            return;
        }
        this.ngZone.run(() => {
            this.openPopup(anchorRef);
            this.bindContent(this.popupRef.content, anchorRef);
        });
        this.popupRef.popupAnchorViewportLeave
            .pipe(take(1))
            .subscribe(() => this.hide());
    }
    bindContent(contentComponent, anchorRef) {
        const content = contentComponent.instance;
        this.closeClickSubscription = content.close
            .subscribe(() => {
            this.hide();
        });
        if (!this.template) {
            content.templateString = this.anchor.nativeElement.getAttribute('data-title');
        }
        else {
            content.templateRef = this.template;
        }
        if (this.titleTemplate) {
            content.titleTemplate = this.titleTemplate;
        }
        content.closeTitle = this.closeTitle;
        content.anchor = anchorRef;
        content.callout = this.callout;
        content.closable = this.closable;
        content.position = this.position;
        content.tooltipWidth = this.tooltipWidth;
        content.tooltipHeight = this.tooltipHeight;
        this.popupRef.content.changeDetectorRef.detectChanges();
    }
    hideElementTitle(elementRef) {
        const element = elementRef.nativeElement;
        if (element.getAttribute('title')) {
            element.setAttribute('data-title', element.getAttribute('title'));
            element.setAttribute('title', '');
        }
    }
    openPopup(anchorRef) {
        const alignSettings = align(this.position, this.offset);
        const anchorAlign = alignSettings.anchorAlign;
        const popupAlign = alignSettings.popupAlign;
        const popupMargin = alignSettings.popupMargin;
        this.popupRef = this.popupService.open({
            anchor: anchorRef,
            anchorAlign,
            animate: false,
            content: TooltipContentComponent,
            collision: collision(this.collision, this.position),
            margin: popupMargin,
            popupAlign,
            popupClass: 'k-popup-transparent'
        });
        if (this.tooltipClass) {
            this.renderer.addClass(this.popupRef.popupElement, this.tooltipClass);
        }
        if (this.tooltipContentClass) {
            this.renderer.addClass(this.popupRef.content.instance['content'].nativeElement, this.tooltipContentClass);
        }
        const popupInstance = this.popupRef.content.instance;
        if (anchorRef) {
            this.renderer.setAttribute(anchorRef.nativeElement, 'aria-labelledby', popupInstance.tooltipId);
        }
        if (popupInstance.callout) {
            this.popupPositionChangeSubscription = this.popupRef.popupPositionChange
                .subscribe(({ flip }) => {
                const isFlip = flip.horizontal === true || flip.vertical === true;
                popupInstance.updateCalloutPosition(this.position, isFlip);
            });
        }
        if (this.showOn === 'hover') {
            this.ngZone.runOutsideAngular(() => {
                const popup = this.popupRef.popupElement;
                this.popupMouseOutSubscription = fromEvent(popup, 'mouseout')
                    .subscribe((e) => this.onMouseOut(e));
            });
        }
    }
    closePopup() {
        if (this.popupRef) {
            if (this.anchor) {
                this.renderer.removeAttribute(this.anchor.nativeElement, 'aria-labelledby');
            }
            this.popupRef.close();
            this.popupRef = null;
        }
        if (this.popupPositionChangeSubscription) {
            this.popupPositionChangeSubscription.unsubscribe();
        }
    }
    subscribeClick() {
        if (this.mouseClickSubscription) {
            this.mouseClickSubscription.unsubscribe();
        }
        if (this.showOn === 'click') {
            this.mouseClickSubscription = fromEvent(document, 'click')
                .pipe(filter(() => this.filter !== ''))
                .subscribe(e => this.onMouseClick(e, this.tooltipWrapper.nativeElement));
        }
    }
    onMouseClick(e, wrapper) {
        const target = e.target;
        const filterElement = closestBySelector(target, this.filter);
        const popup = this.popupRef && this.popupRef.popupElement;
        if (popup) {
            if (popup.contains(target)) {
                return;
            }
            if (this.closable) {
                return;
            }
        }
        if (wrapper.contains(target) && filterElement) {
            this.toggle(filterElement, true);
        }
        else if (popup) {
            this.hide();
        }
    }
    onKeyDown(event) {
        const keyCode = event.keyCode;
        const target = event.target;
        if (this.popupRef) {
            const tooltipId = this.popupRef.content.location.nativeElement.getAttribute('id');
            const anchorLabelledBy = target.getAttribute('aria-labelledby');
            if (keyCode === Keys.Escape && this.canCloseTooltip(target, tooltipId, anchorLabelledBy)) {
                this.closePopup();
            }
        }
    }
    canCloseTooltip(target, tooltipId, anchorLabelledBy) {
        const isIdEqualsLabel = tooltipId === anchorLabelledBy;
        const filterElement = closestBySelector(target, this.filter);
        const isTargetFocused = target === document.activeElement;
        const isTargetInsideWrapper = this.tooltipWrapper.nativeElement.contains(target);
        return isTargetInsideWrapper && filterElement && isTargetFocused && isIdEqualsLabel;
    }
    onMouseOver(e) {
        const filterElement = closestBySelector(e.target, this.filter);
        if (this.showOn !== 'hover') {
            return;
        }
        if (filterElement) {
            this.toggle(filterElement, true);
        }
    }
    onMouseOut(e) {
        if (this.showOn !== 'hover') {
            return;
        }
        if (this.closable) {
            return;
        }
        const popup = this.popupRef && this.popupRef.popupElement;
        const relatedTarget = e.relatedTarget;
        if (relatedTarget && this.anchor && contains(this.anchor.nativeElement, relatedTarget)) {
            return;
        }
        if (relatedTarget && contains(popup, relatedTarget)) {
            return;
        }
        this.hide();
    }
    verifyProperties() {
        if (!isDevMode()) {
            return;
        }
        if (!containsItem(this.validPositions, this.position)) {
            throw new Error(`Invalid value provided for position property.The available options are 'top', 'bottom', 'left', or 'right'.`);
        }
        if (!containsItem(this.validShowOptions, this.showOn)) {
            throw new Error(`Invalid value provided for showOn property.The available options are 'hover' or 'none'.`);
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: i1$1.PopupService }, { token: TooltipSettings, optional: true }, { token: TOOLTIP_SETTINGS, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TooltipDirective, isStandalone: true, selector: "[kendoTooltip]", inputs: { filter: "filter", position: "position", titleTemplate: "titleTemplate", showOn: "showOn", showAfter: "showAfter", callout: "callout", closable: "closable", offset: "offset", tooltipWidth: "tooltipWidth", tooltipHeight: "tooltipHeight", tooltipClass: "tooltipClass", tooltipContentClass: "tooltipContentClass", collision: "collision", closeTitle: "closeTitle", tooltipTemplate: "tooltipTemplate" }, exportAs: ["kendoTooltip"], usesOnChanges: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[kendoTooltip]',
                    exportAs: 'kendoTooltip',
                    standalone: true
                }]
        }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: i1$1.PopupService }, { type: TooltipSettings, decorators: [{
                    type: Optional
                }] }, { type: TooltipSettings, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [TOOLTIP_SETTINGS]
                }] }]; }, propDecorators: { filter: [{
                type: Input
            }], position: [{
                type: Input
            }], titleTemplate: [{
                type: Input
            }], showOn: [{
                type: Input
            }], showAfter: [{
                type: Input
            }], callout: [{
                type: Input
            }], closable: [{
                type: Input
            }], offset: [{
                type: Input
            }], tooltipWidth: [{
                type: Input
            }], tooltipHeight: [{
                type: Input
            }], tooltipClass: [{
                type: Input
            }], tooltipContentClass: [{
                type: Input
            }], collision: [{
                type: Input
            }], closeTitle: [{
                type: Input
            }], tooltipTemplate: [{
                type: Input
            }] } });

/**
 * Utility array that contains all `Tooltip` related components and directives
 */
const KENDO_TOOLTIP = [
    TooltipDirective,
    TooltipContentComponent,
    LocalizedMessagesDirective
];
/**
 * Utility array that contains all `Popover` related components and directives
 */
const KENDO_POPOVER = [
    PopoverComponent,
    PopoverActionsTemplateDirective,
    PopoverBodyTemplateDirective,
    PopoverTitleTemplateDirective,
    PopoverAnchorDirective,
    PopoverContainerDirective
];
/**
 * Utility array that contains all `@progress/kendo-angular-tooltip` related components and directives
 */
const KENDO_TOOLTIPS = [
    ...KENDO_TOOLTIP,
    ...KENDO_POPOVER
];

// IMPORTANT: NgModule export kept for backwards compatibility
/**
 * Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
 * definition for the Tooltip component.
 *
 * The package exports:
 * - `KendoTooltipDirective`&mdash;The Tooltip directive class.
 *
 * @example
 *
 * ```ts-no-run
 * // Import the Tooltip module
 * import { TooltipModule } from '@progress/kendo-angular-tooltip';
 *
 * // The browser platform with a compiler
 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 *
 * import { NgModule } from '@angular/core';
 *
 * // Import the app component
 * _@NgModule{{
 *    declarations: [AppComponent], // declare app component
 *    imports:      [BrowserModule, TooltipModule], // import TooltipModule module
 *    bootstrap:    [AppComponent]
 * }}
 * export class AppModule {}
 *
 * // Compile and launch the module
 * platformBrowserDynamic().bootstrapModule(AppModule);
 * ```
 */
class TooltipModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: TooltipModule, imports: [TooltipDirective, TooltipContentComponent, LocalizedMessagesDirective], exports: [TooltipDirective, TooltipContentComponent, LocalizedMessagesDirective] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipModule, providers: [PopupService, ResizeBatchService, IconsService], imports: [TooltipContentComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [...KENDO_TOOLTIP],
                    exports: [...KENDO_TOOLTIP],
                    providers: [PopupService, ResizeBatchService, IconsService]
                }]
        }] });

// IMPORTANT: NgModule export kept for backwards compatibility
/**
 * Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
 * definition for the Popover component.
 *
 * @example
 *
 * ```ts-no-run
 * import { PopoverModule } from '@progress/kendo-angular-tooltip';
 *
 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 * import { NgModule } from '@angular/core';
 *
 * import { AppComponent } from './app.component';
 *
 * _@NgModule({
 *     declarations: [AppComponent],
 *     imports:      [BrowserModule, PopoverModule],
 *     bootstrap:    [AppComponent]
 * })
 * export class AppModule {}
 *
 * platformBrowserDynamic().bootstrapModule(AppModule);
 *
 * ```
 */
class PopoverModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: PopoverModule, imports: [PopoverComponent, PopoverActionsTemplateDirective, PopoverBodyTemplateDirective, PopoverTitleTemplateDirective, PopoverAnchorDirective, PopoverContainerDirective], exports: [PopoverComponent, PopoverActionsTemplateDirective, PopoverBodyTemplateDirective, PopoverTitleTemplateDirective, PopoverAnchorDirective, PopoverContainerDirective] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverModule, providers: [PopupService, ResizeBatchService] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PopoverModule, decorators: [{
            type: NgModule,
            args: [{
                    exports: [...KENDO_POPOVER],
                    imports: [...KENDO_POPOVER],
                    providers: [PopupService, ResizeBatchService]
                }]
        }] });

// IMPORTANT: NgModule export kept for backwards compatibility
/**
 * Represents the [NgModule](link:site.data.urls.angular['ngmoduleapi'])
 * definition for the Tooltips components.
 *
 * @example
 *
 * ```ts-no-run
 * import { TooltipsModule } from '@progress/kendo-angular-tooltip';
 *
 * // The browser platform with a compiler
 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 *
 * import { NgModule } from '@angular/core';
 *
 * // Import the app component
 * _@NgModule{{
 *    declarations: [AppComponent], // declare app component
 *    imports:      [BrowserModule, TooltipsModule], // import TooltipsModule module
 *    bootstrap:    [AppComponent]
 * }}
 * export class AppModule {}
 *
 * // Compile and launch the module
 * platformBrowserDynamic().bootstrapModule(AppModule);
 * ```
 */
class TooltipsModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: TooltipsModule, imports: [TooltipDirective, TooltipContentComponent, LocalizedMessagesDirective, PopoverComponent, PopoverActionsTemplateDirective, PopoverBodyTemplateDirective, PopoverTitleTemplateDirective, PopoverAnchorDirective, PopoverContainerDirective], exports: [TooltipDirective, TooltipContentComponent, LocalizedMessagesDirective, PopoverComponent, PopoverActionsTemplateDirective, PopoverBodyTemplateDirective, PopoverTitleTemplateDirective, PopoverAnchorDirective, PopoverContainerDirective] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipsModule, providers: [PopupService, ResizeBatchService, IconsService], imports: [TooltipContentComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TooltipsModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [...KENDO_TOOLTIPS],
                    exports: [...KENDO_TOOLTIPS],
                    providers: [PopupService, ResizeBatchService, IconsService]
                }]
        }] });

// Standalone Directives Arrays

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

export { KENDO_POPOVER, KENDO_TOOLTIP, KENDO_TOOLTIPS, LocalizedMessagesDirective, PopoverActionsTemplateDirective, PopoverAnchorDirective, PopoverBodyTemplateDirective, PopoverComponent, PopoverContainerDirective, PopoverHiddenEvent, PopoverHideEvent, PopoverModule, PopoverShowEvent, PopoverShownEvent, PopoverTitleTemplateDirective, TOOLTIP_SETTINGS, TooltipContentComponent, TooltipDirective, TooltipModule, TooltipSettings, TooltipsModule };