|
import {Component, ElementRef, HostListener, Input, NgZone, OnInit, ViewChild} from '@angular/core'; |
|
import {MatTooltip, MatTooltipModule} from '@angular/material/tooltip'; |
|
import {UntilDestroy, untilDestroyed} from '@ngneat/until-destroy'; |
|
import {fromEvent, switchMap} from 'rxjs'; |
|
|
|
@Component({ |
|
// This is required to make this a standalone component |
|
standalone: true, |
|
selector: 'click-to-copy', |
|
// Importing Angular Material Tooltip as a dependency |
|
imports: [MatTooltipModule], |
|
templateUrl: './click-to-copy.component.html', |
|
styleUrls: ['./click-to-copy.component.scss'], |
|
}) |
|
@UntilDestroy() |
|
export class ClickToCopyComponent implements OnInit { |
|
|
|
@Input() text: string; |
|
@ViewChild(MatTooltip) tooltip: MatTooltip; |
|
|
|
tooltipMessage = 'Click to copy'; |
|
tooltipDisabled = true; |
|
|
|
constructor( |
|
private readonly zone: NgZone, |
|
private readonly host: ElementRef<HTMLElement>, |
|
) { |
|
} |
|
|
|
@HostListener('mouseout') |
|
onMouseOut(): void { |
|
// Manually hide the trigger when mouse is out of the component |
|
this.tooltip.hide(); |
|
this.tooltipDisabled = true; |
|
|
|
// Give tooltip some time to hide |
|
setTimeout(() => { |
|
this.tooltipMessage = 'Click to copy'; |
|
}, 100); |
|
} |
|
|
|
@HostListener('mouseover') |
|
onMouseOver(): void { |
|
this.tooltipDisabled = false; |
|
// Manually show the trigger when mouse is over the component |
|
this.tooltip.show(); |
|
} |
|
|
|
ngOnInit(): void { |
|
this.zone.runOutsideAngular(() => { |
|
fromEvent(this.host.nativeElement, 'click').pipe( |
|
switchMap(() => navigator.clipboard.writeText(this.getTextToCopy())), |
|
untilDestroyed(this), |
|
).subscribe(() => { |
|
this.copied(); |
|
}); |
|
}); |
|
} |
|
|
|
private copied(): void { |
|
this.zone.run(() => { |
|
// Change the text as the text is copied in the clipboard |
|
this.tooltipMessage = 'Copied!'; |
|
this.tooltip.show(); |
|
}); |
|
} |
|
|
|
private getTextToCopy(): string { |
|
return this.text || this.host.nativeElement.textContent; |
|
} |
|
|
|
} |