First version AI Search
This commit is contained in:
129
bizmatch/src/app/components/dropdown/dropdown.component.ts
Normal file
129
bizmatch/src/app/components/dropdown/dropdown.component.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { AfterViewInit, Component, ElementRef, HostBinding, Input, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { createPopper, Instance as PopperInstance } from '@popperjs/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dropdown',
|
||||
template: `
|
||||
<div #targetEl [class.hidden]="!isVisible" class="z-10">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
`,
|
||||
standalone: true,
|
||||
})
|
||||
export class DropdownComponent implements AfterViewInit, OnDestroy {
|
||||
@ViewChild('targetEl') targetEl!: ElementRef<HTMLElement>;
|
||||
@Input() triggerEl!: HTMLElement;
|
||||
|
||||
@Input() placement: any = 'bottom';
|
||||
@Input() triggerType: 'click' | 'hover' = 'click';
|
||||
@Input() offsetSkidding: number = 0;
|
||||
@Input() offsetDistance: number = 10;
|
||||
@Input() delay: number = 300;
|
||||
@Input() ignoreClickOutsideClass: string | false = false;
|
||||
|
||||
@HostBinding('class.hidden') isHidden: boolean = true;
|
||||
|
||||
private popperInstance: PopperInstance | null = null;
|
||||
isVisible: boolean = false;
|
||||
private clickOutsideListener: any;
|
||||
private hoverShowListener: any;
|
||||
private hoverHideListener: any;
|
||||
|
||||
ngAfterViewInit() {
|
||||
if (!this.triggerEl) {
|
||||
console.error('Trigger element is not provided to the dropdown component.');
|
||||
return;
|
||||
}
|
||||
this.initializePopper();
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroyPopper();
|
||||
this.removeEventListeners();
|
||||
}
|
||||
|
||||
private initializePopper() {
|
||||
this.popperInstance = createPopper(this.triggerEl, this.targetEl.nativeElement, {
|
||||
placement: this.placement,
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [this.offsetSkidding, this.offsetDistance],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
private setupEventListeners() {
|
||||
if (this.triggerType === 'click') {
|
||||
this.triggerEl.addEventListener('click', () => this.toggle());
|
||||
} else if (this.triggerType === 'hover') {
|
||||
this.hoverShowListener = () => this.show();
|
||||
this.hoverHideListener = () => this.hide();
|
||||
this.triggerEl.addEventListener('mouseenter', this.hoverShowListener);
|
||||
this.triggerEl.addEventListener('mouseleave', this.hoverHideListener);
|
||||
this.targetEl.nativeElement.addEventListener('mouseenter', this.hoverShowListener);
|
||||
this.targetEl.nativeElement.addEventListener('mouseleave', this.hoverHideListener);
|
||||
}
|
||||
|
||||
this.clickOutsideListener = (event: MouseEvent) => this.handleClickOutside(event);
|
||||
document.addEventListener('click', this.clickOutsideListener);
|
||||
}
|
||||
|
||||
private removeEventListeners() {
|
||||
if (this.triggerType === 'click') {
|
||||
this.triggerEl.removeEventListener('click', () => this.toggle());
|
||||
} else if (this.triggerType === 'hover') {
|
||||
this.triggerEl.removeEventListener('mouseenter', this.hoverShowListener);
|
||||
this.triggerEl.removeEventListener('mouseleave', this.hoverHideListener);
|
||||
this.targetEl.nativeElement.removeEventListener('mouseenter', this.hoverShowListener);
|
||||
this.targetEl.nativeElement.removeEventListener('mouseleave', this.hoverHideListener);
|
||||
}
|
||||
|
||||
document.removeEventListener('click', this.clickOutsideListener);
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.isVisible ? this.hide() : this.show();
|
||||
}
|
||||
|
||||
show() {
|
||||
this.isVisible = true;
|
||||
this.isHidden = false;
|
||||
this.targetEl.nativeElement.classList.remove('hidden');
|
||||
this.popperInstance?.update();
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.isVisible = false;
|
||||
this.isHidden = true;
|
||||
this.targetEl.nativeElement.classList.add('hidden');
|
||||
}
|
||||
|
||||
private handleClickOutside(event: MouseEvent) {
|
||||
if (!this.isVisible) return;
|
||||
|
||||
const clickedElement = event.target as HTMLElement;
|
||||
if (this.ignoreClickOutsideClass) {
|
||||
const ignoredElements = document.querySelectorAll(`.${this.ignoreClickOutsideClass}`);
|
||||
const arr = Array.from(ignoredElements);
|
||||
for (const el of arr) {
|
||||
if (el.contains(clickedElement)) return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.targetEl.nativeElement.contains(clickedElement) && !this.triggerEl.contains(clickedElement)) {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
private destroyPopper() {
|
||||
if (this.popperInstance) {
|
||||
this.popperInstance.destroy();
|
||||
this.popperInstance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user