UNPKG

19.4 kBMarkdownView Raw
1<div align="center">
2 <br><b>Emoji Mart</b> is a Slack-like customizable<br>emoji picker component for React
3 <br><a href="https://missive.github.io/emoji-mart">Demo</a><a href="https://github.com/missive/emoji-mart/blob/master/CHANGELOG.md">Changelog</a>
4 <br><br><a href="https://travis-ci.org/missive/emoji-mart"><img src="https://travis-ci.org/missive/emoji-mart.svg?branch=master" alt="Build Status"></a>
5 <br><br><img width="338" alt="picker" src="https://user-images.githubusercontent.com/436043/43481399-d9b60acc-94d3-11e8-9b3b-e5f2db8f0bd1.png">
6 <br><br><a title="Team email, team chat, team tasks, one app" href="https://missiveapp.com"><img width="30" alt="Missive | Team email, team chat, team tasks, one app" src="https://user-images.githubusercontent.com/436043/32532559-0d15ddfc-c400-11e7-8a24-64d0157d0cb0.png"></a>
7 <br>Brought to you by the <a title="Team email, team chat, team tasks, one app" href="https://missiveapp.com">Missive</a> team
8</div>
9
10## Installation
11
12`npm install --save emoji-mart`
13
14## Components
15### Picker
16```jsx
17import 'emoji-mart/css/emoji-mart.css'
18import { Picker } from 'emoji-mart'
19
20<Picker set='emojione' />
21<Picker onSelect={this.addEmoji} />
22<Picker title='Pick your emoji…' emoji='point_up' />
23<Picker style={{ position: 'absolute', bottom: '20px', right: '20px' }} />
24<Picker i18n={{ search: 'Recherche', categories: { search: 'Résultats de recherche', recent: 'Récents' } }} />
25```
26
27| Prop | Required | Default | Description |
28| ---- | :------: | ------- | ----------- |
29| **autoFocus** | | `false` | Auto focus the search input when mounted |
30| **color** | | `#ae65c5` | The top bar anchors select and hover color |
31| **emoji** | | `department_store` | The emoji shown when no emojis are hovered, set to an empty string to show nothing |
32| **include** | | `[]` | Only load included categories. Accepts [I18n categories keys](#i18n). Order will be respected, except for the `recent` category which will always be the first. |
33| **exclude** | | `[]` | Don't load excluded categories. Accepts [I18n categories keys](#i18n). |
34| **custom** | | `[]` | [Custom emojis](#custom-emojis) |
35| **recent** | | | Pass your own frequently used emojis as array of string IDs |
36| **emojiSize** | | `24` | The emoji width and height |
37| **onClick** | | | Params: `(emoji, event) => {}`. Not called when emoji is selected with `enter` |
38| **onSelect** | | | Params: `(emoji) => {}` |
39| **onSkinChange** | | | Params: `(skin) => {}` |
40| **perLine** | | `9` | Number of emojis per line. While there’s no minimum or maximum, this will affect the picker’s width. This will set *Frequently Used* length as well (`perLine * 4`) |
41| **i18n** | | [`{…}`](#i18n) | [An object](#i18n) containing localized strings |
42| **native** | | `false` | Renders the native unicode emoji |
43| **set** | | `apple` | The emoji set: `'apple', 'google', 'twitter', 'emojione', 'messenger', 'facebook'` |
44| **sheetSize** | | `64` | The emoji [sheet size](#sheet-sizes): `16, 20, 32, 64` |
45| **backgroundImageFn** | | ```((set, sheetSize) => …)``` | A Fn that returns that image sheet to use for emojis. Useful for avoiding a request if you have the sheet locally. |
46| **emojisToShowFilter** | | ```((emoji) => true)``` | A Fn to choose whether an emoji should be displayed or not |
47| **showPreview** | | `true` | Display preview section |
48| **showSkinTones** | | `true` | Display skin tones picker |
49| **emojiTooltip** | | `false` | Show emojis short name when hovering (title) |
50| **skin** | | | Forces skin color: `1, 2, 3, 4, 5, 6` |
51| **defaultSkin** | | `1` | Default skin color: `1, 2, 3, 4, 5, 6` |
52| **skinEmoji** | | | The emoji used to pick a skin tone. Uses an emoji-less skin tone picker by default |
53| **style** | | | Inline styles applied to the root element. Useful for positioning |
54| **title** | | `Emoji Mart™` | The title shown when no emojis are hovered |
55| **notFoundEmoji** | | `sleuth_or_spy` | The emoji shown when there are no search results |
56| **notFound** | | | [Not Found](#not-found) |
57| **icons** | | `{}` | [Custom icons](#custom-icons) |
58
59#### I18n
60```js
61search: 'Search',
62clear: 'Clear', // Accessible label on "clear" button
63notfound: 'No Emoji Found',
64skintext: 'Choose your default skin tone',
65categories: {
66 search: 'Search Results',
67 recent: 'Frequently Used',
68 people: 'Smileys & People',
69 nature: 'Animals & Nature',
70 foods: 'Food & Drink',
71 activity: 'Activity',
72 places: 'Travel & Places',
73 objects: 'Objects',
74 symbols: 'Symbols',
75 flags: 'Flags',
76 custom: 'Custom',
77},
78categorieslabel: 'Emoji categories', // Accessible title for the list of categories
79skintones: {
80 1: 'Default Skin Tone',
81 2: 'Light Skin Tone',
82 3: 'Medium-Light Skin Tone',
83 4: 'Medium Skin Tone',
84 5: 'Medium-Dark Skin Tone',
85 6: 'Dark Skin Tone',
86},
87```
88
89#### Sheet sizes
90Sheets are served from [unpkg](https://unpkg.com), a global CDN that serves files published to [npm](https://www.npmjs.com).
91
92| Set | Size (`sheetSize: 16`) | Size (`sheetSize: 20`) | Size (`sheetSize: 32`) | Size (`sheetSize: 64`) |
93| --------- | ---------------------- | ---------------------- | ---------------------- | ---------------------- |
94| apple | 334 KB | 459 KB | 1.08 MB | 2.94 MB |
95| emojione | 315 KB | 435 KB | 1020 KB | 2.33 MB |
96| facebook | 322 KB | 439 KB | 1020 KB | 2.50 MB |
97| google | 301 KB | 409 KB | 907 KB | 2.17 MB |
98| messenger | 325 KB | 449 KB | 1.05 MB | 2.69 MB |
99| twitter | 288 KB | 389 KB | 839 KB | 1.82 MB |
100
101#### Datasets
102While all sets are available by default, you may want to include only a single set data to reduce the size of your bundle.
103
104| Set | Size (on disk) |
105| --------- | -------------- |
106| all | 570 KB |
107| apple | 484 KB |
108| emojione | 485 KB |
109| facebook | 421 KB |
110| google | 483 KB |
111| messenger | 197 KB |
112| twitter | 484 KB |
113
114To use these data files (or any other custom data), use the `NimblePicker` component:
115
116```js
117import data from 'emoji-mart/data/messenger.json'
118import { NimblePicker } from 'emoji-mart'
119
120<NimblePicker set='messenger' data={data} />
121```
122
123#### Examples of `emoji` object:
124```js
125{
126 id: 'smiley',
127 name: 'Smiling Face with Open Mouth',
128 colons: ':smiley:',
129 text: ':)',
130 emoticons: [
131 '=)',
132 '=-)'
133 ],
134 skin: null,
135 native: '😃'
136}
137
138{
139 id: 'santa',
140 name: 'Father Christmas',
141 colons: ':santa::skin-tone-3:',
142 text: '',
143 emoticons: [],
144 skin: 3,
145 native: '🎅🏼'
146}
147
148{
149 id: 'octocat',
150 name: 'Octocat',
151 colons: ':octocat:',
152 text: '',
153 emoticons: [],
154 custom: true,
155 imageUrl: 'https://github.githubassets.com/images/icons/emoji/octocat.png'
156}
157
158```
159
160### Emoji
161```jsx
162import { Emoji } from 'emoji-mart'
163
164<Emoji emoji={{ id: 'santa', skin: 3 }} size={16} />
165<Emoji emoji=':santa::skin-tone-3:' size={16} />
166<Emoji emoji='santa' set='emojione' size={16} />
167```
168
169| Prop | Required | Default | Description |
170| ---- | :------: | ------- | ----------- |
171| **emoji** | ✓ | | Either a string or an `emoji` object |
172| **size** | ✓ | | The emoji width and height. |
173| **native** | | `false` | Renders the native unicode emoji |
174| **onClick** | | | Params: `(emoji, event) => {}` |
175| **onLeave** | | | Params: `(emoji, event) => {}` |
176| **onOver** | | | Params: `(emoji, event) => {}` |
177| [**fallback**](#unsupported-emojis-fallback) | | | Params: `(emoji, props) => {}` |
178| **set** | | `apple` | The emoji set: `'apple', 'google', 'twitter', 'emojione'` |
179| **sheetSize** | | `64` | The emoji [sheet size](#sheet-sizes): `16, 20, 32, 64` |
180| **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. |
181| **skin** | | `1` | Skin color: `1, 2, 3, 4, 5, 6` |
182| **tooltip** | | `false` | Show emoji short name when hovering (title) |
183| [**html**](#using-with-dangerouslysetinnerhtml) | | `false` | Returns an HTML string to use with `dangerouslySetInnerHTML` |
184
185#### Unsupported emojis fallback
186Certain sets don’t support all emojis (i.e. Messenger & 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.
187
188To have the component render `:shrug:` you would need to:
189
190```js
191<Emoji
192 set={'messenger'}
193 emoji={'shrug'}
194 size={24}
195 fallback={(emoji, props) => {
196 return emoji ? `:${emoji.short_names[0]}:` : props.emoji
197 }}
198/>
199```
200
201#### Using with `dangerouslySetInnerHTML`
202The Emoji component being a [functional component](https://medium.com/missive-app/45-faster-react-functional-components-now-3509a668e69f), you can call it as you would call any function instead of using JSX. Make sure you pass `html: true` for it to return an HTML string.
203
204```js
205<span dangerouslySetInnerHTML={{
206 __html: Emoji({
207 html: true
208 set: 'apple'
209 emoji: '+1'
210 size: 24
211 })
212}}></span>
213```
214
215#### Using with `contentEditable`
216Following the `dangerouslySetInnerHTML` example above, make sure the wrapping `span` sets `contenteditable="false"`.
217
218```js
219<div contentEditable={true}>
220 Looks good to me
221
222 <span contentEditable={false} dangerouslySetInnerHTML={{
223 __html: Emoji({
224 html: true
225 set: 'apple'
226 emoji: '+1'
227 size: 24
228 })
229 }}></span>
230</div>
231```
232
233## Custom emojis
234You can provide custom emojis which will show up in their own category. You can either use a single image as imageUrl or use a spritesheet as shown in the second object.
235
236```js
237import { Picker } from 'emoji-mart'
238
239const customEmojis = [
240 {
241 name: 'Octocat',
242 short_names: ['octocat'],
243 text: '',
244 emoticons: [],
245 keywords: ['github'],
246 imageUrl: 'https://github.githubassets.com/images/icons/emoji/octocat.png'
247 },
248 {
249 name: 'Test Flag',
250 short_names: ['test'],
251 text: '',
252 emoticons: [],
253 keywords: ['test', 'flag'],
254 spriteUrl: 'https://unpkg.com/emoji-datasource-twitter@4.0.4/img/twitter/sheets-256/64.png',
255 sheet_x: 1,
256 sheet_y: 1,
257 size: 64,
258 sheetColumns: 52,
259 sheetRows: 52,
260 },
261]
262
263<Picker custom={customEmojis} />
264```
265
266## Not Found
267You can provide a custom Not Found object which will allow the appearance of the not found search results to change. In this case, we change the default 'sleuth_or_spy' emoji to Octocat when our search finds no results.
268
269```js
270import { Picker } from 'emoji-mart'
271
272const notFound = () => <img src='https://github.githubassets.com/images/icons/emoji/octocat.png' />
273
274<Picker notFound={notFound} />
275```
276
277## Custom icons
278You can provide custom icons which will override the default icons.
279
280```js
281import { Picker } from 'emoji-mart'
282
283const customIcons = {
284 categories: {
285 recent: () => <img src='https://github.githubassets.com/images/icons/emoji/octocat.png' />,
286 foods: () => <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0l6.084 24H8L1.916 0zM21 5h-4l-1-4H4l3 12h3l1 4h13L21 5zM6.563 3h7.875l2 8H8.563l-2-8zm8.832 10l-2.856 1.904L12.063 13h3.332zM19 13l-1.5-6h1.938l2 8H16l3-2z"/></svg>,
287 people: () => <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3 2l10 6-10 6z"></path></svg>
288 }
289}
290
291<Picker icons={customIcons} />
292```
293
294## Headless search
295The `Picker` doesn’t have to be mounted for you to take advantage of the advanced search results.
296
297```js
298import { emojiIndex } from 'emoji-mart'
299
300emojiIndex.search('christmas').map((o) => o.native)
301// => [🎄, 🎅🏼, 🔔, 🎁, ⛄️, ❄️]
302```
303
304## Get emoji data from Native
305You can get emoji data from native emoji unicode using the `getEmojiDataFromNative` util function.
306
307```js
308import { getEmojiDataFromNative, Emoji } from 'emoji-mart'
309import data from 'emoji-mart/data/all.json'
310
311const emojiData = getEmojiDataFromNative('🏊🏽‍♀️', 'apple', data)
312
313<Emoji
314 emoji={emojiData}
315 set={'apple'}
316 skin={emojiData.skin || 1}
317 size={48}
318/>
319```
320
321#### Example of `emojiData` object:
322```js
323emojiData: {
324 "id": "woman-swimming",
325 "name": "Woman Swimming",
326 "colons": ":woman-swimming::skin-tone-4:",
327 "emoticons": [],
328 "unified": "1f3ca-1f3fd-200d-2640-fe0f",
329 "skin": 4,
330 "native": "🏊🏽‍♀️"
331}
332```
333
334### With custom data
335```js
336import data from 'emoji-mart/datasets/messenger'
337import { NimbleEmojiIndex } from 'emoji-mart'
338
339let emojiIndex = new NimbleEmojiIndex(data)
340emojiIndex.search('christmas')
341```
342
343## Storage
344By 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.
345
346```js
347import { store } from 'emoji-mart'
348
349store.setHandlers({
350 getter: (key) => {
351 // Get from your own storage (sync)
352 },
353
354 setter: (key, value) => {
355 // Persist in your own storage (can be async)
356 }
357})
358```
359
360Possible keys are:
361
362| Key | Value | Description |
363| --- | ----- | ----------- |
364| skin | `1, 2, 3, 4, 5, 6` | |
365| frequently | `{ 'astonished': 11, '+1': 22 }` | An object where the key is the emoji name and the value is the usage count |
366| last | 'astonished' | (Optional) Used by `frequently` to be sure the latest clicked emoji will always appear in the “Recent” category |
367
368## Features
369### Powerful search
370#### Short name, name and keywords
371Not only does **Emoji Mart** return more results than most emoji picker, they’re more accurate and sorted by relevance.
372
373<img width="338" alt="summer" src="https://user-images.githubusercontent.com/436043/32532567-179f1be4-c400-11e7-885e-df6e9b52c665.png">
374
375#### Emoticons
376The only emoji picker that returns emojis when searching for emoticons.
377
378<img width="338" alt="emoticons" src="https://user-images.githubusercontent.com/436043/32532570-1be0dd28-c400-11e7-90cd-f33396277602.png">
379
380#### Results intersection
381For better results, **Emoji Mart** split search into words and only returns results matching both terms.
382
383<img width="338" alt="high-five" src="https://user-images.githubusercontent.com/436043/32532573-1f4a9d1e-c400-11e7-8656-921bc6c09732.png">
384
385### Fully customizable
386#### Anchors color, title and default emoji
387<img width="338" alt="customizable-color" src="https://user-images.githubusercontent.com/436043/32532582-302dc9e4-c400-11e7-9b97-f37c447231ca.png"><br><img width="338" alt="pick-your-emoji" src="https://user-images.githubusercontent.com/436043/32532585-34546faa-c400-11e7-9c9d-fbbe830d4368.png">
388
389#### Emojis sizes and length
390<img width="296" alt="size-and-length" src="https://user-images.githubusercontent.com/436043/32532590-381f67de-c400-11e7-86f6-328e30d6b116.png">
391
392#### Default skin color
393As the developer, you have control over which skin color is used by default.
394
395<img width="205" alt="skins" src="https://user-images.githubusercontent.com/436043/32532858-0a559560-c402-11e7-8680-f77f780a5a49.png">
396
397It can however be overwritten as per user preference.
398
399<img width="98" alt="customizable-skin" src="https://user-images.githubusercontent.com/436043/32532883-2c620e7c-c402-11e7-976c-50d32be0566c.png">
400
401#### Multiple sets supported
402Apple / Google / Twitter / EmojiOne / Messenger / Facebook
403
404<img width="214" alt="sets" src="https://user-images.githubusercontent.com/436043/33786868-d4226e60-dc38-11e7-840a-e4cf490f5f4a.png">
405
406## Not opinionated
407**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.
408
409## Usage outside React
410
411**Emoji Mart** can be used with React alternatives such as [Preact](https://preactjs.com/), [Inferno](https://www.infernojs.org/), and [react-lite](https://github.com/Lucifier129/react-lite).
412
413Furthermore, you can use it as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) using [remount](https://github.com/rstacruz/remount), meaning that you can use it within any JavaScript framework (or vanilla JS).
414
415For an end-to-end example of how to do this, see [emoji-mart-outside-react](https://github.com/nolanlawson/emoji-mart-outside-react).
416
417## Optimizing for production
418
419### Modern/ES builds
420
421**Emoji Mart** comes in three flavors:
422
423```
424dist
425dist-es
426dist-modern
427```
428
429- `dist` is the standard build with the highest level of compatibility.
430- `dist-es` is the same, but uses ES modules for better tree-shaking.
431- `dist-modern` removes features not needed in modern evergreen browsers (i.e. latest Chrome, Edge, Firefox, and Safari).
432
433The default builds are `dist` and `dist-es`. (In Webpack, one or the other will be chosen based on your [resolve main fields](https://webpack.js.org/configuration/resolve/#resolve-mainfields).)
434If you want to use `dist-modern`, you must explicitly import it:
435
436```js
437import { Picker } from 'emoji-mart/dist-modern/index.js'
438```
439
440Using something like Babel, you can transpile the modern build to suit your own needs.
441
442### Removing prop-types
443
444To remove [prop-types](https://github.com/facebook/prop-types) in production, use [babel-plugin-transform-react-remove-prop-types](https://github.com/oliviertassinari/babel-plugin-transform-react-remove-prop-types):
445
446```bash
447npm install --save-dev babel-plugin-transform-react-remove-prop-types
448```
449
450Then add to your `.babelrc`:
451
452```json
453"plugins": [
454 [
455 "transform-react-remove-prop-types",
456 {
457 "removeImport": true,
458 "additionalLibraries": [
459 "../../utils/shared-props"
460 ]
461 }
462 ]
463]
464```
465
466You'll also need to ensure that Babel is transpiling `emoji-mart`, e.g. [by not excluding `node_modules` in `babel-loader`](https://github.com/babel/babel-loader#usage).
467
468## Development
469
470```bash
471yarn build
472```
473
474In two separate tabs:
475
476```bash
477yarn start
478yarn storybook
479```
480
481The storybook is hosted at `localhost:6006`, and the code will be built on-the-fly.
482
483## 🎩 Hat tips!
484Powered by [iamcal/emoji-data](https://github.com/iamcal/emoji-data) and inspired by [iamcal/js-emoji](https://github.com/iamcal/js-emoji).<br>
485🙌🏼  [Cal Henderson](https://github.com/iamcal).
486
487<br><br>
488<div align="center">
489 <a title="Team email, team chat, team tasks, one app" href="https://missiveapp.com"><img width="64" alt="Missive | Team email, team chat, team tasks, one app" src="https://user-images.githubusercontent.com/436043/32532559-0d15ddfc-c400-11e7-8a24-64d0157d0cb0.png"></a>
490 <br><a title="Team email, team chat, team tasks, one app" href="https://missiveapp.com">Missive</a> mixes team email and threaded group chat for productive teams.
491 <br>A single app for all your internal and external communication and a full work management solution.
492</div>