import { ChangeDetectionStrategy, Component, ElementRef, Input, signal, TemplateRef } from '@angular/core'; @Component({ selector: 'kit-tooltip-content', templateUrl: './tooltip-content.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) export class TooltipContentComponent { @Input() title?: string; @Input() description?: string; @Input() templateRef?: TemplateRef; @Input() positionType = 'top'; @Input() offset = 8; private visibleState = signal(false); private positionCoords = signal({ top: 0, left: 0 }); // Expose signal readers for the template visible = this.visibleState.asReadonly(); positionState = this.positionCoords.asReadonly(); show(x: number, y: number, position?: string): void { if (position) { this.positionType = position; } this.calculatePosition(x, y); this.visibleState.set(true); } hide(): void { this.visibleState.set(false); } private calculatePosition(x: number, y: number): void { let top = 0; let left = 0; // Get tooltip dimensions const tooltipElement = this.elementRef.nativeElement.querySelector('.tooltip-container'); const tooltipHeight = tooltipElement.offsetHeight; const tooltipWidth = tooltipElement.offsetWidth; switch (this.positionType) { case 'top': top = y - tooltipHeight - this.offset; left = x - (tooltipWidth / 2); break; case 'bottom': top = y + this.offset; left = x - (tooltipWidth / 2); break; case 'left': top = y - (tooltipHeight / 2); left = x - tooltipWidth - this.offset; break; case 'right': top = y - (tooltipHeight / 2); left = x + this.offset; break; } // Ensure tooltip doesn't go outside viewport const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; if (left < 0) left = 0; if (left + tooltipWidth > viewportWidth) left = viewportWidth - tooltipWidth; if (top < 0) top = 0; if (top + tooltipHeight > viewportHeight) top = viewportHeight - tooltipHeight; this.positionCoords.set({ top, left }); } constructor(private elementRef: ElementRef) {} }