diff --git a/src/lib/emoji/emoji.component.ts b/src/lib/emoji/emoji.component.ts index 50aeb12f..8d3e9253 100644 --- a/src/lib/emoji/emoji.component.ts +++ b/src/lib/emoji/emoji.component.ts @@ -50,7 +50,6 @@ export interface EmojiEvent { `, - styles: [], changeDetection: ChangeDetectionStrategy.OnPush, preserveWhitespaces: false, }) @@ -81,9 +80,7 @@ export class EmojiComponent implements OnChanges, Emoji { this.set }/sheets-256/${this.sheetSize}.png` - constructor( - private emojiService: EmojiService, - ) {} + constructor(private emojiService: EmojiService) {} ngOnChanges() { if (!this.emoji) { @@ -93,42 +90,37 @@ export class EmojiComponent implements OnChanges, Emoji { if (!data) { return this.isVisible = false; } - - const { unified, custom, short_names, imageUrl, obsoleted_by, native } = data; // const children = this.children; this.unified = null; - if (custom) { - this.custom = custom; + if (data.custom) { + this.custom = data.custom; } - - if (!unified && !custom) { + if (!data.unified && !data.custom) { return this.isVisible = false; } - if (this.tooltip) { - this.title = short_names[0]; + this.title = data.short_names[0]; } - - if (obsoleted_by && this.hideObsolete) { + if (data.obsoleted_by && this.hideObsolete) { return this.isVisible = false; } - if (this.native && unified && native) { + if (this.native && data.unified && data.native) { // hide older emoji before the split into gendered emoji this.style = { fontSize: `${this.size}px` }; - this.unified = native; + this.unified = data.native; if (this.forceSize) { this.style.display = 'inline-block'; this.style.width = `${this.size}px`; this.style.height = `${this.size}px`; } - } else if (custom) { + } else if (data.custom) { this.style = { width: `${this.size}px`, height: `${this.size}px`, display: 'inline-block', - backgroundImage: `url(${imageUrl})`, + backgroundImage: `url(${data.imageUrl})`, backgroundSize: 'contain', }; } else { diff --git a/src/lib/picker/anchors.component.ts b/src/lib/picker/anchors.component.ts index 00fe7e97..c996bf7a 100644 --- a/src/lib/picker/anchors.component.ts +++ b/src/lib/picker/anchors.component.ts @@ -13,7 +13,7 @@ import SVGs from './svgs'; selector: 'emoji-mart-anchors', template: `
- + - +
`, - styles: [], changeDetection: ChangeDetectionStrategy.OnPush, preserveWhitespaces: false, }) @@ -47,6 +46,9 @@ export class AnchorsComponent { @Output() anchorClick = new EventEmitter<{ category: EmojiCategory, index: number }>(); svgs: any = SVGs; + trackByFn(idx: number, cat: EmojiCategory) { + return cat.id; + } handleClick($event: Event, index: number) { this.anchorClick.emit({ category: this.categories[index], diff --git a/src/lib/picker/category.component.ts b/src/lib/picker/category.component.ts index f032924a..ccc92326 100644 --- a/src/lib/picker/category.component.ts +++ b/src/lib/picker/category.component.ts @@ -74,7 +74,6 @@ import { EmojiFrequentlyService } from './emoji-frequently.service'; `, - styles: [], changeDetection: ChangeDetectionStrategy.OnPush, preserveWhitespaces: false, }) @@ -133,7 +132,6 @@ export class CategoryComponent implements OnInit, AfterViewInit { this.parent = this.container!.nativeElement.parentNode.parentNode; this.memoizeSize(); } - memoizeSize() { const { top, @@ -150,14 +148,13 @@ export class CategoryComponent implements OnInit, AfterViewInit { this.maxMargin = height - labelHeight; } } - - handleScroll(scrollTop: number) { + handleScroll(scrollTop: number): boolean { let margin = scrollTop - this.top; margin = margin < this.minMargin ? this.minMargin : margin; margin = margin > this.maxMargin ? this.maxMargin : margin; if (margin === this.margin) { - return; + return false; } if (!this.hasStickyPosition) { diff --git a/src/lib/picker/picker.component.html b/src/lib/picker/picker.component.html index f1fed2ca..70af17dd 100644 --- a/src/lib/picker/picker.component.html +++ b/src/lib/picker/picker.component.html @@ -13,6 +13,7 @@
(); @ViewChild('scrollRef') private scrollRef?: ElementRef; @ViewChild('previewRef') private previewRef?: PreviewComponent; + @ViewChild('searchRef') private searchRef?: SearchComponent; @ViewChildren('categoryRef') private categoryRefs?: QueryList; scrollHeight = 0; clientHeight = 0; selected?: string; + nextScroll?: string; scrollTop?: number; firstRender = true; recent?: string[]; @@ -114,7 +121,10 @@ export class PickerComponent implements OnInit, AfterViewInit { this.set }/sheets-256/${this.sheetSize}.png` - constructor(private frequently: EmojiFrequentlyService) {} + constructor( + private ref: ChangeDetectorRef, + private frequently: EmojiFrequentlyService, + ) {} ngOnInit() { // measure scroll @@ -150,12 +160,7 @@ export class PickerComponent implements OnInit, AfterViewInit { }); } - for ( - let categoryIndex = 0; - categoryIndex < allCategories.length; - categoryIndex++ - ) { - const category = allCategories[categoryIndex]; + for (const category of allCategories) { const isIncluded = this.include && this.include.length ? this.include.indexOf(category.id) > -1 @@ -212,12 +217,17 @@ export class PickerComponent implements OnInit, AfterViewInit { this.categories.unshift(this.SEARCH_CATEGORY); this.selected = this.categories.filter(category => category.first)[0].name; - } + this.activeCategories = this.categories.slice(0, 3); + setTimeout(() => { + this.activeCategories = this.categories; + this.ref.markForCheck(); + this.updateCategoriesSize(); + }); + } ngAfterViewInit() { this.updateCategoriesSize(); } - updateCategoriesSize() { this.categoryRefs!.forEach(component => component.memoizeSize()); @@ -227,90 +237,63 @@ export class PickerComponent implements OnInit, AfterViewInit { this.clientHeight = target.clientHeight; } } - handleAnchorClick($event: { category: EmojiCategory; index: number }) { const component = this.categoryRefs!.find(n => n.id === $event.category.id); - let scrollToComponent = null; - - scrollToComponent = () => { - if (component) { - let { top } = component; - - if ($event.category.first) { - top = 0; - } else { - top += 1; - } - this.scrollRef!.nativeElement.scrollTop = top; - } - }; if (this.SEARCH_CATEGORY.emojis) { - // this.handleSearch(null); - // this.search.clear(); + this.handleSearch(null); + this.searchRef!.clear(); + } + if (component) { + let { top } = component; - window.requestAnimationFrame(scrollToComponent); - } else { - scrollToComponent(); + if ($event.category.first) { + top = 0; + } else { + top += 1; + } + this.scrollRef!.nativeElement.scrollTop = top; } + this.selected = $event.category.name; + this.nextScroll = $event.category.name; } categoryTrack(index: number, item: any) { return item.id; } handleScroll() { + if (this.nextScroll) { + this.selected = this.nextScroll; + this.nextScroll = undefined; + return; + } if (!this.scrollRef) { return; } let activeCategory = null; - let scrollTop; - if (this.SEARCH_CATEGORY.emojis) { activeCategory = this.SEARCH_CATEGORY; } else { const target = this.scrollRef.nativeElement; - scrollTop = target.scrollTop; - const scrollingDown = scrollTop > (this.scrollTop || 0); - let minTop = 0; - - for (let i = 0, l = this.categories.length; i < l; i++) { - const ii = scrollingDown ? this.categories.length - 1 - i : i; - const category = this.categories[ii]; - const component = this.categoryRefs!.find(n => n.id === category.id); - - if (component) { - const active = component.handleScroll(scrollTop); - - if (!minTop || component.top < minTop) { - if (component.top > 0) { - minTop = component.top; - } - } - - if (active && !activeCategory) { + // check scroll is not at bottom + if (target.scrollHeight - target.scrollTop !== this.clientHeight) { + for (const category of this.categories) { + const component = this.categoryRefs!.find(n => n.id === category.id); + const active = component!.handleScroll(target.scrollTop); + if (active) { activeCategory = category; } } - } - - if (scrollTop < minTop) { - activeCategory = this.categories.filter( - category => !(category.anchor === false), - )[0]; - } else if (scrollTop + this.clientHeight >= this.scrollHeight) { + } else { + // scrolled to bottom activate last category activeCategory = this.categories[this.categories.length - 1]; } - } + this.scrollTop = target.scrollTop; + } if (activeCategory) { - const { name: categoryName } = activeCategory; - - if (this.selected !== categoryName) { - this.selected = categoryName; - } + this.selected = activeCategory.name; } - - this.scrollTop = scrollTop; } handleSearch($emojis: any) { this.SEARCH_CATEGORY.emojis = $emojis; diff --git a/src/lib/picker/search.component.ts b/src/lib/picker/search.component.ts index a077be48..aa083a93 100644 --- a/src/lib/picker/search.component.ts +++ b/src/lib/picker/search.component.ts @@ -1,6 +1,5 @@ import { AfterViewInit, - ChangeDetectionStrategy, Component, ElementRef, EventEmitter, @@ -21,8 +20,6 @@ import { EmojiSearch } from './emoji-search.service'; />
`, - styles: [], - changeDetection: ChangeDetectionStrategy.OnPush, preserveWhitespaces: false, }) export class SearchComponent implements AfterViewInit { @@ -45,6 +42,9 @@ export class SearchComponent implements AfterViewInit { this.inputRef.nativeElement.focus(); } } + clear() { + this.query = ''; + } handleEnterKey($event: Event) { this.enterKey.emit($event); $event.preventDefault();