Gathering detailed insights and metrics for emoji-mart-vue-fast
Gathering detailed insights and metrics for emoji-mart-vue-fast
Gathering detailed insights and metrics for emoji-mart-vue-fast
Gathering detailed insights and metrics for emoji-mart-vue-fast
npm install emoji-mart-vue-fast
Typescript
Module System
Node Version
NPM Version
82.1
Supply Chain
99.1
Quality
78
Maintenance
100
Vulnerability
100
License
JavaScript (75.81%)
Vue (15.7%)
CSS (8.38%)
Dockerfile (0.12%)
Total Downloads
5,238,609
Last Day
7,273
Last Week
30,345
Last Month
123,059
Last Year
1,537,522
283 Stars
1,320 Commits
49 Forks
4 Watching
16 Branches
48 Contributors
Minified
Minified + Gzipped
Latest Version
15.0.3
Package Id
emoji-mart-vue-fast@15.0.3
Unpacked Size
3.91 MB
Size
531.56 kB
File Count
39
NPM Version
10.2.3
Node Version
20.10.0
Publised On
21 Sept 2024
Cumulative downloads
Total Downloads
Last day
13.5%
7,273
Compared to previous day
Last week
-9.5%
30,345
Compared to previous week
Last month
7.7%
123,059
Compared to previous month
Last year
4.7%
1,537,522
Compared to previous year
2
1
29
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 for details.
The original component was very slow to show/destroy, 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, use the "Show / hide the picker" button to see create/destroy performance
The original project has been forked from emoji-mart which was written for React.
Live demo app: https://serebrov.github.io/emoji-mart-vue/ Demo application code is under the ./docs folder.
Install from npm: npm install --save emoji-mart-vue-fast
.
It is also possible to install directly from github (could be useful for forks): npm install --save serebrov/emoji-mart-vue#5.4.9.
Here is the list of releases.
Component works with Vue 3, here is a simple demo app.
Live demo: https://serebrov.github.io/emoji-mart-vue3-demo/.
See also: #88.
<template>
<div class="row">
<Picker :data="emojiIndex" set="twitter" @select="showEmoji" />
</div>
<div class="row">
<div>
{{ emojisOutput }}
</div>
</div>
</template>
<script>
// Import data/twitter.json to reduce size, all.json contains data for
// all emoji sets.
import data from "emoji-mart-vue-fast/data/all.json";
// Import default CSS
import "emoji-mart-vue-fast/css/emoji-mart.css";
// Vue 2:
import { Picker, EmojiIndex } from "emoji-mart-vue-fast";
// Vue 3, import components from `/src`:
import { Picker, EmojiIndex } from "emoji-mart-vue-fast/src";
// Create emoji data index.
// We can change it (for example, filter by category) before passing to the component.
let emojiIndex = new EmojiIndex(data);
export default {
name: "App",
components: {
Picker
},
data() {
return {
emojiIndex: emojiIndex,
emojisOutput: ""
};
},
methods: {
showEmoji(emoji) {
this.emojisOutput = this.emojisOutput + emoji.native;
}
}
};
</script>
<style>
.row { display: flex; }
.row > * { margin: auto; }
</style>
Major changes comparing to the original emoji-mart-vue:
Performance improvements:
Emoji
component, there are a lot of emojis to render and there is a noticeable slow down when we render a component per emoji.EmojiIndex
globally, before it was loaded (along with the emoji data) even when it was not actually usedBreaking change in v6: removed Emoji
and Picker
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:
Breaking change in v8:
StaticPicker
component is now default (exported as Picker
), previous default component renamed to VirtualScrollPicker
Breaking change in v12:
VirtualScrollPicker
was removed, see #236.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.
1import data from 'emoji-mart-vue-fast/data/all.json' 2import { Picker, EmojiIndex } from 'emoji-mart-vue-fast' 3let emojiIndex = new EmojiIndex(data)
Import CSS with default styles:
1import 'emoji-mart-vue-fast/css/emoji-mart.css'
Note: to have a custom look for the picker, either use own css file without including the standard one or add custom styles on top of standard.
Note: CSS also includes background images for image-based emoji sets (apple, google, twitter, facebook). The images are loaded from the unpkg.com
. To use self-hosted emojis sheet, override CSS like this:
1/* load twitter sheet from own server */ 2.emoji-mart-body .emoji-type-image.emoji-set-twitter { 3 background-image: url(/img/twitter-5.0.1-sheets-256-64.png); 4}
Add the <picker>
component to your template:
1<picker :data="emojiIndex" set="twitter" /> 2<picker :data="emojiIndex" @select="addEmoji" /> 3<picker :data="emojiIndex" title="Pick your emoji…" emoji="point_up" /> 4<picker :data="emojiIndex" :style="{ position: 'absolute', bottom: '20px', right: '20px' }" /> 5<picker :data="emojiIndex" 6 :i18n="{ search: 'Recherche', categories: { search: 'Résultats de recherche', recent: 'Récents' } }" 7/>
Prop | Required | Default | Description |
---|---|---|---|
autoFocus | false | Auto focus the search input when mounted | |
color | #ae65c5 | The top bar anchors select and hover color | |
emoji | department_store | The emoji shown when no emojis are hovered, set to an empty string to show nothing | |
emojiSize | 24 | The emoji width and height; affects font size for native emoji (it is 80% of emojiSize); also the picker width is cacluated dynamically based on emojiSize | |
perLine | 9 | Number of emojis per line. While there’s no minimum or maximum, this will affect the picker’s width. | |
i18n | {…} | An object containing localized strings | |
native | false | Renders the native unicode emoji | |
set | apple | The emoji set: 'apple', 'google', 'twitter', 'facebook' | |
showPreview | true | Display preview section | |
showSearch | true | Display search section | |
showCategories | true | Display categories | |
showSkinTones | true | Display skin tones picker | |
emojiTooltip | false | Show emojis short name when hovering (title) | |
skin | Forces skin color: 1, 2, 3, 4, 5, 6 | ||
defaultSkin | 1 | Default skin color: 1, 2, 3, 4, 5, 6 | |
pickerStyles | Inline styles applied to the root element. Useful for positioning | ||
title | Emoji Mart™ | The title shown when no emojis are hovered | |
infiniteScroll | true | Scroll continuously through the categories |
Event | Description |
---|---|
select | Params: (emoji) => {} |
skin-change | Params: (skin) => {} |
The select
event described above can be handled to insert the emoji into the text area or use it in any other way.
This component does not enforce the usage pattern and it's up to the application how to handle the emoji after it was selected.
For example:
<picker :data="emojiIndex" @select="this.selectEmoji" />
...
selectEmoji(emoji) {
// Assuming the `textContainer` method that returns the
// text container component with `enterText` method.
const textContainer = this.textContainer()
// Enter the native emoji
textContainer.enterText(emoji.native)
}
The above will use emoji.native
to insert native emoji into the input.
This is the simplest way to use the component and it works relatively well in latest versions of native browsers and latest operating systems. Here, we rely on native unicode emojis support, which, theoretically, should be handled just like any other unicode characters.
In practice, the support for native unicode emoji is still not perfect: unicode emoji characters are part of the font and the font needs to be colorful. But there is no yet a single standard for color fonts implemented by browsers, so the browser leaves emoji rendering to the operating system.
This way, how the emoji will look depends on the operating system and native unicode emoji will look different on different platforms. Also older operating system versions don't not support all the emojis that are currently in the unicode standard, so it may be necessary to limit emojis to some smaller subset.
More consistent solution is also more complex: we can use emoji.colons
to insert emoji in the "colons" syntax (such as :smile:
) and use regular expressions to find and render the colons emoji as images.
In this case the application can keep text emoji representation and replace before rendering wherever needed (browser, mobile app, email).
The good part here is that we get rid of most of the problems, related to unicode, we work with plain text. For example, in the database the application could have a text like "Hello :smile:" which will be turned into emoji with javascript and even if we leave it as a text (due to the bug or lack of javascript support), it will still make sense.
The bad part is that conflicts are possible - if someone enters the :smile:
text, it will turn into emoji.
The emoji.getPosition()
might be useful in this case to get the emoji position on the emoji sprite sheet.
The replacement can be done approximately like this:
const COLONS_REGEX = new RegExp(
'([^:]+)?(:[a-zA-Z0-9-_+]+:(:skin-tone-[2-6]:)?)',
'g'
)
/**
* Replace emojis insdie the `text` with `<span>`s.
*/
export function wrapEmoji(text: string): string {
return text.replace(COLONS_REGEX, function(match, p1, p2) {
const before = p1 || ''
// We add "data-text='{emoji.native}'", don't replace it
if (endsWith(before, 'alt="') || endsWith(before, 'data-text="')) {
return match
}
let emoji = emojiIndex.findEmoji(p2)
if (!emoji) {
return match
}
return before + emojiToHtml(emoji)
})
return text;
}
/**
* Convert Emoji to HTML to represent it as an image.
*/
export function emojiToHtml(emoji: Emoji): string {
let style = `background-position: ${emoji.getPosition()}`
// The src="data:image..." is needed to prevent border around img tags.
return `<img data-text="${emoji.native}" alt="${
emoji.colons
}" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class='emoji-text' style="${style}">`
}
Another solution is to use emoji.native
to insert native emoji and then find and replace them with images.
In this case, the application can keep the native emoji in the database and replace with images where needed - in this case, it can do the replacement for browser, but keep unicode emoji for native app.
The good side here is that conflicts are unlikely, we have native unicode emoji as a part of the text and replace them with images for better browser / os support. It means that if browsers improve the color font support in the future, we can just remove the image replacement part and the rest will be working.
The replacement can be done like this (using the emoji-regex package):
// npm install emoji-regex
import emojiRegex from 'emoji-regex'
import data from 'emoji-mart-vue-fast/data/all.json'
import { EmojiIndex } from 'emoji-mart-vue-fast'
const unicodeEmojiRegex = emojiRegex()
export function wrapEmoji(text: string): string {
return text.replace(unicodeEmojiRegex, function(match, offset) {
const before = text.substring(0, offset)
if (endsWith(before, 'alt="') || endsWith(before, 'data-text="')) {
// Emoji inside the replaced <img>
return match
}
// Find emoji object by native emoji.
let emoji = emojiIndex.nativeEmoji(match)
if (!emoji) {
// Can't find unicode emoji in our index
return match
}
// See `emojiToHtml` function above.
return emojiToHtml(emoji)
})
}
Here we can use emojiIndex.nativeEmoji(emoji_char)
to get the emoji object by native emoji and then convert it to the HTML image.
1search: 'Search', 2notfound: 'No Emoji Found', 3categories: { 4 search: 'Search Results', 5 recent: 'Frequently Used', 6 smileys: 'Smileys & Emoticon', 7 people: 'People & Body', 8 nature: 'Animals & Nature', 9 foods: 'Food & Drink', 10 activity: 'Activity', 11 places: 'Travel & Places', 12 objects: 'Objects', 13 symbols: 'Symbols', 14 flags: 'Flags', 15 custom: 'Custom', 16}
Sheets are served from unpkg, a global CDN that serves files published to npm. Note: URLs for background images are specified in the css/emoji-mart.css.
Set | Size (sheetSize: 16 ) | Size (sheetSize: 20 ) | Size (sheetSize: 32 ) | Size (sheetSize: 64 ) |
---|---|---|---|---|
apple | 334 KB | 459 KB | 1.08 MB | 2.94 MB |
322 KB | 439 KB | 1020 KB | 2.50 MB | |
301 KB | 409 KB | 907 KB | 2.17 MB | |
288 KB | 389 KB | 839 KB | 1.82 MB |
While the default setup assumes all.json
usage with all sets available, you may want to include only a single set data to reduce the size of your bundle.
Set | Size (on disk) |
---|---|
all | 570 KB |
apple | 484 KB |
421 KB | |
483 KB | |
484 KB |
To use these data files (or any other custom data), use the Picker
component like this:
1import data from 'emoji-mart-vue-fast/data/facebook.json' 2import { Picker, EmojiIndex } from 'emoji-mart-vue-fast' 3let index = new EmojiIndex(data)
1<picker set="facebook" :data="data" />
Using EmojiIndex
, it is also possible to control which emojis data is included or excluded via constructor parameters:
Param | Default | Description |
---|---|---|
include | [] | Only load included categories. Accepts I18n categories keys. Order will be respected, except for the recent category which will always be the first. |
exclude | [] | Don't load excluded categories. Accepts I18n categories keys. |
custom | [] | Custom emojis |
recent | Pass your own frequently used emojis as array of string IDs | |
recentLength | Set the number of emojis for the recent category. | |
emojisToShowFilter | ((emoji) => true) |
Categories for exclude
and include
parameters are specified as category id, that are present in data arrays.
Avaiable categories are: people,
nature,
foods,
activity,
places,
objects,
symbols,
flags
.
For example:
1import data from 'emoji-mart-vue-fast/data/facebook.json' 2import { Picker, EmojiIndex } from 'emoji-mart-vue-fast' 3 4let emojisToShowFilter = function(emoji) { 5 // check the emoji properties, see the examples of emoji object below 6 return true // return true to include or false to exclude 7} 8let include = ['people', 'nature'] 9// or exclude: 10// let exclude = ['flags'] 11 12const custom = [ 13 { 14 name: 'Octocat', 15 short_names: ['octocat'], 16 text: '', 17 emoticons: [], 18 keywords: ['github'], 19 imageUrl: 'https://assets-cdn.github.com/images/icons/emoji/octocat.png?v7', 20 }, 21] 22 23let index = new EmojiIndex(data, { 24 emojisToShowFilter, 25 include, 26 exclude, 27 custom, 28})
emoji
object:1{ 2 id: 'smiley', 3 name: 'Smiling Face with Open Mouth', 4 colons: ':smiley:', 5 text: ':)', 6 emoticons: [ 7 '=)', 8 '=-)' 9 ], 10 skin: null, 11 native: '😃' 12} 13 14{ 15 id: 'santa', 16 name: 'Father Christmas', 17 colons: ':santa::skin-tone-3:', 18 text: '', 19 emoticons: [], 20 skin: 3, 21 native: '🎅🏼' 22} 23 24{ 25 id: 'octocat', 26 name: 'Octocat', 27 colons: ':octocat', 28 text: '', 29 emoticons: [], 30 custom: true, 31 imageUrl: 'https://assets-cdn.github.com/images/icons/emoji/octocat.png?v7' 32}
When the cursor is in the search field, the Picker
component allows to select the emoji with arrow keys.
The selection is confirm with enter, which will emit the selected
event (same as when the emoji is clicked with mouse).
1import data from 'emoji-mart-vue-fast/data/all.json' 2import { Emoji, EmojiIndex } from 'emoji-mart-vue-fast'
1<emoji :data="index" emoji=":santa::skin-tone-3:" :size="32" /> 2<emoji :data="index" emoji="santa" set="twitter" :size="32" /> 3<emoji :data="index" :emoji="santaEmojiObject" :size="32" /> 4 5<script> 6import data from 'emoji-mart-vue-fast/data/all.json' 7let index = new EmojiIndex(data) 8 9export default { 10 computed: { 11 santaEmojiObject() { 12 return index.findEmoji(':santa:') 13 }, 14 }, 15} 16</script> 17
Prop | Required | Default | Description |
---|---|---|---|
emoji | ✓ | Either a string or an emoji object | |
size | ✓ | The emoji width and height. | |
native | false | Renders the native unicode emoji | |
fallback | Params: (emoji) => {} | ||
set | apple | The emoji set: 'apple', 'google', 'twitter', 'facebook' | |
sheetSize | 64 | The emoji sheet size: 16, 20, 32, 64 | |
backgroundImageFn | ((set, sheetSize) => `https://unpkg.com/emoji-datasource@3.0.0/sheet_${set}_${sheetSize}.png`) | A Fn that returns that image sheet to use for emojis. Useful for avoiding a request if you have the sheet locally. | |
skin | 1 | Skin color: 1, 2, 3, 4, 5, 6 | |
tooltip | false | Show emoji short name when hovering (title) | |
tag | span | HTML tag to use, span by default, set to button for clickable emojis. |
Event | Description |
---|---|
select | Params: (emoji) => {} |
mouseenter | Params: (emoji) => {} |
mouseleave | Params: (emoji) => {} |
Certain sets don’t support all emojis (i.e. Facebook don’t support :shrug:
). By default the Emoji component will not render anything so that the emojis’ don’t take space in the picker when not available. When using the standalone Emoji component, you can however render anything you want by providing the fallback
props.
To have the component render :shrug:
you would need to:
1function emojiFallback(emoji) { 2 return `:${emoji.short_names[0]}:` 3}
1<emoji set="facebook" emoji="shrug" :size="24" :fallback="emojiFallback" />
The Picker
doesn’t have to be mounted for you to take advantage of the advanced search results.
1import { EmojiIndex } from 'emoji-mart-vue-fast' 2import data from 'emoji-mart-vue-fast/data/all.json' 3 4const emojiIndex = new EmojiIndex(data) 5emojiIndex.search('christmas').map((o) => o.native) 6// => [🎄, 🎅🏼, 🔔, 🎁, ⛄️, ❄️]
1import data from 'emoji-mart-vue-fast/data/facebook' 2import { EmojiIndex } from 'emoji-mart-vue-fast' 3 4let emojiIndex = new EmojiIndex(data) 5emojiIndex.search('christmas')
By default EmojiMart will store user chosen skin and frequently used emojis in localStorage
. That can however be overwritten should you want to store these in your own storage.
1import { store } from 'emoji-mart-vue-fast' 2 3store.setHandlers({ 4 getter: (key) => { 5 // Get from your own storage (sync) 6 }, 7 8 setter: (key, value) => { 9 // Persist in your own storage (can be async) 10 }, 11})
Possible keys are:
Key | Value | Description |
---|---|---|
skin | 1, 2, 3, 4, 5, 6 | |
frequently | { 'astonished': 11, '+1': 22 } | An object where the key is the emoji name and the value is the usage count |
last | 'astonished' | (Optional) Used by frequently to be sure the latest clicked emoji will always appear in the “Recent” category |
Not only does Emoji Mart return more results than most emoji picker, they’re more accurate and sorted by relevance.
The only emoji picker that returns emojis when searching for emoticons.
For better results, Emoji Mart split search into words and only returns results matching both terms.
As the developer, you have control over which skin color is used by default.
It can however be overwritten as per user preference.
Apple / Google / Twitter / Facebook
The original project had convenience wrappers for Emoji
and Picker
components that make the usage a bit simpler.
But, since they are using all.json
for data, that resulted in bigger bundle sizes as all.json
was also included into the any app that is using emoji picker, even if it doesn't need all kinds of emojis.
Original components were removed and included here as an example.
Picker component wrapper with default settings:
1<script> 2import data from 'emoji-mart-vue-fast/data/all.json' 3import { EmojiIndex } from 'emoji-mart-vue-fast/src/utils/emoji-data' 4import EmojiMartPicker from 'emoji-mart-vue-fast/src/components/Picker' 5 6import { PickerProps } from 'emoji-mart-vue-fast/src/utils/shared-props' 7 8let index = new EmojiIndex(data) 9 10export default { 11 functional: true, 12 props: { 13 ...PickerProps, 14 data: { 15 type: Object, 16 default() { 17 return index 18 }, 19 }, 20 }, 21 render(h, ctx) { 22 let { data, props, children } = ctx 23 24 return h(EmojiMartPicker, { ...data, props }, children) 25 }, 26} 27</script>
Emoji component wrapper with default settings:
1<script> 2import data from 'emoji-mart-vue-fast/data/all.json' 3import { EmojiIndex } from 'emoji-mart-vue-fast/src/utils/emoji-data' 4import EmojiMartEmoji from 'emoji-mart-vue-fast/src/components/Emoji' 5 6import { EmojiProps } from 'emoji-mart-vue-fast/src/utils/shared-props' 7 8export default { 9 functional: true, 10 props: { 11 ...EmojiProps, 12 data: { 13 type: Object, 14 default() { 15 let index = new EmojiIndex(data) 16 return index 17 }, 18 }, 19 }, 20 render(h, ctx) { 21 let { data, props, children } = ctx 22 23 return h(EmojiMartEmoji, { ...data, props }, children) 24 }, 25} 26</script>
Build the component and the demo app.
1# Build the component and watch for file changes. 2$ npm run build
1# Build the demo app and watch for file changes. 2$ npm run dev:docs
Open docs/index.html in browser to see the demo.
Or serve the dir (with npx and http-server:
1npx http-server ./docs
And open http://127.0.0.1:8080/.
Update emoji-datasource
in package.json
.
Run npm install
to update packages.
Rebuild data with npm run build
.
If needed, update sheet columns in src/utils/emoji-data.js
to reflect emoji-datasource
(usually found here).
Update tests with npm run jest -- -u
, then run tests and prettier (below).
Push changes to GitHub.
Run tests with npm run jest
.
To debug tests, run npm run jest-debug
and then open chrome://inspect
in Chrome and open the node inspector client from there.
Code formatting with prettier: npm run prettier
.
1# Checkout master branch, update version 2git checkout master 3# Edit package.json, update `version` field 4vim package.json 5git add package.json 6 7# Build 8nvm use v20 9NODE_ENV=production npm run build 10npm run dev:docs 11 12# Add build files 13git add dist/ 14git add docs/ 15 16# Commit and push changes. 17git commit -m "Update version to X.Y.Z" 18git push origin HEAD 19 20# Tag the new release (same as package.json version), add the description for tag 21# Hint: refer PRs with #17 (PR id) to later have links to PRs in github releases 22git tag X.Y.Z -a 23 24# Push the tags 25git push origin --tags 26 27# Publish to npm with `npm publish` 28 29## 🎩 Hat tips! 30 31Original react emoji picker: [missive/emoji-mart](https://github.com/missive/emoji-mart). 32Vue port: [jm-david/emoji-mart-vue](https://github.com/jm-david/emoji-mart-vue) 33 34Powered by [iamcal/emoji-data](https://github.com/iamcal/emoji-data) and inspired by [iamcal/js-emoji](https://github.com/iamcal/js-emoji).<br> 35🙌🏼 [Cal Henderson](https://github.com/iamcal).
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 4/13 approved changesets -- score normalized to 3
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
project is not fuzzed
Details
Reason
18 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-01-27
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn Morealispig-emoji-mart-vue-fast
Customizable Slack-like emoji picker for VueJS, fast version
emoji-mart-vue-fast-japanese
Customizable Slack-like emoji picker for VueJS, fast version
@moji.is/emoji-mart-vue-fast
Customizable Slack-like emoji picker for VueJS, fast version
@bitsler/emoji-mart-vue-mini
Customizable Slack-like emoji picker for VueJS, fast version