UNPKG

@duyvu-fsdev/ng-tooltip-directive

Version:
287 lines (280 loc) 18.7 kB
import * as i1 from '@angular/common'; import { DOCUMENT, CommonModule } from '@angular/common'; import * as i0 from '@angular/core'; import { Component, Input, Directive, Inject, HostListener, NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; class TooltipComponent { position = "bottom"; top; left; visible = false; text = ""; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.12", type: TooltipComponent, selector: "ng-tooltip", inputs: { position: "position", top: "top", left: "left", visible: "visible", text: "text" }, ngImport: i0, template: "<div\n class=\"app-tooltip tooltip-container {{ position }}\"\n [ngStyle]=\"{\n top: top,\n left: left,\n visibility: visible ? 'visible' : 'hidden'\n }\"\n>\n <div class=\"tooltip-arrow\"></div>\n <div class=\"tooltip-content\">{{ text }}</div>\n</div>\n", styles: [".app-tooltip{--background-color: var(--tooltip-background, #26292c);--color: var(--tooltip-color, #f4f5f8);--max-width: var(--tooltip-max-width, fit-content);--height: var(--tooltip-height, fit-content);--border-radius: var(--tooltip-border-radius, 4px);--padding: var(--tooltip-padding, 6px 8px)}.app-tooltip *{box-sizing:border-box}.tooltip-container{position:fixed;background-color:var(--background-color);color:var(--color);padding:var(--padding);border-radius:var(--border-radius);z-index:1000;max-width:var(--max-width);height:var(--height)}.tooltip-container .tooltip-content{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.tooltip-container .tooltip-arrow{position:absolute;width:0;height:0}.tooltip-container.top{transform:translate(-50%,-100%)}.tooltip-container.top .tooltip-arrow{bottom:-5px;left:50%;transform:translate(-50%);border-width:5px 5px 0;border-style:solid;border-color:var(--background-color) transparent transparent transparent}.tooltip-container.bottom{transform:translate(-50%)}.tooltip-container.bottom .tooltip-arrow{top:-5px;left:50%;transform:translate(-50%);border-width:0 5px 5px;border-style:solid;border-color:transparent transparent var(--background-color) transparent}.tooltip-container.left{transform:translate(-100%,-50%)}.tooltip-container.left .tooltip-arrow{top:50%;right:-5px;transform:translateY(-50%);border-width:5px 0 5px 5px;border-style:solid;border-color:transparent transparent transparent var(--background-color)}.tooltip-container.right{transform:translateY(-50%)}.tooltip-container.right .tooltip-arrow{top:50%;left:-5px;transform:translateY(-50%);border-width:5px 5px 5px 0;border-style:solid;border-color:transparent var(--background-color) transparent transparent}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TooltipComponent, decorators: [{ type: Component, args: [{ selector: "ng-tooltip", template: "<div\n class=\"app-tooltip tooltip-container {{ position }}\"\n [ngStyle]=\"{\n top: top,\n left: left,\n visibility: visible ? 'visible' : 'hidden'\n }\"\n>\n <div class=\"tooltip-arrow\"></div>\n <div class=\"tooltip-content\">{{ text }}</div>\n</div>\n", styles: [".app-tooltip{--background-color: var(--tooltip-background, #26292c);--color: var(--tooltip-color, #f4f5f8);--max-width: var(--tooltip-max-width, fit-content);--height: var(--tooltip-height, fit-content);--border-radius: var(--tooltip-border-radius, 4px);--padding: var(--tooltip-padding, 6px 8px)}.app-tooltip *{box-sizing:border-box}.tooltip-container{position:fixed;background-color:var(--background-color);color:var(--color);padding:var(--padding);border-radius:var(--border-radius);z-index:1000;max-width:var(--max-width);height:var(--height)}.tooltip-container .tooltip-content{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.tooltip-container .tooltip-arrow{position:absolute;width:0;height:0}.tooltip-container.top{transform:translate(-50%,-100%)}.tooltip-container.top .tooltip-arrow{bottom:-5px;left:50%;transform:translate(-50%);border-width:5px 5px 0;border-style:solid;border-color:var(--background-color) transparent transparent transparent}.tooltip-container.bottom{transform:translate(-50%)}.tooltip-container.bottom .tooltip-arrow{top:-5px;left:50%;transform:translate(-50%);border-width:0 5px 5px;border-style:solid;border-color:transparent transparent var(--background-color) transparent}.tooltip-container.left{transform:translate(-100%,-50%)}.tooltip-container.left .tooltip-arrow{top:50%;right:-5px;transform:translateY(-50%);border-width:5px 0 5px 5px;border-style:solid;border-color:transparent transparent transparent var(--background-color)}.tooltip-container.right{transform:translateY(-50%)}.tooltip-container.right .tooltip-arrow{top:50%;left:-5px;transform:translateY(-50%);border-width:5px 5px 5px 0;border-style:solid;border-color:transparent var(--background-color) transparent transparent}\n"] }] }], propDecorators: { position: [{ type: Input }], top: [{ type: Input }], left: [{ type: Input }], visible: [{ type: Input }], text: [{ type: Input }] } }); class TooltipDirective { el; viewContainerRef; document; option; tooltipComponentRef; constructor(el, viewContainerRef, document) { this.el = el; this.viewContainerRef = viewContainerRef; this.document = document; } ngAfterViewInit() { this.option.position = this.option.position ?? "bottom"; this.option.class = this.option.class ?? ""; } onMouseEnter() { this.showTooltip(); } onMouseLeave() { this.hideTooltip(); } getHostPosition(hostEl) { if (!hostEl) return { h: 0, w: 0, l: 0, t: 0 }; const styles = getComputedStyle(hostEl); const { left, top, height, width } = hostEl.getBoundingClientRect(); const l = styles.left === "auto" ? left : left + parseFloat(styles.marginLeft); const t = styles.top === "auto" ? top : top + parseFloat(styles.marginTop); const w = styles.width === "auto" ? width : parseFloat(styles.width); const h = styles.height === "auto" ? height : parseFloat(styles.height); return { w, h, l, t }; } getStandardPosition(p) { const { h, w, l, t } = this.getHostPosition(this.el.nativeElement); if (p === "top") return { left: l + w / 2, top: t - 6 }; if (p === "left") return { left: l - 6, top: t + h / 2 }; if (p === "right") return { left: l + w + 6, top: t + h / 2 }; else return { left: l + w / 2, top: t + h + 6 }; } showTooltip() { const factory = this.viewContainerRef.createComponent(TooltipComponent); this.tooltipComponentRef = factory; const tooltipInstance = this.tooltipComponentRef.instance; const tooltipEl = this.tooltipComponentRef.location.nativeElement; this.document.body.appendChild(tooltipEl); const { left, top } = this.getStandardPosition(this.option.position ?? "bottom"); tooltipInstance.position = this.option.position ?? "bottom"; tooltipInstance.text = this.option.text; tooltipInstance.left = `${left}px`; tooltipInstance.top = `${top}px`; tooltipInstance.visible = false; setTimeout(() => { const tooltipEl = this.tooltipComponentRef.location.nativeElement.querySelector(".tooltip-container"); if (this.option.class) tooltipEl.classList.add(this.option.class); this.adjustPosition(tooltipEl).then((position) => { const { left, top } = this.getStandardPosition(position); tooltipInstance.position = position; tooltipInstance.left = `${left}px`; tooltipInstance.top = `${top}px`; tooltipInstance.visible = true; }); }, 1); } adjustPosition(initTooltipEl) { return new Promise((resolve) => { const { left, right, top, bottom } = initTooltipEl.getBoundingClientRect(); const windowWidth = document.documentElement.clientWidth; const windowHeight = document.documentElement.clientHeight; const isOverLeft = left < 0; const isOverRight = right > windowWidth; const isOverTop = top < 0; const isOverBottom = bottom > windowHeight; if (!isOverLeft && !isOverRight && !isOverBottom && !isOverTop) resolve(this.option.position ?? "bottom"); else if (isOverLeft && isOverRight && isOverBottom && isOverTop) resolve("bottom"); else if (this.option.position === "top") { if (isOverLeft && !isOverRight && !isOverBottom && !isOverTop) resolve("right"); if (!isOverLeft && isOverRight && !isOverBottom && !isOverTop) resolve("left"); if (!isOverLeft && !isOverRight && isOverBottom && !isOverTop) resolve("top"); if (!isOverLeft && !isOverRight && !isOverBottom && isOverTop) resolve("bottom"); if (isOverLeft && isOverRight && !isOverBottom && !isOverTop) resolve("top"); if (isOverLeft && !isOverRight && isOverBottom && !isOverTop) resolve("right"); if (isOverLeft && !isOverRight && !isOverBottom && isOverTop) resolve("right"); if (!isOverLeft && isOverRight && isOverBottom && !isOverTop) resolve("left"); if (!isOverLeft && isOverRight && !isOverBottom && isOverTop) resolve("left"); if (!isOverLeft && !isOverRight && isOverBottom && isOverTop) resolve("left"); if (isOverLeft && isOverRight && isOverBottom && !isOverTop) resolve("top"); if (isOverLeft && isOverRight && !isOverBottom && isOverTop) resolve("bottom"); if (isOverLeft && !isOverRight && isOverBottom && isOverTop) resolve("right"); if (!isOverLeft && isOverRight && isOverBottom && isOverTop) resolve("left"); } else if (this.option.position === "left") { if (isOverLeft && !isOverRight && !isOverBottom && !isOverTop) resolve("right"); if (!isOverLeft && isOverRight && !isOverBottom && !isOverTop) resolve("left"); if (!isOverLeft && !isOverRight && isOverBottom && !isOverTop) resolve("left"); if (!isOverLeft && !isOverRight && !isOverBottom && isOverTop) resolve("left"); if (isOverLeft && isOverRight && !isOverBottom && !isOverTop) resolve("bottom"); if (isOverLeft && !isOverRight && isOverBottom && !isOverTop) resolve("right"); if (isOverLeft && !isOverRight && !isOverBottom && isOverTop) resolve("right"); if (!isOverLeft && isOverRight && isOverBottom && !isOverTop) resolve("left"); if (!isOverLeft && isOverRight && !isOverBottom && isOverTop) resolve("left"); if (!isOverLeft && !isOverRight && isOverBottom && isOverTop) resolve("left"); if (isOverLeft && isOverRight && isOverBottom && !isOverTop) resolve("top"); if (isOverLeft && isOverRight && !isOverBottom && isOverTop) resolve("bottom"); if (isOverLeft && !isOverRight && isOverBottom && isOverTop) resolve("right"); if (!isOverLeft && isOverRight && isOverBottom && isOverTop) resolve("left"); } else if (this.option.position === "right") { if (isOverLeft && !isOverRight && !isOverBottom && !isOverTop) resolve("right"); if (!isOverLeft && isOverRight && !isOverBottom && !isOverTop) resolve("left"); if (!isOverLeft && !isOverRight && isOverBottom && !isOverTop) resolve("right"); if (!isOverLeft && !isOverRight && !isOverBottom && isOverTop) resolve("right"); if (isOverLeft && isOverRight && !isOverBottom && !isOverTop) resolve("bottom"); if (isOverLeft && !isOverRight && isOverBottom && !isOverTop) resolve("right"); if (isOverLeft && !isOverRight && !isOverBottom && isOverTop) resolve("right"); if (!isOverLeft && isOverRight && isOverBottom && !isOverTop) resolve("left"); if (!isOverLeft && isOverRight && !isOverBottom && isOverTop) resolve("left"); if (!isOverLeft && !isOverRight && isOverBottom && isOverTop) resolve("right"); if (isOverLeft && isOverRight && isOverBottom && !isOverTop) resolve("top"); if (isOverLeft && isOverRight && !isOverBottom && isOverTop) resolve("bottom"); if (isOverLeft && !isOverRight && isOverBottom && isOverTop) resolve("right"); if (!isOverLeft && isOverRight && isOverBottom && isOverTop) resolve("left"); } else if (this.option.position === "bottom") { if (isOverLeft && !isOverRight && !isOverBottom && !isOverTop) resolve("right"); if (!isOverLeft && isOverRight && !isOverBottom && !isOverTop) resolve("left"); if (!isOverLeft && !isOverRight && isOverBottom && !isOverTop) resolve("top"); if (!isOverLeft && !isOverRight && !isOverBottom && isOverTop) resolve("bottom"); if (isOverLeft && isOverRight && !isOverBottom && !isOverTop) resolve("bottom"); if (isOverLeft && !isOverRight && isOverBottom && !isOverTop) resolve("right"); if (isOverLeft && !isOverRight && !isOverBottom && isOverTop) resolve("right"); if (!isOverLeft && isOverRight && isOverBottom && !isOverTop) resolve("right"); if (!isOverLeft && isOverRight && !isOverBottom && isOverTop) resolve("left"); if (!isOverLeft && !isOverRight && isOverBottom && isOverTop) resolve("right"); if (isOverLeft && isOverRight && isOverBottom && !isOverTop) resolve("top"); if (isOverLeft && isOverRight && !isOverBottom && isOverTop) resolve("bottom"); if (isOverLeft && !isOverRight && isOverBottom && isOverTop) resolve("right"); if (!isOverLeft && isOverRight && isOverBottom && isOverTop) resolve("left"); } }); } hideTooltip() { if (this.tooltipComponentRef) { const tooltipInstance = this.tooltipComponentRef.instance; tooltipInstance.visible = false; this.tooltipComponentRef.destroy(); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TooltipDirective, deps: [{ token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.12", type: TooltipDirective, selector: "[tooltip]", inputs: { option: ["tooltipOption", "option"] }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TooltipDirective, decorators: [{ type: Directive, args: [{ selector: "[tooltip]", }] }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: Document, decorators: [{ type: Inject, args: [DOCUMENT] }] }], propDecorators: { option: [{ type: Input, args: ["tooltipOption"] }], onMouseEnter: [{ type: HostListener, args: ["mouseenter"] }], onMouseLeave: [{ type: HostListener, args: ["mouseleave"] }] } }); class TooltipModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TooltipModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.12", ngImport: i0, type: TooltipModule, declarations: [TooltipComponent, TooltipDirective], imports: [CommonModule, FormsModule, ReactiveFormsModule], exports: [TooltipDirective] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TooltipModule, imports: [CommonModule, FormsModule, ReactiveFormsModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TooltipModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule, FormsModule, ReactiveFormsModule], declarations: [TooltipComponent, TooltipDirective], exports: [TooltipDirective], }] }] }); /* * Public API Surface of ng-tooltip-directive */ /** * Generated bundle index. Do not edit. */ export { TooltipComponent, TooltipDirective, TooltipModule }; //# sourceMappingURL=duyvu-fsdev-ng-tooltip-directive.mjs.map