@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.
173 lines (172 loc) • 6.8 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Directive, ElementRef, NgZone, Renderer2 } from "@angular/core";
import { closest } from "@progress/kendo-angular-common";
import { PopupService } from "@progress/kendo-angular-popup";
import { filter, take } from "rxjs/operators";
import { PopoverDirectivesBase } from "./directives-base";
import { PopoverService } from "./popover.service";
import { Subscription } from "rxjs";
import * as i0 from "@angular/core";
import * as i1 from "@progress/kendo-angular-popup";
import * as i2 from "./popover.service";
/**
* 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>
* ```
*/
export 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.PopupService }, { token: i0.Renderer2 }, { token: i2.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.PopupService }, { type: i0.Renderer2 }, { type: i2.PopoverService }]; } });