import {
AfterViewInit, ChangeDetectorRef,
Component, ComponentFactoryResolver, ComponentRef,
Directive,
ElementRef,
EventEmitter,
HostListener, Input, OnChanges, OnDestroy,
Output, SimpleChanges,
ViewChild,
ViewContainerRef
} from "@angular/core";
import * as emojis from './emojis';
import {EmojiCategory} from './emojis';
import {each} from "@marcj/estdlib";
import {DropdownComponent} from "../button";
@Component({
selector: 'dui-emoji-dropdown',
template: `
`,
styleUrls: ['./emoji-dropdown.component.scss'],
})
export class EmojiDropdownComponent implements AfterViewInit {
@Input() blacklist: string[] = [];
@Input() lastEmojis: string[] = [];
@Output() lastEmojisChange = new EventEmitter();
@Input() emoji: string = '';
@Output() emojiChange = new EventEmitter();
@ViewChild(DropdownComponent, {static: true}) dropdown!: DropdownComponent;
emojis = emojis;
search: string = '';
categories: string[] = [
'Smileys & People',
'Animals & Nature',
'Food & Drink',
'Activities',
'Travel & Places',
'Objects',
'Symbols',
'Flags',
];
constructor(protected element: ElementRef, protected cd: ChangeDetectorRef) {
}
getLast(emojis: string[]): string[] | undefined {
if (!emojis.length) return;
return [...new Set(emojis.map(v => {
if (v[0] === ':') return v.substring(1, v.length - 1);
return v[0];
}))];
}
ngAfterViewInit() {
this.element.nativeElement.remove();
}
public open(target: ElementRef) {
if (this.search) {
this.search = '';
this.cd.detectChanges();
}
this.dropdown.toggle(target);
if (this.emoji) {
const element = document.getElementById('emoji_' + this.emoji);
if (element) {
element.scrollIntoView({behavior: 'smooth', block: 'center'});
}
}
}
find(search: string): string[] {
search = search.toLowerCase();
const result: string[] = [];
for (const emoji of each(emojis.emojis)) {
if (-1 !== emoji.name.toLowerCase().indexOf(search)) {
result.push(emoji.shortName);
}
}
return result;
}
choose(name: string) {
name = ':' + name + ':';
this.emoji = name;
this.emojiChange.emit(name);
if (-1 === this.lastEmojis.indexOf(name)) {
this.lastEmojis.push(name);
} else {
const index = this.lastEmojis.indexOf(name);
if (index > 0) {
this.lastEmojis.splice(index, 1);
this.lastEmojis.splice(index - 1, 0, name);
}
}
this.lastEmojis = this.lastEmojis.slice(0);
this.dropdown.close();
this.cd.detectChanges();
}
getCategory(name: string): EmojiCategory {
for (const category of emojis.categories) {
if (category.name === name) return category;
}
throw new Error(`No category for name ${name} found`);
}
}
@Directive({
selector: '[duiEmojiDropdown]'
})
export class EmojiDropdownDirective implements OnChanges, AfterViewInit, OnDestroy {
protected dropdown?: ComponentRef;
@Input() lastEmojis: string[] = [];
@Output() lastEmojisChange = new EventEmitter();
@Input() blacklist: string[] = [];
@Input() emoji: string = '';
@Output() emojiChange = new EventEmitter();
constructor(
protected elementRef: ElementRef,
protected view: ViewContainerRef,
protected resolver: ComponentFactoryResolver,
) {
}
ngAfterViewInit() {
const factory = this.resolver.resolveComponentFactory(EmojiDropdownComponent);
this.dropdown = this.view.createComponent(factory);
this.dropdown.instance.emojiChange = this.emojiChange;
this.dropdown.instance.lastEmojisChange = this.lastEmojisChange;
this.dropdown.instance.blacklist = this.blacklist;
this.dropdown.instance.lastEmojis = this.lastEmojis;
this.dropdown.instance.emoji = this.emoji;
this.dropdown.changeDetectorRef.detectChanges();
}
ngOnChanges(changes: SimpleChanges): void {
if (this.dropdown) {
this.dropdown.instance.blacklist = this.blacklist;
this.dropdown.instance.emoji = this.emoji;
this.dropdown.instance.lastEmojis = this.lastEmojis;
this.dropdown.changeDetectorRef.detectChanges();
}
}
@HostListener('click')
onClick() {
if (this.dropdown) {
this.dropdown.instance.open(this.elementRef);
}
}
ngOnDestroy() {
if (this.dropdown) {
this.dropdown.destroy();
}
}
}