Skip to content

Commit

Permalink
Merge branch 'master' into build
Browse files Browse the repository at this point in the history
  • Loading branch information
serebrov committed Jan 31, 2021
2 parents d886539 + a39dee4 commit b109897
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 46 deletions.
69 changes: 44 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,26 @@

[![codecov](https://codecov.io/gh/serebrov/emoji-mart-vue/branch/master/graph/badge.svg)](https://codecov.io/gh/serebrov/emoji-mart-vue)

This project is a fork of https://github.com/jm-david/emoji-mart-vue with many performance fixes, tests and some structural code changes.
This project is a fork of https://github.com/jm-david/emoji-mart-vue with many performance fixes, tests and structural code changes.
See the [changelog](#changelog) for details.

The original component was [very slow to show/destroy](https://github.com/jm-david/emoji-mart-vue/pull/47), around 2 seconds to show and even a bit longer to destroy, so it was unusable in a popup.

This was the reason to fork and change it, the demo is [here](https://serebrov.github.io/emoji-mart-vue/), use the "Show / hide the picker" button to see create/destroy performance

Major changes are:

- Reworked emoji index class: use same index (so same data) for all components.
- Render emojis in categories without `Emoji` component, there are a lot of emojis to render and there is a noticeable slow down when we render a component per emoji.
- Frozen objects with emoji data to disable Vue change tracking
- Do not create `EmojiIndex` globally, before it was loaded (along with the emoji data) even when it was not actually used
- Extract CSS into external file, use less inline styles to reduce the amount of generated HTML
- Fixes in CSS for native unicode emojis ported from the [original react project](https://github.com/missive/emoji-mart)
- Excluded ./data/all.json from the js bundle (it was always loaded within the bundle even if it is not needed)
- Updated to babel 7
- Added tests
- Updated to emojis v12 (see the breaking change note below)

Breaking change in v6: removed `Emoji` and `Picker` [wrappers](#convenience-wrappers), renamed `NimbleEmoji` to `Emoji` and `NimblePicker` to `Picker`.
See the `Convenience Wrappers` section below for details.

Breaking change in v7: switched to Unicode v12 emoji set which results in several breaking changes:
- Removed 'emojione' set (removed from [emoji-datasource](https://github.com/iamcal/emoji-data) by [JoyPixels request](https://github.com/iamcal/emoji-data/blob/master/CHANGES.md#2018-07-05--v410))
- Removed 'messenger' set - it was [merged](https://github.com/iamcal/emoji-data/blob/master/CHANGES.md#2020-01-10--v500) into 'facebook' set
- Changed emoji categories: removed 'Smileys & People', added 'Smileys & Emotions' and 'People & Body' instead

> The original project has been forked from [emoji-mart](https://www.npmjs.com/package/emoji-mart) which was written for React
> The original project has been forked from [emoji-mart](https://www.npmjs.com/package/emoji-mart) which was written for React.
<div align="center">
<br><b>Emoji Mart (Vue)</b> is a Slack-like customizable<br>emoji picker component for VueJS
<br><a href="https://serebrov.github.io/emoji-mart-vue">Demo</a> • <a href="https://github.com/serebrov/emoji-mart-vue/releases">Changelog</a>
<br><img src="https://cloud.githubusercontent.com/assets/436043/17186519/9e71e8fe-5403-11e6-9314-21365c56a601.png">
</div>

## Demo app

Live demo app: https://serebrov.github.io/emoji-mart-vue/
Demo application code is [under the ./docs folder](./docs).

## Installation

Install from npm: `npm install --save emoji-mart-vue-fast`.
Expand All @@ -45,6 +30,14 @@ It is also possible to install directly from github (could be useful for forks):

Here is the list of [releases](https://github.com/serebrov/emoji-mart-vue/releases).

## Vue 3 Support

Component works with Vue 3, [here is a simple demo app](https://github.com/serebrov/emoji-mart-vue3-demo).

Live demo: https://serebrov.github.io/emoji-mart-vue3-demo/.

See also: [#88](https://github.com/serebrov/emoji-mart-vue/issues/88).

## Quick Example

```
Expand Down Expand Up @@ -100,6 +93,9 @@ export default {
</style>
```

## Not opinionated

**Emoji Mart** doesn’t automatically insert anything into a text input, nor does it show or hide itself. It simply returns an `emoji` object. It’s up to the developer to mount/unmount (it’s fast!) and position the picker. You can use the returned object as props for the `EmojiMart.Emoji` component. You could also use `emoji.colons` to insert text into a textarea or `emoji.native` to use the emoji.

## Components

Expand Down Expand Up @@ -667,9 +663,32 @@ export default {
</script>
```

## Not opinionated
## Changelog

Major changes comparing to the original emoji-mart-vue:

- Reworked emoji index class: use same index (so same data) for all components.
- Render emojis in categories without `Emoji` component, there are a lot of emojis to render and there is a noticeable slow down when we render a component per emoji.
- Frozen objects with emoji data to disable Vue change tracking
- Do not create `EmojiIndex` globally, before it was loaded (along with the emoji data) even when it was not actually used
- Extract CSS into external file, use less inline styles to reduce the amount of generated HTML
- Fixes in CSS for native unicode emojis ported from the [original react project](https://github.com/missive/emoji-mart)
- Excluded ./data/all.json from the js bundle (it was always loaded within the bundle even if it is not needed)
- Updated to babel 7
- Added tests
- Updated to emojis v12 (see the breaking change note below)

Breaking change in v6: removed `Emoji` and `Picker` [wrappers](#convenience-wrappers), renamed `NimbleEmoji` to `Emoji` and `NimblePicker` to `Picker`.
See the `Convenience Wrappers` section below for details.

Breaking change in v7: switched to Unicode v12 emoji set which results in several breaking changes:
- Removed 'emojione' set (removed from [emoji-datasource](https://github.com/iamcal/emoji-data) by [JoyPixels request](https://github.com/iamcal/emoji-data/blob/master/CHANGES.md#2018-07-05--v410))
- Removed 'messenger' set - it was [merged](https://github.com/iamcal/emoji-data/blob/master/CHANGES.md#2020-01-10--v500) into 'facebook' set
- Changed emoji categories: removed 'Smileys & People', added 'Smileys & Emotions' and 'People & Body' instead

Breaking change in v8:
- The `StaticPicker` component is now default (exported as `Picker`), previous default component renamed to `VirtualScrollPicker`

**Emoji Mart** doesn’t automatically insert anything into a text input, nor does it show or hide itself. It simply returns an `emoji` object. It’s up to the developer to mount/unmount (it’s fast!) and position the picker. You can use the returned object as props for the `EmojiMart.Emoji` component. You could also use `emoji.colons` to insert text into a textarea or `emoji.native` to use the emoji.

## Development

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "emoji-mart-vue-fast",
"version": "8.0.1",
"version": "8.0.2",
"description": "Customizable Slack-like emoji picker for VueJS, fast version",
"main": "dist/emoji-mart.js",
"repository": {
Expand Down
18 changes: 12 additions & 6 deletions spec/picker-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ describe('Picker', () => {
})

it('renders 10 categories', () => {
// Due to the virtual scroller, not all the categories
// are rendered at once
let categories = picker.findAll(Category)
// StaticPicker change (8 -> 10)
expect(categories.length).toBe(11)
// Hidden category with search results
expect(categories.at(0).vm.name).toBe('Search')
Expand All @@ -57,7 +54,6 @@ describe('Picker', () => {
expect(categories.at(6).vm.name).toBe('Activities')
expect(categories.at(7).vm.name).toBe('Travel & Places')
expect(categories.at(8).vm.name).toBe('Objects')
// StaticPicker change (Symbols and Flags)
expect(categories.at(9).vm.name).toBe('Symbols')
expect(categories.at(10).vm.name).toBe('Flags')
})
Expand Down Expand Up @@ -207,21 +203,31 @@ describe('anchors', () => {
])
})

it('can be clicked to scroll to the category', () => {
it('can be clicked to scroll to the category', async () => {
let anchors = picker.find(Anchors)

let anchorsCategories = anchors.findAll('span.emoji-mart-anchor')
let symbols = anchorsCategories.at(8)
expect(symbols.element.attributes['data-title'].value).toBe('Symbols')

// The `recent` category is selected initially.
expect(picker.vm.activeCategory.id).toBe('recent')
expect(anchors.vm.activeCategory.id).toBe('recent')

symbols.trigger('click')
let events = anchors.emitted().click
expect(events.length).toBe(1)

let category = events[0][0]
expect(category.id).toBe('symbols')
expect(category.name).toBe('Symbols')

// StaticPicker change - the check below fails (although works in demo app)
await picker.vm.$nextTick()

// Picker change - the check below fails (although works in demo app)
// scrollTop if 0 for all categories and activeCategory is changed in the
// onScroll handler, need to find a way to thes this.
// expect(picker.vm.activeCategory.id).toBe('symbols')
// expect(anchors.vm.activeCategory.id).toBe('symbols')
})
})
Expand Down
35 changes: 22 additions & 13 deletions src/components/Picker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,11 @@ export default {
},
onScrollPaint() {
this.waitingForPaint = false
let scrollTop = this.$refs.scroll.scrollTop,
activeCategory = this.filteredCategories[0]
let scrollTop = this.$refs.scroll.scrollTop
let activeCategory = this.filteredCategories[0]
for (let i = 0, l = this.filteredCategories.length; i < l; i++) {
let category = this.filteredCategories[i],
component = this.$refs['categories_' + i]
let category = this.filteredCategories[i]
let component = this.getCategoryComponent(i)
// The `-50` offset switches active category (selected in the
// anchors bar) a bit eariler, before it actually reaches the top.
if (component && component.$el.offsetTop - 50 > scrollTop) {
Expand All @@ -216,17 +216,17 @@ export default {
// No categories are shown when search is active.
return
}
let i = this.filteredCategories.indexOf(category),
component = this.$refs['categories_' + i],
scrollToComponent = () => {
if (component) {
let top = component.$el.offsetTop
if (category.first) {
top = 0
}
this.$refs.scroll.scrollTop = top
let i = this.filteredCategories.indexOf(category)
let component = this.getCategoryComponent(i)
let scrollToComponent = () => {
if (component) {
let top = component.$el.offsetTop
if (category.first) {
top = 0
}
this.$refs.scroll.scrollTop = top
}
}
if (this.infiniteScroll) {
scrollToComponent()
} else {
Expand All @@ -253,6 +253,15 @@ export default {
this.$emit('skin-change', skin)
},
getCategoryComponent(index) {
let component = this.$refs['categories_' + index]
if ('0' in component) {
// Vue 2 has $refs under v-for as an array.
return component['0']
}
// Vue 3 does not support $refs as array.
return component
},
},
components: {
Anchors,
Expand Down

0 comments on commit b109897

Please sign in to comment.