Compare commits
76 Commits
Author | SHA1 | Date |
---|---|---|
mashirozx | d496014be7 | |
mashirozx | dac9386e73 | |
mashirozx | 818aba94a0 | |
mashirozx | 7edf171664 | |
Ross Gardiner | fe28ab637b | |
Etienne Lemay | 5912b6b902 | |
Etienne Lemay | 37c3c6267c | |
Erin Hinson | ca6a7fd74b | |
Matt Krick | 612dae7b08 | |
Sagar Jain | 3a97898c5b | |
Sagar Jain | 4f8ef7255a | |
Etienne Lemay | ca3d4e5f0e | |
Etienne Lemay | cd29d5b9f6 | |
Etienne Lemay | 3b6fd1516f | |
Etienne Lemay | 2dacd30dc8 | |
Etienne Lemay | b548c38624 | |
Etienne Lemay | d1138c00e8 | |
Etienne Lemay | c41fc5ec7a | |
Etienne Lemay | 0e299ff4dd | |
Etienne Lemay | 17cf50f7ba | |
Etienne Lemay | 22ffd5b85e | |
Etienne Lemay | b8fad36c6d | |
Etienne Lemay | 56ae7b49c5 | |
SaraRandolph | 6ca158bb36 | |
SaraRandolph | cdb6c26a08 | |
Etienne Lemay | 769b55c875 | |
Etienne Lemay | dc4ca683d2 | |
Etienne Lemay | 16ca493f3c | |
Etienne Lemay | cf4a1043f7 | |
Etienne Lemay | 5c083a8026 | |
Etienne Lemay | f8ce5a6814 | |
Etienne Lemay | fcae7a913b | |
Thomas Piard | 57cabf6f75 | |
Thomas Piard | 9bab24f3c6 | |
Thomas Piard | 4404e71264 | |
Thomas Piard | 3941549f6a | |
Thomas Piard | a253148b86 | |
Thomas Piard | cdb74f28c7 | |
Etienne Lemay | 113b07abcf | |
Etienne Lemay | bfada8f5c1 | |
Etienne Lemay | 39c2c9d6ee | |
rugk | e57118c6f3 | |
Nolan Lawson | 835c2e9c36 | |
Nolan Lawson | c8305f6013 | |
Nolan Lawson | 97f6ffde2d | |
Nolan Lawson | 0bd369144b | |
Nolan Lawson | 99eae3605d | |
Nolan Lawson | 6bb1932db8 | |
Etienne Lemay | 85577c0b58 | |
Etienne Lemay | 7b2f760df2 | |
Etienne Lemay | 3440a74328 | |
Etienne Lemay | f1a988ca4b | |
Etienne Lemay | 2860851c0b | |
Etienne Lemay | e66be9dc4e | |
Etienne Lemay | e39c1e53d8 | |
Etienne Lemay | c778bc6084 | |
Etienne Lemay | ff9d416300 | |
Nolan Lawson | 61c0bd4e4e | |
Nolan Lawson | 7a025243b4 | |
Eugen Rochko | 1a9d5f97b6 | |
Nolan Lawson | 8cff39f6fd | |
Mohan Raj | 848fc76396 | |
dependabot[bot] | 830c69a4e1 | |
dependabot[bot] | 1b69530f53 | |
dependabot[bot] | 6c60ac1242 | |
dependabot[bot] | 364ae72ba3 | |
Carl Tessier | f3387cdce2 | |
Peder Johnsen | edcd64b101 | |
Hiro-Aki Hotta | 208099c2dc | |
Ryan McCue | f10510b262 | |
Alex Brioux | 76ac008169 | |
Nolan Lawson | 3576091fc0 | |
Xavier Shay | 956aaa91f3 | |
Nolan Lawson | a0ce9d8122 | |
Nolan Lawson | cdd3229de6 | |
rugk | f8322a8c5d |
66
.babelrc
66
.babelrc
|
@ -1,66 +0,0 @@
|
||||||
{
|
|
||||||
"presets": ["react"],
|
|
||||||
"plugins": [
|
|
||||||
"check-es2015-constants",
|
|
||||||
"transform-object-rest-spread",
|
|
||||||
"transform-runtime",
|
|
||||||
[
|
|
||||||
"module-resolver",
|
|
||||||
{
|
|
||||||
"alias": {
|
|
||||||
"babel-runtime/core-js/object/get-prototype-of": "./src/polyfills/objectGetPrototypeOf",
|
|
||||||
"babel-runtime/helpers/extends": "./src/polyfills/extends",
|
|
||||||
"babel-runtime/helpers/inherits": "./src/polyfills/inherits",
|
|
||||||
"babel-runtime/helpers/createClass": "./src/polyfills/createClass",
|
|
||||||
"babel-runtime/helpers/possibleConstructorReturn": "./src/polyfills/possibleConstructorReturn",
|
|
||||||
"babel-runtime/helpers/classCallCheck": "./src/polyfills/classCallCheck",
|
|
||||||
"babel-runtime/core-js/object/keys": "./src/polyfills/keys"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"transform-define", "scripts/define.js"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"legacy-es": {
|
|
||||||
"plugins": [
|
|
||||||
"transform-es2015-arrow-functions",
|
|
||||||
"transform-es2015-block-scoped-functions",
|
|
||||||
"transform-es2015-block-scoping",
|
|
||||||
"transform-es2015-classes",
|
|
||||||
"transform-es2015-computed-properties",
|
|
||||||
"transform-es2015-destructuring",
|
|
||||||
"transform-es2015-duplicate-keys",
|
|
||||||
"transform-es2015-for-of",
|
|
||||||
"transform-es2015-function-name",
|
|
||||||
"transform-es2015-literals",
|
|
||||||
"transform-es2015-object-super",
|
|
||||||
"transform-es2015-parameters",
|
|
||||||
"transform-es2015-shorthand-properties",
|
|
||||||
"transform-es2015-spread",
|
|
||||||
"transform-es2015-sticky-regex",
|
|
||||||
"transform-es2015-template-literals",
|
|
||||||
"transform-es2015-unicode-regex",
|
|
||||||
"transform-regenerator"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"legacy-cjs": {
|
|
||||||
"plugins": [
|
|
||||||
"transform-es2015-modules-commonjs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"test": {
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"env",
|
|
||||||
{
|
|
||||||
"targets": {
|
|
||||||
"node": "current"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
*.md
|
||||||
|
*.css
|
|
@ -5,6 +5,8 @@ sudo: false
|
||||||
script: yarn test
|
script: yarn test
|
||||||
before_script:
|
before_script:
|
||||||
- yarn prettier:check
|
- yarn prettier:check
|
||||||
|
- yarn test:size
|
||||||
|
- yarn test:ssr
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
|
61
CHANGELOG.md
61
CHANGELOG.md
|
@ -1,8 +1,63 @@
|
||||||
### Changelog
|
### Changelog
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
#### [v3.0.1](https://github.com/missive/emoji-mart/compare/v3.0.0...v3.0.1)
|
||||||
|
|
||||||
|
> February 24 2021
|
||||||
|
|
||||||
|
##### Fixes 🐛
|
||||||
|
- Safely access search input #419
|
||||||
|
- Custom category aria-label #480
|
||||||
|
|
||||||
|
##### Chores 🧹
|
||||||
|
- React v17 support #475
|
||||||
|
|
||||||
|
#### [v3.0.0](https://github.com/missive/emoji-mart/compare/v2.11.2...v3.0.0)
|
||||||
|
|
||||||
|
> March 16 2020
|
||||||
|
|
||||||
|
##### New 🎉
|
||||||
|
- [Emoji 12.1](https://emojipedia.org/emoji-12.1) 👩🦳👨🦰🦾 [`#411`](https://github.com/missive/emoji-mart/pull/411)
|
||||||
|
- Option to disable use of `<button>` in Picker [`17cf50f`](https://github.com/missive/emoji-mart/commit/17cf50f7bafbbd2dbff9cabe0737e457a8aa1e72)
|
||||||
|
|
||||||
|
##### Breaking 🚨
|
||||||
|
- As part of the Emoji 12.1 support and the upgrade of our data provider, `emojione` is no longer available [`emoji-data/142`](https://github.com/iamcal/emoji-data/pull/142)
|
||||||
|
- `messenger` has been removed. Facebook has unified their emojis and is no longer mainting a different set for Messenger. Use `facebook` instead [`emoji-data/165#issuecomment-572795078`](https://github.com/iamcal/emoji-data/pull/165#issuecomment-572795078)
|
||||||
|
- `darkMode` Picker prop superseded by `theme`. Defaults to `light` [`d1138c0`](https://github.com/missive/emoji-mart/commit/d1138c00e8d2e79c990ea75b89aaea4c7e819c7b)
|
||||||
|
- No more auto-sorting of the “Frequently used” category. Use `enableFrequentEmojiSort` to enable [`#417`](https://github.com/missive/emoji-mart/pull/417)
|
||||||
|
|
||||||
|
##### Fixes 🐛
|
||||||
|
- Horizontal scoll overflow [`#410`](https://github.com/missive/emoji-mart/pull/410)
|
||||||
|
|
||||||
|
##### Chores 🧹
|
||||||
|
- Remove core-js dependency [`#394`](https://github.com/missive/emoji-mart/pull/394)
|
||||||
|
- Upgrade to Babel V7 [`#397`](https://github.com/missive/emoji-mart/pull/397)
|
||||||
|
- Remove _JSON hack [`#401`](https://github.com/missive/emoji-mart/pull/401)
|
||||||
|
- Remove rAF polyfill [`#402`](https://github.com/missive/emoji-mart/pull/402)
|
||||||
|
|
||||||
|
#### [v2.11.2](https://github.com/missive/emoji-mart/compare/v2.11.1...v2.11.2)
|
||||||
|
|
||||||
|
> 23 December 2019
|
||||||
|
|
||||||
|
- chore(deps): bump lodash from 4.17.11 to 4.17.15 [`#390`](https://github.com/missive/emoji-mart/pull/390)
|
||||||
|
- chore(deps): bump handlebars from 4.1.0 to 4.5.3 [`#389`](https://github.com/missive/emoji-mart/pull/389)
|
||||||
|
- chore(deps): bump lodash-es from 4.17.11 to 4.17.15 [`#388`](https://github.com/missive/emoji-mart/pull/388)
|
||||||
|
- chore(deps): bump mixin-deep from 1.3.1 to 1.3.2 [`#387`](https://github.com/missive/emoji-mart/pull/387)
|
||||||
|
- fix: gracefully ignore bad JSON in localstorage [`#385`](https://github.com/missive/emoji-mart/pull/385)
|
||||||
|
- docs: Move `With custom data` to correct position [`#377`](https://github.com/missive/emoji-mart/pull/377)
|
||||||
|
- fix: Use getDerivedStateFromProps instead of componentWillReceiveProps [`#372`](https://github.com/missive/emoji-mart/pull/372)
|
||||||
|
- fix: Ensure emoji backgrounds do not tile [`#362`](https://github.com/missive/emoji-mart/pull/362)
|
||||||
|
- Fix: Allowing emoji selection on enter [`#386`](https://github.com/missive/emoji-mart/pull/386)
|
||||||
|
- fix: ensure unique keys for React list [`#352`](https://github.com/missive/emoji-mart/pull/352)
|
||||||
|
- fix: Deterministic sorting of search results. [`#343`](https://github.com/missive/emoji-mart/pull/343)
|
||||||
|
- docs: document how to remove the footer [`#330`](https://github.com/missive/emoji-mart/pull/330)
|
||||||
|
- test: add basic skins test [`#315`](https://github.com/missive/emoji-mart/pull/315)
|
||||||
|
- docs: Add tip for l10n to use CLDR [`#344`](https://github.com/missive/emoji-mart/pull/344)
|
||||||
|
- Add support for more than one custom category [`#224`](https://github.com/missive/emoji-mart/issues/224)
|
||||||
|
- Update gh-pages [`ff9d416`](https://github.com/missive/emoji-mart/commit/ff9d416300e30a6bb14262066cb1a63f9790c336)
|
||||||
|
- Add theme selection to gh-pages [`e66be9d`](https://github.com/missive/emoji-mart/commit/e66be9dc4efb753b26ecaaf8583392e83c933b9c)
|
||||||
|
- fix: dark mode CSS tweaks, add storybook/matchMedia/docs [`8cff39f`](https://github.com/missive/emoji-mart/commit/8cff39f6fd7add3a15ba7695bc117fe4794d3688)
|
||||||
|
|
||||||
#### [v2.11.1](https://github.com/missive/emoji-mart/compare/v2.11.0...v2.11.1)
|
#### [v2.11.1](https://github.com/missive/emoji-mart/compare/v2.11.0...v2.11.1)
|
||||||
|
|
||||||
|
@ -10,8 +65,8 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||||
|
|
||||||
- Added `type={"button"}` to anchors.js [`#338`](https://github.com/missive/emoji-mart/pull/338)
|
- Added `type={"button"}` to anchors.js [`#338`](https://github.com/missive/emoji-mart/pull/338)
|
||||||
- Update gh-pages [`f654ef4`](https://github.com/missive/emoji-mart/commit/f654ef4050dd8fe4e06af96818bbddebcf8c4650)
|
- Update gh-pages [`f654ef4`](https://github.com/missive/emoji-mart/commit/f654ef4050dd8fe4e06af96818bbddebcf8c4650)
|
||||||
|
- Release v2.11.1 [`ae24948`](https://github.com/missive/emoji-mart/commit/ae24948861119f4cd366ad9432f74afff5cfddff)
|
||||||
- attempt 2 to fix prettier error [`af37a7a`](https://github.com/missive/emoji-mart/commit/af37a7a20f66f172ef6f8e75dbcd59d36a91df05)
|
- attempt 2 to fix prettier error [`af37a7a`](https://github.com/missive/emoji-mart/commit/af37a7a20f66f172ef6f8e75dbcd59d36a91df05)
|
||||||
- attempting to fix the prettier issue [`14c5d4f`](https://github.com/missive/emoji-mart/commit/14c5d4f2b42fc2749de7f670133a160cbfb537fd)
|
|
||||||
|
|
||||||
#### [v2.11.0](https://github.com/missive/emoji-mart/compare/v2.10.0...v2.11.0)
|
#### [v2.11.0](https://github.com/missive/emoji-mart/compare/v2.10.0...v2.11.0)
|
||||||
|
|
||||||
|
|
76
README.md
76
README.md
|
@ -2,7 +2,7 @@
|
||||||
<br><b>Emoji Mart</b> is a Slack-like customizable<br>emoji picker component for React
|
<br><b>Emoji Mart</b> is a Slack-like customizable<br>emoji picker component for React
|
||||||
<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>
|
<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>
|
||||||
<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>
|
<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>
|
||||||
<br><br><img width="338" alt="picker" src="https://user-images.githubusercontent.com/436043/43481399-d9b60acc-94d3-11e8-9b3b-e5f2db8f0bd1.png">
|
<br><br><img width="420" alt="picker" src="https://user-images.githubusercontent.com/436043/71363432-1b69d000-2567-11ea-9416-88446025e03c.png">
|
||||||
<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>
|
<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>
|
||||||
<br>Brought to you by the <a title="Team email, team chat, team tasks, one app" href="https://missiveapp.com">Missive</a> team
|
<br>Brought to you by the <a title="Team email, team chat, team tasks, one app" href="https://missiveapp.com">Missive</a> team
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
import 'emoji-mart/css/emoji-mart.css'
|
import 'emoji-mart/css/emoji-mart.css'
|
||||||
import { Picker } from 'emoji-mart'
|
import { Picker } from 'emoji-mart'
|
||||||
|
|
||||||
<Picker set='emojione' />
|
<Picker set='apple' />
|
||||||
<Picker onSelect={this.addEmoji} />
|
<Picker onSelect={this.addEmoji} />
|
||||||
<Picker title='Pick your emoji…' emoji='point_up' />
|
<Picker title='Pick your emoji…' emoji='point_up' />
|
||||||
<Picker style={{ position: 'absolute', bottom: '20px', right: '20px' }} />
|
<Picker style={{ position: 'absolute', bottom: '20px', right: '20px' }} />
|
||||||
|
@ -33,6 +33,7 @@ import { Picker } from 'emoji-mart'
|
||||||
| **exclude** | | `[]` | Don't load excluded categories. Accepts [I18n categories keys](#i18n). |
|
| **exclude** | | `[]` | Don't load excluded categories. Accepts [I18n categories keys](#i18n). |
|
||||||
| **custom** | | `[]` | [Custom emojis](#custom-emojis) |
|
| **custom** | | `[]` | [Custom emojis](#custom-emojis) |
|
||||||
| **recent** | | | Pass your own frequently used emojis as array of string IDs |
|
| **recent** | | | Pass your own frequently used emojis as array of string IDs |
|
||||||
|
| **enableFrequentEmojiSort** | | `false` | Instantly sort “Frequently Used” category |
|
||||||
| **emojiSize** | | `24` | The emoji width and height |
|
| **emojiSize** | | `24` | The emoji width and height |
|
||||||
| **onClick** | | | Params: `(emoji, event) => {}`. Not called when emoji is selected with `enter` |
|
| **onClick** | | | Params: `(emoji, event) => {}`. Not called when emoji is selected with `enter` |
|
||||||
| **onSelect** | | | Params: `(emoji) => {}` |
|
| **onSelect** | | | Params: `(emoji) => {}` |
|
||||||
|
@ -40,13 +41,15 @@ import { Picker } from 'emoji-mart'
|
||||||
| **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`) |
|
| **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`) |
|
||||||
| **i18n** | | [`{…}`](#i18n) | [An object](#i18n) containing localized strings |
|
| **i18n** | | [`{…}`](#i18n) | [An object](#i18n) containing localized strings |
|
||||||
| **native** | | `false` | Renders the native unicode emoji |
|
| **native** | | `false` | Renders the native unicode emoji |
|
||||||
| **set** | | `apple` | The emoji set: `'apple', 'google', 'twitter', 'emojione', 'messenger', 'facebook'` |
|
| **set** | | `apple` | The emoji set: `'apple', 'google', 'twitter', 'facebook'` |
|
||||||
|
| **theme** | | `light` | The picker theme: `'auto', 'light', 'dark'` |
|
||||||
| **sheetSize** | | `64` | The emoji [sheet size](#sheet-sizes): `16, 20, 32, 64` |
|
| **sheetSize** | | `64` | The emoji [sheet size](#sheet-sizes): `16, 20, 32, 64` |
|
||||||
| **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. |
|
| **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. |
|
||||||
| **emojisToShowFilter** | | ```((emoji) => true)``` | A Fn to choose whether an emoji should be displayed or not |
|
| **emojisToShowFilter** | | ```((emoji) => true)``` | A Fn to choose whether an emoji should be displayed or not |
|
||||||
| **showPreview** | | `true` | Display preview section |
|
| **showPreview** | | `true` | Display preview section |
|
||||||
| **showSkinTones** | | `true` | Display skin tones picker |
|
| **showSkinTones** | | `true` | Display skin tones picker. Disable both this and `showPreview` to remove the footer entirely. |
|
||||||
| **emojiTooltip** | | `false` | Show emojis short name when hovering (title) |
|
| **emojiTooltip** | | `false` | Show emojis short name when hovering (title) |
|
||||||
|
| **useButton** | | `true` | When clickable, render emojis with a `<button>`. Some browsers have issues rendering certain emojis on a button, so you might want to disable this. It is better for accessibility to use buttons. |
|
||||||
| **skin** | | | Forces skin color: `1, 2, 3, 4, 5, 6` |
|
| **skin** | | | Forces skin color: `1, 2, 3, 4, 5, 6` |
|
||||||
| **defaultSkin** | | `1` | Default skin color: `1, 2, 3, 4, 5, 6` |
|
| **defaultSkin** | | `1` | Default skin color: `1, 2, 3, 4, 5, 6` |
|
||||||
| **skinEmoji** | | | The emoji used to pick a skin tone. Uses an emoji-less skin tone picker by default |
|
| **skinEmoji** | | | The emoji used to pick a skin tone. Uses an emoji-less skin tone picker by default |
|
||||||
|
@ -65,7 +68,8 @@ skintext: 'Choose your default skin tone',
|
||||||
categories: {
|
categories: {
|
||||||
search: 'Search Results',
|
search: 'Search Results',
|
||||||
recent: 'Frequently Used',
|
recent: 'Frequently Used',
|
||||||
people: 'Smileys & People',
|
smileys: 'Smileys & Emotion',
|
||||||
|
people: 'People & Body',
|
||||||
nature: 'Animals & Nature',
|
nature: 'Animals & Nature',
|
||||||
foods: 'Food & Drink',
|
foods: 'Food & Drink',
|
||||||
activity: 'Activity',
|
activity: 'Activity',
|
||||||
|
@ -86,38 +90,36 @@ skintones: {
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Tip:** You usually do not need to translate the categories and skin tones by youself, because this data and their translations [should be included in the Unicode CLDR](http://cldr.unicode.org/) (the ["Common Locale Data Repository"](https://en.wikipedia.org/wiki/Common_Locale_Data_Repository)). You can look them up and just take them from there.
|
||||||
|
|
||||||
#### Sheet sizes
|
#### Sheet sizes
|
||||||
Sheets are served from [unpkg](https://unpkg.com), a global CDN that serves files published to [npm](https://www.npmjs.com).
|
Sheets are served from [unpkg](https://unpkg.com), a global CDN that serves files published to [npm](https://www.npmjs.com).
|
||||||
|
|
||||||
| Set | Size (`sheetSize: 16`) | Size (`sheetSize: 20`) | Size (`sheetSize: 32`) | Size (`sheetSize: 64`) |
|
| Set | Size (`sheetSize: 16`) | Size (`sheetSize: 20`) | Size (`sheetSize: 32`) | Size (`sheetSize: 64`) |
|
||||||
| --------- | ---------------------- | ---------------------- | ---------------------- | ---------------------- |
|
| --------- | ---------------------- | ---------------------- | ---------------------- | ---------------------- |
|
||||||
| apple | 334 KB | 459 KB | 1.08 MB | 2.94 MB |
|
| apple | 407 KB | 561 KB | 1.34 MB | 3.60 MB |
|
||||||
| emojione | 315 KB | 435 KB | 1020 KB | 2.33 MB |
|
| facebook | 416 KB | 579 KB | 1.38 MB | 3.68 MB |
|
||||||
| facebook | 322 KB | 439 KB | 1020 KB | 2.50 MB |
|
| google | 362 KB | 489 KB | 1.12 MB | 2.78 MB |
|
||||||
| google | 301 KB | 409 KB | 907 KB | 2.17 MB |
|
| twitter | 361 KB | 485 KB | 1.05 MB | 2.39 MB |
|
||||||
| messenger | 325 KB | 449 KB | 1.05 MB | 2.69 MB |
|
|
||||||
| twitter | 288 KB | 389 KB | 839 KB | 1.82 MB |
|
|
||||||
|
|
||||||
#### Datasets
|
#### Datasets
|
||||||
While all sets are available by default, you may want to include only a single set data to reduce the size of your bundle.
|
While all sets are available by default, you may want to include only a single set data to reduce the size of your bundle.
|
||||||
|
|
||||||
| Set | Size (on disk) |
|
| Set | Size (on disk) |
|
||||||
| --------- | -------------- |
|
| --------- | -------------- |
|
||||||
| all | 570 KB |
|
| all | 611 KB |
|
||||||
| apple | 484 KB |
|
| apple | 548 KB |
|
||||||
| emojione | 485 KB |
|
| facebook | 468 KB |
|
||||||
| facebook | 421 KB |
|
| google | 518 KB |
|
||||||
| google | 483 KB |
|
| twitter | 517 KB |
|
||||||
| messenger | 197 KB |
|
|
||||||
| twitter | 484 KB |
|
|
||||||
|
|
||||||
To use these data files (or any other custom data), use the `NimblePicker` component:
|
To use these data files (or any other custom data), use the `NimblePicker` component:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import data from 'emoji-mart/data/messenger.json'
|
import data from 'emoji-mart/data/google.json'
|
||||||
import { NimblePicker } from 'emoji-mart'
|
import { NimblePicker } from 'emoji-mart'
|
||||||
|
|
||||||
<NimblePicker set='messenger' data={data} />
|
<NimblePicker set='google' data={data} />
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Examples of `emoji` object:
|
#### Examples of `emoji` object:
|
||||||
|
@ -163,7 +165,7 @@ import { Emoji } from 'emoji-mart'
|
||||||
|
|
||||||
<Emoji emoji={{ id: 'santa', skin: 3 }} size={16} />
|
<Emoji emoji={{ id: 'santa', skin: 3 }} size={16} />
|
||||||
<Emoji emoji=':santa::skin-tone-3:' size={16} />
|
<Emoji emoji=':santa::skin-tone-3:' size={16} />
|
||||||
<Emoji emoji='santa' set='emojione' size={16} />
|
<Emoji emoji='santa' set='apple' size={16} />
|
||||||
```
|
```
|
||||||
|
|
||||||
| Prop | Required | Default | Description |
|
| Prop | Required | Default | Description |
|
||||||
|
@ -175,7 +177,7 @@ import { Emoji } from 'emoji-mart'
|
||||||
| **onLeave** | | | Params: `(emoji, event) => {}` |
|
| **onLeave** | | | Params: `(emoji, event) => {}` |
|
||||||
| **onOver** | | | Params: `(emoji, event) => {}` |
|
| **onOver** | | | Params: `(emoji, event) => {}` |
|
||||||
| [**fallback**](#unsupported-emojis-fallback) | | | Params: `(emoji, props) => {}` |
|
| [**fallback**](#unsupported-emojis-fallback) | | | Params: `(emoji, props) => {}` |
|
||||||
| **set** | | `apple` | The emoji set: `'apple', 'google', 'twitter', 'emojione'` |
|
| **set** | | `apple` | The emoji set: `'apple', 'google', 'twitter'` |
|
||||||
| **sheetSize** | | `64` | The emoji [sheet size](#sheet-sizes): `16, 20, 32, 64` |
|
| **sheetSize** | | `64` | The emoji [sheet size](#sheet-sizes): `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. |
|
| **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` |
|
| **skin** | | `1` | Skin color: `1, 2, 3, 4, 5, 6` |
|
||||||
|
@ -183,13 +185,13 @@ import { Emoji } from 'emoji-mart'
|
||||||
| [**html**](#using-with-dangerouslysetinnerhtml) | | `false` | Returns an HTML string to use with `dangerouslySetInnerHTML` |
|
| [**html**](#using-with-dangerouslysetinnerhtml) | | `false` | Returns an HTML string to use with `dangerouslySetInnerHTML` |
|
||||||
|
|
||||||
#### Unsupported emojis fallback
|
#### Unsupported emojis fallback
|
||||||
Certain 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.
|
Certain sets don’t support all emojis. 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:
|
To have the component render `:shrug:` you would need to:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
<Emoji
|
<Emoji
|
||||||
set={'messenger'}
|
set={'apple'}
|
||||||
emoji={'shrug'}
|
emoji={'shrug'}
|
||||||
size={24}
|
size={24}
|
||||||
fallback={(emoji, props) => {
|
fallback={(emoji, props) => {
|
||||||
|
@ -243,7 +245,8 @@ const customEmojis = [
|
||||||
text: '',
|
text: '',
|
||||||
emoticons: [],
|
emoticons: [],
|
||||||
keywords: ['github'],
|
keywords: ['github'],
|
||||||
imageUrl: 'https://github.githubassets.com/images/icons/emoji/octocat.png'
|
imageUrl: 'https://github.githubassets.com/images/icons/emoji/octocat.png',
|
||||||
|
customCategory: 'GitHub'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Test Flag',
|
name: 'Test Flag',
|
||||||
|
@ -263,6 +266,9 @@ const customEmojis = [
|
||||||
<Picker custom={customEmojis} />
|
<Picker custom={customEmojis} />
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The `customCategory` string is optional. If you include it, then the custom emoji will be shown in whatever
|
||||||
|
categories you define. If you don't include it, then there will just be one category called "Custom."
|
||||||
|
|
||||||
## Not Found
|
## Not Found
|
||||||
You 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.
|
You 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.
|
||||||
|
|
||||||
|
@ -301,6 +307,15 @@ emojiIndex.search('christmas').map((o) => o.native)
|
||||||
// => [🎄, 🎅🏼, 🔔, 🎁, ⛄️, ❄️]
|
// => [🎄, 🎅🏼, 🔔, 🎁, ⛄️, ❄️]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### With custom data
|
||||||
|
```js
|
||||||
|
import data from 'emoji-mart/datasets/apple'
|
||||||
|
import { NimbleEmojiIndex } from 'emoji-mart'
|
||||||
|
|
||||||
|
let emojiIndex = new NimbleEmojiIndex(data)
|
||||||
|
emojiIndex.search('christmas')
|
||||||
|
```
|
||||||
|
|
||||||
## Get emoji data from Native
|
## Get emoji data from Native
|
||||||
You can get emoji data from native emoji unicode using the `getEmojiDataFromNative` util function.
|
You can get emoji data from native emoji unicode using the `getEmojiDataFromNative` util function.
|
||||||
|
|
||||||
|
@ -331,15 +346,6 @@ emojiData: {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### With custom data
|
|
||||||
```js
|
|
||||||
import data from 'emoji-mart/datasets/messenger'
|
|
||||||
import { NimbleEmojiIndex } from 'emoji-mart'
|
|
||||||
|
|
||||||
let emojiIndex = new NimbleEmojiIndex(data)
|
|
||||||
emojiIndex.search('christmas')
|
|
||||||
```
|
|
||||||
|
|
||||||
## Storage
|
## Storage
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
@ -399,7 +405,7 @@ It can however be overwritten as per user preference.
|
||||||
<img width="98" alt="customizable-skin" src="https://user-images.githubusercontent.com/436043/32532883-2c620e7c-c402-11e7-976c-50d32be0566c.png">
|
<img width="98" alt="customizable-skin" src="https://user-images.githubusercontent.com/436043/32532883-2c620e7c-c402-11e7-976c-50d32be0566c.png">
|
||||||
|
|
||||||
#### Multiple sets supported
|
#### Multiple sets supported
|
||||||
Apple / Google / Twitter / EmojiOne / Messenger / Facebook
|
Apple / Google / Twitter / Facebook
|
||||||
|
|
||||||
<img width="214" alt="sets" src="https://user-images.githubusercontent.com/436043/33786868-d4226e60-dc38-11e7-840a-e4cf490f5f4a.png">
|
<img width="214" alt="sets" src="https://user-images.githubusercontent.com/436043/33786868-d4226e60-dc38-11e7-840a-e4cf490f5f4a.png">
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
const { devDependencies } = require('./package.json')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
presets: ['@babel/preset-react'],
|
||||||
|
plugins: [
|
||||||
|
'@babel/plugin-transform-runtime',
|
||||||
|
[
|
||||||
|
'babel-plugin-transform-define',
|
||||||
|
{
|
||||||
|
'process.env.NODE_ENV': 'production',
|
||||||
|
EMOJI_DATASOURCE_VERSION: devDependencies['emoji-datasource'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
env: {
|
||||||
|
'legacy-es': {
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
modules: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'legacy-cjs': {
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
modules: 'cjs',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
modern: {
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
targets: {
|
||||||
|
chrome: '77',
|
||||||
|
edge: '18',
|
||||||
|
firefox: '71',
|
||||||
|
safari: '13',
|
||||||
|
},
|
||||||
|
modules: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
targets: {
|
||||||
|
node: 'current',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
|
@ -37,7 +37,6 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
color: #858585;
|
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +44,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
color: #858585;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 12px 4px;
|
padding: 12px 4px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -54,7 +54,9 @@
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
.emoji-mart-anchor:focus { outline: 0 }
|
||||||
.emoji-mart-anchor:hover,
|
.emoji-mart-anchor:hover,
|
||||||
|
.emoji-mart-anchor:focus,
|
||||||
.emoji-mart-anchor-selected {
|
.emoji-mart-anchor-selected {
|
||||||
color: #464646;
|
color: #464646;
|
||||||
}
|
}
|
||||||
|
@ -78,13 +80,14 @@
|
||||||
|
|
||||||
.emoji-mart-anchors svg,
|
.emoji-mart-anchors svg,
|
||||||
.emoji-mart-anchors img {
|
.emoji-mart-anchors img {
|
||||||
fill: #858585;
|
fill: currentColor;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-mart-scroll {
|
.emoji-mart-scroll {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
height: 270px;
|
height: 270px;
|
||||||
padding: 0 6px 6px 6px;
|
padding: 0 6px 6px 6px;
|
||||||
will-change: transform; /* avoids "repaints on scroll" in mobile Chrome */
|
will-change: transform; /* avoids "repaints on scroll" in mobile Chrome */
|
||||||
|
@ -134,7 +137,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-mart-category .emoji-mart-emoji:hover:before {
|
.emoji-mart-category .emoji-mart-emoji:hover:before {
|
||||||
z-index: 0;
|
z-index: -1;
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0; left: 0;
|
top: 0; left: 0;
|
||||||
|
@ -184,7 +187,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-mart-emoji-native {
|
.emoji-mart-emoji-native {
|
||||||
font-family: "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "EmojiOne Color", "Android Emoji";
|
font-family: "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "Android Emoji";
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-mart-no-results {
|
.emoji-mart-no-results {
|
||||||
|
@ -413,4 +416,46 @@
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dark mode styles
|
||||||
|
*/
|
||||||
|
|
||||||
|
.emoji-mart-dark {
|
||||||
|
color: #fff;
|
||||||
|
border-color: #555453;
|
||||||
|
background-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-bar {
|
||||||
|
border-color: #555453;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-search input {
|
||||||
|
color: #fff;
|
||||||
|
border-color: #555453;
|
||||||
|
background-color: #2f2f2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-search-icon svg {
|
||||||
|
fill: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-category .emoji-mart-emoji:hover:before {
|
||||||
|
background-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-category-label span {
|
||||||
|
background-color: #222;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-skin-swatches {
|
||||||
|
border-color: #555453;
|
||||||
|
background-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-anchor:hover,
|
||||||
|
.emoji-mart-dark .emoji-mart-anchor:focus,
|
||||||
|
.emoji-mart-dark .emoji-mart-anchor-selected {
|
||||||
|
color: #bfbfbf;
|
||||||
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
5283
docs/bundle.js
5283
docs/bundle.js
File diff suppressed because one or more lines are too long
|
@ -37,7 +37,6 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
color: #858585;
|
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +44,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
color: #858585;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 12px 4px;
|
padding: 12px 4px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -54,7 +54,9 @@
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
.emoji-mart-anchor:focus { outline: 0 }
|
||||||
.emoji-mart-anchor:hover,
|
.emoji-mart-anchor:hover,
|
||||||
|
.emoji-mart-anchor:focus,
|
||||||
.emoji-mart-anchor-selected {
|
.emoji-mart-anchor-selected {
|
||||||
color: #464646;
|
color: #464646;
|
||||||
}
|
}
|
||||||
|
@ -78,13 +80,14 @@
|
||||||
|
|
||||||
.emoji-mart-anchors svg,
|
.emoji-mart-anchors svg,
|
||||||
.emoji-mart-anchors img {
|
.emoji-mart-anchors img {
|
||||||
fill: #858585;
|
fill: currentColor;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-mart-scroll {
|
.emoji-mart-scroll {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
height: 270px;
|
height: 270px;
|
||||||
padding: 0 6px 6px 6px;
|
padding: 0 6px 6px 6px;
|
||||||
will-change: transform; /* avoids "repaints on scroll" in mobile Chrome */
|
will-change: transform; /* avoids "repaints on scroll" in mobile Chrome */
|
||||||
|
@ -184,7 +187,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-mart-emoji-native {
|
.emoji-mart-emoji-native {
|
||||||
font-family: "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "EmojiOne Color", "Android Emoji";
|
font-family: "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "Android Emoji";
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-mart-no-results {
|
.emoji-mart-no-results {
|
||||||
|
@ -413,4 +416,46 @@
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dark mode styles
|
||||||
|
*/
|
||||||
|
|
||||||
|
.emoji-mart-dark {
|
||||||
|
color: #fff;
|
||||||
|
border-color: #555453;
|
||||||
|
background-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-bar {
|
||||||
|
border-color: #555453;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-search input {
|
||||||
|
color: #fff;
|
||||||
|
border-color: #555453;
|
||||||
|
background-color: #2f2f2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-search-icon svg {
|
||||||
|
fill: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-category .emoji-mart-emoji:hover:before {
|
||||||
|
background-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-category-label span {
|
||||||
|
background-color: #222;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-skin-swatches {
|
||||||
|
border-color: #555453;
|
||||||
|
background-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-mart-dark .emoji-mart-anchor:hover,
|
||||||
|
.emoji-mart-dark .emoji-mart-anchor:focus,
|
||||||
|
.emoji-mart-dark .emoji-mart-anchor-selected {
|
||||||
|
color: #bfbfbf;
|
||||||
|
}
|
||||||
|
|
117
docs/index.js
117
docs/index.js
|
@ -1,37 +1,26 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
|
|
||||||
import { Picker, Emoji } from '../src'
|
import { Picker, Emoji } from '../dist'
|
||||||
|
|
||||||
const CUSTOM_EMOJIS = [
|
const CUSTOM_EMOJIS = [
|
||||||
{
|
{
|
||||||
name: 'Party Parrot',
|
name: 'Party Parrot',
|
||||||
short_names: ['parrot'],
|
short_names: ['party_parrot'],
|
||||||
keywords: ['party'],
|
keywords: ['party', 'parrot'],
|
||||||
imageUrl: './images/parrot.gif'
|
imageUrl: './images/parrot.gif',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Octocat',
|
name: 'Octocat',
|
||||||
short_names: ['octocat'],
|
short_names: ['octocat'],
|
||||||
keywords: ['github'],
|
keywords: ['github'],
|
||||||
imageUrl: 'https://github.githubassets.com/images/icons/emoji/octocat.png'
|
imageUrl: 'https://github.githubassets.com/images/icons/emoji/octocat.png',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Squirrel',
|
name: 'Squirrel',
|
||||||
short_names: ['shipit', 'squirrel'],
|
short_names: ['shipit', 'squirrel'],
|
||||||
keywords: ['github'],
|
keywords: ['github'],
|
||||||
imageUrl: 'https://github.githubassets.com/images/icons/emoji/shipit.png'
|
imageUrl: 'https://github.githubassets.com/images/icons/emoji/shipit.png',
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Test Flag',
|
|
||||||
short_names: ['test'],
|
|
||||||
keywords: ['test', 'flag'],
|
|
||||||
spriteUrl: 'https://unpkg.com/emoji-datasource-twitter@4.0.4/img/twitter/sheets-256/64.png',
|
|
||||||
sheet_x: 1,
|
|
||||||
sheet_y: 1,
|
|
||||||
size: 64,
|
|
||||||
sheetColumns: 52,
|
|
||||||
sheetRows: 52,
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -41,49 +30,73 @@ class Example extends React.Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
native: true,
|
native: true,
|
||||||
set: 'apple',
|
set: 'apple',
|
||||||
|
theme: 'auto',
|
||||||
emoji: 'point_up',
|
emoji: 'point_up',
|
||||||
title: 'Pick your emoji…',
|
title: 'Pick your emoji…',
|
||||||
custom: CUSTOM_EMOJIS,
|
custom: CUSTOM_EMOJIS,
|
||||||
|
useButton: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div>
|
return (
|
||||||
<div className="row">
|
<div>
|
||||||
<h1>Emoji Mart 🏬</h1>
|
<div className="row">
|
||||||
|
<h1>Emoji Mart 🏬</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row sets">
|
||||||
|
Set:
|
||||||
|
{['native', 'apple', 'google', 'twitter', 'facebook'].map((set) => {
|
||||||
|
var props = {
|
||||||
|
disabled: !this.state.native && set == this.state.set,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set == 'native' && this.state.native) {
|
||||||
|
props.disabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={set}
|
||||||
|
value={set}
|
||||||
|
onClick={() => {
|
||||||
|
if (set == 'native') {
|
||||||
|
this.setState({ native: true })
|
||||||
|
} else {
|
||||||
|
this.setState({ set: set, native: false })
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{set}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row-small sets">
|
||||||
|
Theme:
|
||||||
|
{['auto', 'light', 'dark'].map((theme) => {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={theme}
|
||||||
|
disabled={theme == this.state.theme}
|
||||||
|
onClick={() => {
|
||||||
|
this.setState({ theme })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{theme}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<Picker {...this.state} onSelect={console.log} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
<div className="row sets">
|
|
||||||
{['native', 'apple', 'google', 'twitter', 'emojione', 'messenger', 'facebook'].map((set) => {
|
|
||||||
var props = { disabled: !this.state.native && set == this.state.set }
|
|
||||||
|
|
||||||
if (set == 'native' && this.state.native) {
|
|
||||||
props.disabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return <button
|
|
||||||
key={set}
|
|
||||||
value={set}
|
|
||||||
onClick={() => {
|
|
||||||
if (set == 'native') {
|
|
||||||
this.setState({ native: true })
|
|
||||||
} else {
|
|
||||||
this.setState({ set: set, native: false })
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
{...props}>
|
|
||||||
{set}
|
|
||||||
</button>
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="row">
|
|
||||||
<Picker
|
|
||||||
{...this.state}
|
|
||||||
onSelect={console.log}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
179
package.json
179
package.json
|
@ -1,90 +1,89 @@
|
||||||
{
|
{
|
||||||
"name": "emoji-mart",
|
"name": "emoji-mart-lazyload",
|
||||||
"version": "2.11.1",
|
"version": "3.0.1k",
|
||||||
"description": "Customizable Slack-like emoji picker for React",
|
"description": "Customizable Slack-like emoji picker for React",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist-es/index.js",
|
"module": "dist-es/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git@github.com:missive/emoji-mart.git"
|
"url": "git@github.com:mashirozx/emoji-mart.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
"emoji",
|
"emoji",
|
||||||
"picker"
|
"picker"
|
||||||
],
|
],
|
||||||
"author": "Etienne Lemay",
|
"author": "Etienne Lemay",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/missive/emoji-mart/issues"
|
"url": "https://github.com/mashirozx/emoji-mart/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/missive/emoji-mart",
|
"homepage": "https://github.com/mashirozx/emoji-mart",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"prop-types": "^15.6.0"
|
"@babel/runtime": "^7.0.0",
|
||||||
},
|
"intersection-observer": "^0.12.0",
|
||||||
"peerDependencies": {
|
"prop-types": "^15.6.0"
|
||||||
"react": "^0.14.0 || ^15.0.0-0 || ^16.0.0"
|
},
|
||||||
},
|
"peerDependencies": {
|
||||||
"devDependencies": {
|
"react": "^0.14.0 || ^15.0.0-0 || ^16.0.0 || ^17.0.0"
|
||||||
"@storybook/addon-actions": "^3.2.11",
|
},
|
||||||
"@storybook/addon-knobs": "^3.2.10",
|
"devDependencies": {
|
||||||
"@storybook/addon-links": "^3.2.10",
|
"@babel/cli": "^7.0.0",
|
||||||
"@storybook/addon-options": "3.2.10",
|
"@babel/core": "^7.0.0",
|
||||||
"@storybook/react": "^3.2.11",
|
"@babel/plugin-transform-runtime": "^7.7.6",
|
||||||
"auto-changelog": "1.12.0",
|
"@babel/preset-env": "^7.0.0",
|
||||||
"babel-cli": "^6.0.0",
|
"@babel/preset-react": "7.0.0",
|
||||||
"babel-core": "^6.0.0",
|
"@storybook/addon-actions": "^3.2.11",
|
||||||
"babel-jest": "^23.6.0",
|
"@storybook/addon-knobs": "^3.2.10",
|
||||||
"babel-loader": "^7.0.0",
|
"@storybook/addon-links": "^3.2.10",
|
||||||
"babel-plugin-module-resolver": "2.7.1",
|
"@storybook/addon-options": "3.2.10",
|
||||||
"babel-plugin-transform-define": "^1.3.0",
|
"@storybook/react": "^3.2.11",
|
||||||
"babel-plugin-transform-es2015-destructuring": "6.9.0",
|
"babel-jest": "^24.9.0",
|
||||||
"babel-plugin-transform-object-rest-spread": "6.8.0",
|
"babel-loader": "^8.0.0",
|
||||||
"babel-plugin-transform-runtime": "^6.23.0",
|
"babel-plugin-transform-define": "^2.0.0",
|
||||||
"babel-preset-env": "^1.7.0",
|
"emoji-datasource": "5.0.1",
|
||||||
"babel-preset-es2015": "6.6.0",
|
"emojilib": "^2.2.1",
|
||||||
"babel-preset-react": "6.5.0",
|
"enzyme": "^3.9.0",
|
||||||
"babel-runtime": "^6.26.0",
|
"enzyme-adapter-react-16": "^1.11.2",
|
||||||
"emoji-datasource": "4.0.4",
|
"inflection": "1.10.0",
|
||||||
"emojilib": "^2.2.1",
|
"jest": "^24.9.0",
|
||||||
"inflection": "1.10.0",
|
"mkdirp": "0.5.1",
|
||||||
"jest": "^23.0.0",
|
"prettier": "^1.16.4",
|
||||||
"mkdirp": "0.5.1",
|
"react": "^16.0.0",
|
||||||
"prettier": "^1.16.4",
|
"react-dom": "^16.0.0",
|
||||||
"react": "^16.0.0",
|
"react-test-renderer": "^16.8.4",
|
||||||
"react-dom": "^16.0.0",
|
"rimraf": "2.5.2",
|
||||||
"react-test-renderer": "^16.8.4",
|
"size-limit": "^0.11.4",
|
||||||
"rimraf": "2.5.2",
|
"webpack": "^3.6.0"
|
||||||
"size-limit": "^0.11.4",
|
},
|
||||||
"webpack": "^3.6.0"
|
"scripts": {
|
||||||
},
|
"clean": "rm -rf dist/ dist-es/ dist-modern/",
|
||||||
"scripts": {
|
"build:data": "node scripts/build-data",
|
||||||
"changelog": "auto-changelog",
|
"build:dist": "npm run build:cjs && npm run build:es && npm run build:modern",
|
||||||
"clean": "rm -rf dist/ dist-es/ dist-modern/",
|
"build:cjs": "BABEL_ENV=legacy-cjs babel src --out-dir dist --ignore '**/__tests__/*'",
|
||||||
"build:data": "node scripts/build-data",
|
"build:es": "BABEL_ENV=legacy-es babel src --out-dir dist-es --ignore '**/__tests__/*'",
|
||||||
"build:dist": "npm run build:cjs && npm run build:es && npm run build:modern",
|
"build:modern": "BABEL_ENV=modern babel src --out-dir dist-modern --ignore '**/__tests__/*'",
|
||||||
"build:cjs": "BABEL_ENV=legacy-cjs babel src --out-dir dist --copy-files --ignore '**/*.test.js'",
|
"build:docs": "cp css/emoji-mart.css docs && webpack --config ./docs/webpack.config.js",
|
||||||
"build:es": "BABEL_ENV=legacy-es babel src --out-dir dist-es --copy-files --ignore '**/*.test.js'",
|
"build": "npm run clean && npm run build:dist",
|
||||||
"build:modern": "babel src --out-dir dist-modern --copy-files --ignore '**/*.test.js'",
|
"watch": "BABEL_ENV=legacy-cjs babel src --watch --out-dir dist --ignore '**/__tests__/*'",
|
||||||
"build:docs": "cp css/emoji-mart.css docs && webpack --config ./docs/webpack.config.js",
|
"start": "npm run watch",
|
||||||
"build": "npm run clean && npm run build:dist",
|
"react:clean": "rimraf node_modules/{react,react-dom,react-addons-test-utils}",
|
||||||
"watch": "BABEL_ENV=cjs babel src --watch --out-dir dist --copy-files --ignore '**/*.test.js'",
|
"react:14": "npm run react:clean && npm i react@^0.14 react-dom@^0.14 react-addons-test-utils@^0.14 --save-dev",
|
||||||
"start": "npm run watch",
|
"react:15": "npm run react:clean && npm i react@^15 react-dom@^15 react-addons-test-utils@^15 --save-dev",
|
||||||
"react:clean": "rimraf node_modules/{react,react-dom,react-addons-test-utils}",
|
"test": "npm run clean && jest",
|
||||||
"react:14": "npm run react:clean && npm i react@^0.14 react-dom@^0.14 react-addons-test-utils@^0.14 --save-dev",
|
"test:size": "size-limit",
|
||||||
"react:15": "npm run react:clean && npm i react@^15 react-dom@^15 react-addons-test-utils@^15 --save-dev",
|
"test:ssr": "node test/ssr.js",
|
||||||
"test": "npm run clean && jest",
|
"prepublishOnly": "npm run build",
|
||||||
"prepublishOnly": "npm run build",
|
"storybook": "start-storybook -p 6006",
|
||||||
"storybook": "start-storybook -p 6006",
|
"build-storybook": "build-storybook",
|
||||||
"build-storybook": "build-storybook",
|
"prettier": "prettier --write \"{src,scripts,test,stories}/**/*.js\"",
|
||||||
"prettier": "prettier --write \"{src,scripts}/**/*.js\"",
|
"prettier:check": "prettier --check \"{src,scripts,test,stories}/**/*.js\"",
|
||||||
"prettier:check": "prettier --check \"{src,scripts}/**/*.js\"",
|
"prepare": "npm run build:dist"
|
||||||
"prepare": "npm run build:dist"
|
},
|
||||||
},
|
"size-limit": [
|
||||||
"size-limit": [
|
{
|
||||||
{
|
"path": "dist-es/index.js",
|
||||||
"path": "dist-es/index.js",
|
"limit": "82 KB"
|
||||||
"limit": "80 KB"
|
}
|
||||||
}
|
]
|
||||||
]
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const build = require('./build')
|
const build = require('./build')
|
||||||
const sets = ['apple', 'emojione', 'facebook', 'google', 'messenger', 'twitter']
|
const sets = ['apple', 'facebook', 'google', 'twitter']
|
||||||
|
|
||||||
build({ output: 'data/all.json' })
|
build({ output: 'data/all.json' })
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@ var fs = require('fs'),
|
||||||
var { compress } = require('../dist/utils/data')
|
var { compress } = require('../dist/utils/data')
|
||||||
|
|
||||||
var categories = [
|
var categories = [
|
||||||
['Smileys & People', 'people'],
|
['Smileys & Emotion', 'smileys'],
|
||||||
|
['People & Body', 'people'],
|
||||||
['Animals & Nature', 'nature'],
|
['Animals & Nature', 'nature'],
|
||||||
['Food & Drink', 'foods'],
|
['Food & Drink', 'foods'],
|
||||||
['Activities', 'activity'],
|
['Activities', 'activity'],
|
||||||
|
@ -16,7 +17,7 @@ var categories = [
|
||||||
['Flags', 'flags'],
|
['Flags', 'flags'],
|
||||||
]
|
]
|
||||||
|
|
||||||
var sets = ['apple', 'emojione', 'facebook', 'google', 'messenger', 'twitter']
|
var sets = ['apple', 'facebook', 'google', 'twitter']
|
||||||
|
|
||||||
module.exports = (options) => {
|
module.exports = (options) => {
|
||||||
delete require.cache[require.resolve('emoji-datasource')]
|
delete require.cache[require.resolve('emoji-datasource')]
|
||||||
|
@ -118,6 +119,18 @@ module.exports = (options) => {
|
||||||
})
|
})
|
||||||
.sort()
|
.sort()
|
||||||
|
|
||||||
|
// Merge “Smileys & Emotion” and “People & Body” into a single category
|
||||||
|
let smileys = data.categories[0]
|
||||||
|
let people = data.categories[1]
|
||||||
|
let smileysAndPeople = { id: 'people', name: 'Smileys & People' }
|
||||||
|
smileysAndPeople.emojis = []
|
||||||
|
.concat(smileys.emojis.slice(0, 114))
|
||||||
|
.concat(people.emojis)
|
||||||
|
.concat(smileys.emojis.slice(114))
|
||||||
|
|
||||||
|
data.categories.unshift(smileysAndPeople)
|
||||||
|
data.categories.splice(1, 2)
|
||||||
|
|
||||||
fs.writeFile(options.output, JSON.stringify(data), (err) => {
|
fs.writeFile(options.output, JSON.stringify(data), (err) => {
|
||||||
if (err) throw err
|
if (err) throw err
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
var pack = require('../package.json')
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
'process.env.NODE_ENV': 'production',
|
|
||||||
EMOJI_DATASOURCE_VERSION: pack.devDependencies['emoji-datasource'],
|
|
||||||
}
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { shallow, configure } from 'enzyme'
|
||||||
|
import Adapter from 'enzyme-adapter-react-16'
|
||||||
|
import SkinsDot from '../skins-dot'
|
||||||
|
|
||||||
|
configure({ adapter: new Adapter() })
|
||||||
|
|
||||||
|
test('click dot to expand the menu', () => {
|
||||||
|
let currentSkin
|
||||||
|
const onChange = (skin) => {
|
||||||
|
currentSkin = skin
|
||||||
|
}
|
||||||
|
const i18n = {
|
||||||
|
skintones: {
|
||||||
|
1: 'Default Skin Tone',
|
||||||
|
2: 'Light Skin Tone',
|
||||||
|
3: 'Medium-Light Skin Tone',
|
||||||
|
4: 'Medium Skin Tone',
|
||||||
|
5: 'Medium-Dark Skin Tone',
|
||||||
|
6: 'Dark Skin Tone',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const skins = shallow(<SkinsDot skin={1} onChange={onChange} i18n={i18n} />)
|
||||||
|
|
||||||
|
// component should be un-expanded by default
|
||||||
|
expect(skins.find('[aria-haspopup]').prop('aria-label')).toEqual(
|
||||||
|
'Default Skin Tone',
|
||||||
|
)
|
||||||
|
expect(skins.find('[aria-haspopup]').prop('aria-expanded')).toEqual(false)
|
||||||
|
|
||||||
|
// simulate click
|
||||||
|
skins.find('[aria-haspopup]').simulate('click', {
|
||||||
|
currentTarget: {
|
||||||
|
getAttribute(name) {
|
||||||
|
if (name === 'data-skin') {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// component should now be expanded
|
||||||
|
expect(skins.find('[aria-haspopup]').prop('aria-expanded')).toEqual(true)
|
||||||
|
expect(skins.find('[data-skin=1]').prop('aria-pressed')).toEqual(true)
|
||||||
|
expect(skins.find('[data-skin=2]').prop('aria-pressed')).toEqual(false)
|
||||||
|
})
|
|
@ -37,11 +37,13 @@ export default class Anchors extends React.PureComponent {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const iconId = id.startsWith('custom-') ? 'custom' : id
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={id}
|
key={id}
|
||||||
aria-label={i18n.categories[id]}
|
aria-label={i18n.categories[iconId]}
|
||||||
title={i18n.categories[id]}
|
title={i18n.categories[iconId]}
|
||||||
data-index={i}
|
data-index={i}
|
||||||
type={'button'}
|
type={'button'}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
|
@ -51,7 +53,7 @@ export default class Anchors extends React.PureComponent {
|
||||||
style={{ color: isSelected ? color : null }}
|
style={{ color: isSelected ? color : null }}
|
||||||
>
|
>
|
||||||
<div className="emoji-mart-anchor-icon">
|
<div className="emoji-mart-anchor-icon">
|
||||||
{icons.categories[id]()}
|
{icons.categories[iconId]()}
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
className="emoji-mart-anchor-bar"
|
className="emoji-mart-anchor-bar"
|
||||||
|
|
|
@ -1,242 +1,291 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import frequently from '../utils/frequently'
|
import frequently from '../utils/frequently'
|
||||||
import { getData } from '../utils'
|
import { getData } from '../utils'
|
||||||
import NimbleEmoji from './emoji/nimble-emoji'
|
import NimbleEmoji from './emoji/nimble-emoji'
|
||||||
import NotFound from './not-found'
|
import NotFound from './not-found'
|
||||||
|
import 'intersection-observer'
|
||||||
export default class Category extends React.Component {
|
|
||||||
constructor(props) {
|
export default class Category extends React.Component {
|
||||||
super(props)
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
this.data = props.data
|
|
||||||
this.setContainerRef = this.setContainerRef.bind(this)
|
this.data = props.data
|
||||||
this.setLabelRef = this.setLabelRef.bind(this)
|
this.setContainerRef = this.setContainerRef.bind(this)
|
||||||
}
|
this.setLabelRef = this.setLabelRef.bind(this)
|
||||||
|
|
||||||
componentDidMount() {
|
this.imageObserver = new window.IntersectionObserver((entries, observer) => {
|
||||||
this.margin = 0
|
entries.forEach((entry) => {
|
||||||
this.minMargin = 0
|
if (entry.isIntersecting) {
|
||||||
|
const image = entry.target;
|
||||||
this.memoizeSize()
|
image.src = image.dataset.src;
|
||||||
}
|
image.classList.remove("lazy");
|
||||||
|
this.imageObserver.unobserve(image);
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
}
|
||||||
var {
|
});
|
||||||
name,
|
});
|
||||||
perLine,
|
}
|
||||||
native,
|
|
||||||
hasStickyPosition,
|
componentDidMount() {
|
||||||
emojis,
|
this.margin = 0
|
||||||
emojiProps,
|
this.minMargin = 0
|
||||||
} = this.props,
|
|
||||||
{ skin, size, set } = emojiProps,
|
this.memoizeSize()
|
||||||
{
|
|
||||||
perLine: nextPerLine,
|
this.lazyloadImages = []
|
||||||
native: nextNative,
|
this.addLazyloadObserver()
|
||||||
hasStickyPosition: nextHasStickyPosition,
|
}
|
||||||
emojis: nextEmojis,
|
|
||||||
emojiProps: nextEmojiProps,
|
componentDidUpdate() {
|
||||||
} = nextProps,
|
this.addLazyloadObserver()
|
||||||
{ skin: nextSkin, size: nextSize, set: nextSet } = nextEmojiProps,
|
}
|
||||||
shouldUpdate = false
|
|
||||||
|
componentWillUnmount() {
|
||||||
if (name == 'Recent' && perLine != nextPerLine) {
|
this.removeLazyloadObserver()
|
||||||
shouldUpdate = true
|
}
|
||||||
}
|
|
||||||
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
if (name == 'Search') {
|
var {
|
||||||
shouldUpdate = !(emojis == nextEmojis)
|
name,
|
||||||
}
|
perLine,
|
||||||
|
native,
|
||||||
if (
|
hasStickyPosition,
|
||||||
skin != nextSkin ||
|
emojis,
|
||||||
size != nextSize ||
|
emojiProps,
|
||||||
native != nextNative ||
|
} = this.props,
|
||||||
set != nextSet ||
|
{ skin, size, set } = emojiProps,
|
||||||
hasStickyPosition != nextHasStickyPosition
|
{
|
||||||
) {
|
perLine: nextPerLine,
|
||||||
shouldUpdate = true
|
native: nextNative,
|
||||||
}
|
hasStickyPosition: nextHasStickyPosition,
|
||||||
|
emojis: nextEmojis,
|
||||||
return shouldUpdate
|
emojiProps: nextEmojiProps,
|
||||||
}
|
} = nextProps,
|
||||||
|
{ skin: nextSkin, size: nextSize, set: nextSet } = nextEmojiProps,
|
||||||
memoizeSize() {
|
shouldUpdate = false
|
||||||
if (!this.container) {
|
|
||||||
// probably this is a test environment, e.g. jest
|
if (name == 'Recent' && perLine != nextPerLine) {
|
||||||
this.top = 0
|
shouldUpdate = true
|
||||||
this.maxMargin = 0
|
}
|
||||||
return
|
|
||||||
}
|
if (name == 'Search') {
|
||||||
var parent = this.container.parentElement
|
// shouldUpdate = !(emojis == nextEmojis)
|
||||||
var { top, height } = this.container.getBoundingClientRect()
|
shouldUpdate = true
|
||||||
var { top: parentTop } = parent.getBoundingClientRect()
|
}
|
||||||
var { height: labelHeight } = this.label.getBoundingClientRect()
|
|
||||||
|
if (
|
||||||
this.top = top - parentTop + parent.scrollTop
|
skin != nextSkin ||
|
||||||
|
size != nextSize ||
|
||||||
if (height == 0) {
|
native != nextNative ||
|
||||||
this.maxMargin = 0
|
set != nextSet ||
|
||||||
} else {
|
hasStickyPosition != nextHasStickyPosition
|
||||||
this.maxMargin = height - labelHeight
|
) {
|
||||||
}
|
shouldUpdate = true
|
||||||
}
|
}
|
||||||
|
|
||||||
handleScroll(scrollTop) {
|
return shouldUpdate
|
||||||
var margin = scrollTop - this.top
|
}
|
||||||
margin = margin < this.minMargin ? this.minMargin : margin
|
|
||||||
margin = margin > this.maxMargin ? this.maxMargin : margin
|
memoizeSize() {
|
||||||
|
if (!this.container) {
|
||||||
if (margin == this.margin) return
|
// probably this is a test environment, e.g. jest
|
||||||
|
this.top = 0
|
||||||
if (!this.props.hasStickyPosition) {
|
this.maxMargin = 0
|
||||||
this.label.style.top = `${margin}px`
|
return
|
||||||
}
|
}
|
||||||
|
var parent = this.container.parentElement
|
||||||
this.margin = margin
|
var { top, height } = this.container.getBoundingClientRect()
|
||||||
return true
|
var { top: parentTop } = parent.getBoundingClientRect()
|
||||||
}
|
var { height: labelHeight } = this.label.getBoundingClientRect()
|
||||||
|
|
||||||
getEmojis() {
|
this.top = top - parentTop + parent.scrollTop
|
||||||
var { name, emojis, recent, perLine } = this.props
|
|
||||||
|
if (height == 0) {
|
||||||
if (name == 'Recent') {
|
this.maxMargin = 0
|
||||||
let { custom } = this.props
|
} else {
|
||||||
let frequentlyUsed = recent || frequently.get(perLine)
|
this.maxMargin = height - labelHeight
|
||||||
|
}
|
||||||
if (frequentlyUsed.length) {
|
}
|
||||||
emojis = frequentlyUsed
|
|
||||||
.map((id) => {
|
addLazyloadObserver() {
|
||||||
const emoji = custom.filter((e) => e.id === id)[0]
|
this.removeLazyloadObserver()
|
||||||
if (emoji) {
|
this.lazyloadImages = this.container.querySelectorAll(".lazy");
|
||||||
return emoji
|
|
||||||
}
|
this.lazyloadImages.forEach((image) => {
|
||||||
|
this.imageObserver.observe(image);
|
||||||
return id
|
});
|
||||||
})
|
}
|
||||||
.filter((id) => !!getData(id, null, null, this.data))
|
|
||||||
}
|
removeLazyloadObserver() {
|
||||||
|
this.lazyloadImages.forEach((image) => {
|
||||||
if (emojis.length === 0 && frequentlyUsed.length > 0) {
|
this.imageObserver.unobserve(image);
|
||||||
return null
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
handleOnContextMenu(e) {
|
||||||
if (emojis) {
|
e.preventDefault();
|
||||||
emojis = emojis.slice(0)
|
}
|
||||||
}
|
|
||||||
|
handleScroll(scrollTop) {
|
||||||
return emojis
|
var margin = scrollTop - this.top
|
||||||
}
|
margin = margin < this.minMargin ? this.minMargin : margin
|
||||||
|
margin = margin > this.maxMargin ? this.maxMargin : margin
|
||||||
updateDisplay(display) {
|
|
||||||
var emojis = this.getEmojis()
|
if (margin == this.margin) return
|
||||||
|
|
||||||
if (!emojis || !this.container) {
|
if (!this.props.hasStickyPosition) {
|
||||||
return
|
this.label.style.top = `${margin}px`
|
||||||
}
|
}
|
||||||
|
|
||||||
this.container.style.display = display
|
this.margin = margin
|
||||||
}
|
return true
|
||||||
|
}
|
||||||
setContainerRef(c) {
|
|
||||||
this.container = c
|
getEmojis() {
|
||||||
}
|
var { name, emojis, recent, perLine } = this.props
|
||||||
|
|
||||||
setLabelRef(c) {
|
if (name == 'Recent') {
|
||||||
this.label = c
|
let { custom } = this.props
|
||||||
}
|
let frequentlyUsed = recent || frequently.get(perLine)
|
||||||
|
|
||||||
render() {
|
if (frequentlyUsed.length) {
|
||||||
var {
|
emojis = frequentlyUsed
|
||||||
id,
|
.map((id) => {
|
||||||
name,
|
const emoji = custom.filter((e) => e.id === id)[0]
|
||||||
hasStickyPosition,
|
if (emoji) {
|
||||||
emojiProps,
|
return emoji
|
||||||
i18n,
|
}
|
||||||
notFound,
|
|
||||||
notFoundEmoji,
|
return id
|
||||||
} = this.props,
|
})
|
||||||
emojis = this.getEmojis(),
|
.filter((id) => !!getData(id, null, null, this.data))
|
||||||
labelStyles = {},
|
}
|
||||||
labelSpanStyles = {},
|
|
||||||
containerStyles = {}
|
if (emojis.length === 0 && frequentlyUsed.length > 0) {
|
||||||
|
return null
|
||||||
if (!emojis) {
|
}
|
||||||
containerStyles = {
|
}
|
||||||
display: 'none',
|
|
||||||
}
|
if (emojis) {
|
||||||
}
|
emojis = emojis.slice(0)
|
||||||
|
}
|
||||||
if (!hasStickyPosition) {
|
|
||||||
labelStyles = {
|
return emojis
|
||||||
height: 28,
|
}
|
||||||
}
|
|
||||||
|
updateDisplay(display) {
|
||||||
labelSpanStyles = {
|
var emojis = this.getEmojis()
|
||||||
position: 'absolute',
|
|
||||||
}
|
if (!emojis || !this.container) {
|
||||||
}
|
return
|
||||||
|
}
|
||||||
return (
|
|
||||||
<section
|
this.container.style.display = display
|
||||||
ref={this.setContainerRef}
|
}
|
||||||
className="emoji-mart-category"
|
|
||||||
aria-label={i18n.categories[id]}
|
setContainerRef(c) {
|
||||||
style={containerStyles}
|
this.container = c
|
||||||
>
|
}
|
||||||
<div
|
|
||||||
style={labelStyles}
|
setLabelRef(c) {
|
||||||
data-name={name}
|
this.label = c
|
||||||
className="emoji-mart-category-label"
|
}
|
||||||
>
|
|
||||||
<span
|
render() {
|
||||||
style={labelSpanStyles}
|
var {
|
||||||
ref={this.setLabelRef}
|
id,
|
||||||
aria-hidden={true /* already labeled by the section aria-label */}
|
name,
|
||||||
>
|
hasStickyPosition,
|
||||||
{i18n.categories[id]}
|
emojiProps,
|
||||||
</span>
|
i18n,
|
||||||
</div>
|
notFound,
|
||||||
|
notFoundEmoji,
|
||||||
<ul className="emoji-mart-category-list">
|
} = this.props,
|
||||||
{emojis &&
|
emojis = this.getEmojis(),
|
||||||
emojis.map((emoji) => (
|
labelStyles = {},
|
||||||
<li key={emoji.id || emoji}>
|
labelSpanStyles = {},
|
||||||
{NimbleEmoji({ emoji: emoji, data: this.data, ...emojiProps })}
|
containerStyles = {}
|
||||||
</li>
|
|
||||||
))}
|
if (!emojis) {
|
||||||
</ul>
|
containerStyles = {
|
||||||
|
display: 'none',
|
||||||
{emojis && !emojis.length && (
|
}
|
||||||
<NotFound
|
}
|
||||||
i18n={i18n}
|
|
||||||
notFound={notFound}
|
if (!hasStickyPosition) {
|
||||||
notFoundEmoji={notFoundEmoji}
|
labelStyles = {
|
||||||
data={this.data}
|
height: 28,
|
||||||
emojiProps={emojiProps}
|
}
|
||||||
/>
|
|
||||||
)}
|
labelSpanStyles = {
|
||||||
</section>
|
position: 'absolute',
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
const label = i18n.categories[id] || name
|
||||||
Category.propTypes /* remove-proptypes */ = {
|
|
||||||
emojis: PropTypes.array,
|
return (
|
||||||
hasStickyPosition: PropTypes.bool,
|
<section
|
||||||
name: PropTypes.string.isRequired,
|
ref={this.setContainerRef}
|
||||||
native: PropTypes.bool.isRequired,
|
className="emoji-mart-category"
|
||||||
perLine: PropTypes.number.isRequired,
|
aria-label={label}
|
||||||
emojiProps: PropTypes.object.isRequired,
|
style={containerStyles}
|
||||||
recent: PropTypes.arrayOf(PropTypes.string),
|
>
|
||||||
notFound: PropTypes.func,
|
<div
|
||||||
notFoundEmoji: PropTypes.string.isRequired,
|
style={labelStyles}
|
||||||
}
|
data-name={name}
|
||||||
|
className="emoji-mart-category-label"
|
||||||
Category.defaultProps = {
|
>
|
||||||
emojis: [],
|
<span
|
||||||
hasStickyPosition: true,
|
style={labelSpanStyles}
|
||||||
}
|
ref={this.setLabelRef}
|
||||||
|
aria-hidden={true /* already labeled by the section aria-label */}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul className="emoji-mart-category-list">
|
||||||
|
{emojis &&
|
||||||
|
emojis.map((emoji) => (
|
||||||
|
<li
|
||||||
|
key={
|
||||||
|
(emoji.short_names && emoji.short_names.join('_')) || emoji
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{NimbleEmoji({ emoji: emoji, data: this.data, ...emojiProps, lazy: true })}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{emojis && !emojis.length && (
|
||||||
|
<NotFound
|
||||||
|
i18n={i18n}
|
||||||
|
notFound={notFound}
|
||||||
|
notFoundEmoji={notFoundEmoji}
|
||||||
|
data={this.data}
|
||||||
|
emojiProps={emojiProps}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Category.propTypes /* remove-proptypes */ = {
|
||||||
|
emojis: PropTypes.array,
|
||||||
|
hasStickyPosition: PropTypes.bool,
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
|
native: PropTypes.bool.isRequired,
|
||||||
|
perLine: PropTypes.number.isRequired,
|
||||||
|
emojiProps: PropTypes.object.isRequired,
|
||||||
|
recent: PropTypes.arrayOf(PropTypes.string),
|
||||||
|
notFound: PropTypes.func,
|
||||||
|
notFoundEmoji: PropTypes.string.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
Category.defaultProps = {
|
||||||
|
emojis: [],
|
||||||
|
hasStickyPosition: true,
|
||||||
|
}
|
||||||
|
|
|
@ -1,220 +1,242 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import { getData, getSanitizedData, unifiedToNative } from '../../utils'
|
import { getData, getSanitizedData, unifiedToNative } from '../../utils'
|
||||||
import { uncompress } from '../../utils/data'
|
import { uncompress } from '../../utils/data'
|
||||||
import { EmojiPropTypes } from '../../utils/shared-props'
|
import { EmojiPropTypes } from '../../utils/shared-props'
|
||||||
import { EmojiDefaultProps } from '../../utils/shared-default-props'
|
import { EmojiDefaultProps } from '../../utils/shared-default-props'
|
||||||
|
|
||||||
const _getData = (props) => {
|
const _getData = (props) => {
|
||||||
var { emoji, skin, set, data } = props
|
var { emoji, skin, set, data } = props
|
||||||
return getData(emoji, skin, set, data)
|
return getData(emoji, skin, set, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
const _getPosition = (props) => {
|
const _getPosition = (props) => {
|
||||||
var { sheet_x, sheet_y } = _getData(props),
|
var { sheet_x, sheet_y } = _getData(props),
|
||||||
multiplyX = 100 / (props.sheetColumns - 1),
|
multiplyX = 100 / (props.sheetColumns - 1),
|
||||||
multiplyY = 100 / (props.sheetRows - 1)
|
multiplyY = 100 / (props.sheetRows - 1)
|
||||||
|
|
||||||
return `${multiplyX * sheet_x}% ${multiplyY * sheet_y}%`
|
return `${multiplyX * sheet_x}% ${multiplyY * sheet_y}%`
|
||||||
}
|
}
|
||||||
|
|
||||||
const _getSanitizedData = (props) => {
|
const _getSanitizedData = (props) => {
|
||||||
var { emoji, skin, set, data } = props
|
var { emoji, skin, set, data } = props
|
||||||
return getSanitizedData(emoji, skin, set, data)
|
return getSanitizedData(emoji, skin, set, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
const _handleClick = (e, props) => {
|
const _handleClick = (e, props) => {
|
||||||
if (!props.onClick) {
|
if (!props.onClick) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var { onClick } = props,
|
var { onClick } = props,
|
||||||
emoji = _getSanitizedData(props)
|
emoji = _getSanitizedData(props)
|
||||||
|
|
||||||
onClick(emoji, e)
|
onClick(emoji, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
const _handleOver = (e, props) => {
|
const _handleOver = (e, props) => {
|
||||||
if (!props.onOver) {
|
if (!props.onOver) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var { onOver } = props,
|
var { onOver } = props,
|
||||||
emoji = _getSanitizedData(props)
|
emoji = _getSanitizedData(props)
|
||||||
|
|
||||||
onOver(emoji, e)
|
onOver(emoji, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
const _handleLeave = (e, props) => {
|
const _handleLeave = (e, props) => {
|
||||||
if (!props.onLeave) {
|
if (!props.onLeave) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var { onLeave } = props,
|
var { onLeave } = props,
|
||||||
emoji = _getSanitizedData(props)
|
emoji = _getSanitizedData(props)
|
||||||
|
|
||||||
onLeave(emoji, e)
|
onLeave(emoji, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
const _isNumeric = (value) => {
|
const _isNumeric = (value) => {
|
||||||
return !isNaN(value - parseFloat(value))
|
return !isNaN(value - parseFloat(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
const _convertStyleToCSS = (style) => {
|
const _convertStyleToCSS = (style) => {
|
||||||
let div = document.createElement('div')
|
let div = document.createElement('div')
|
||||||
|
|
||||||
for (let key in style) {
|
for (let key in style) {
|
||||||
let value = style[key]
|
let value = style[key]
|
||||||
|
|
||||||
if (_isNumeric(value)) {
|
if (_isNumeric(value)) {
|
||||||
value += 'px'
|
value += 'px'
|
||||||
}
|
}
|
||||||
|
|
||||||
div.style[key] = value
|
div.style[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
return div.getAttribute('style')
|
return div.getAttribute('style')
|
||||||
}
|
}
|
||||||
|
|
||||||
const NimbleEmoji = (props) => {
|
const NimbleEmoji = (props) => {
|
||||||
if (props.data.compressed) {
|
if (props.data.compressed) {
|
||||||
uncompress(props.data)
|
uncompress(props.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let k in NimbleEmoji.defaultProps) {
|
for (let k in NimbleEmoji.defaultProps) {
|
||||||
if (props[k] == undefined && NimbleEmoji.defaultProps[k] != undefined) {
|
if (props[k] == undefined && NimbleEmoji.defaultProps[k] != undefined) {
|
||||||
props[k] = NimbleEmoji.defaultProps[k]
|
props[k] = NimbleEmoji.defaultProps[k]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = _getData(props)
|
let data = _getData(props)
|
||||||
if (!data) {
|
if (!data) {
|
||||||
if (props.fallback) {
|
if (props.fallback) {
|
||||||
return props.fallback(null, props)
|
return props.fallback(null, props)
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let { unified, custom, short_names, imageUrl } = data,
|
let { unified, custom, short_names, imageUrl } = data,
|
||||||
style = {},
|
style = {},
|
||||||
children = props.children,
|
children = props.children,
|
||||||
className = 'emoji-mart-emoji',
|
className = 'emoji-mart-emoji',
|
||||||
nativeEmoji = unified && unifiedToNative(unified),
|
nativeEmoji = unified && unifiedToNative(unified),
|
||||||
// combine the emoji itself and all shortcodes into an accessible label
|
// combine the emoji itself and all shortcodes into an accessible label
|
||||||
label = [nativeEmoji]
|
label = [nativeEmoji]
|
||||||
.concat(short_names)
|
.concat(short_names)
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(', '),
|
.join(', '),
|
||||||
title = null
|
title = null
|
||||||
|
|
||||||
if (!unified && !custom) {
|
if (!unified && !custom) {
|
||||||
if (props.fallback) {
|
if (props.fallback) {
|
||||||
return props.fallback(data, props)
|
return props.fallback(data, props)
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.tooltip) {
|
if (props.tooltip) {
|
||||||
title = short_names[0]
|
title = short_names[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.native && unified) {
|
if (props.native && unified) {
|
||||||
className += ' emoji-mart-emoji-native'
|
className += ' emoji-mart-emoji-native'
|
||||||
style = { fontSize: props.size }
|
style = { fontSize: props.size }
|
||||||
children = nativeEmoji
|
children = nativeEmoji
|
||||||
|
|
||||||
if (props.forceSize) {
|
if (props.forceSize) {
|
||||||
style.display = 'inline-block'
|
style.display = 'inline-block'
|
||||||
style.width = props.size
|
style.width = props.size
|
||||||
style.height = props.size
|
style.height = props.size
|
||||||
style.wordBreak = 'keep-all'
|
style.wordBreak = 'keep-all'
|
||||||
}
|
}
|
||||||
} else if (custom) {
|
} else if (custom) {
|
||||||
className += ' emoji-mart-emoji-custom'
|
className += ' emoji-mart-emoji-custom'
|
||||||
style = {
|
style = {
|
||||||
width: props.size,
|
width: props.size,
|
||||||
height: props.size,
|
height: props.size,
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
}
|
}
|
||||||
if (data.spriteUrl) {
|
if (data.spriteUrl) {
|
||||||
style = {
|
style = {
|
||||||
...style,
|
...style,
|
||||||
backgroundImage: `url(${data.spriteUrl})`,
|
backgroundImage: `url(${data.spriteUrl})`,
|
||||||
backgroundSize: `${100 * props.sheetColumns}% ${100 *
|
backgroundSize: `${100 * props.sheetColumns}% ${100 *
|
||||||
props.sheetRows}%`,
|
props.sheetRows}%`,
|
||||||
backgroundPosition: _getPosition(props),
|
backgroundPosition: _getPosition(props),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
style = {
|
style = {
|
||||||
...style,
|
...style,
|
||||||
backgroundImage: `url(${imageUrl})`,
|
backgroundImage: `url(${imageUrl})`,
|
||||||
backgroundSize: 'contain',
|
backgroundSize: 'contain',
|
||||||
}
|
backgroundRepeat: 'no-repeat',
|
||||||
}
|
backgroundPosition: 'center',
|
||||||
} else {
|
}
|
||||||
let setHasEmoji =
|
if(props.lazy){
|
||||||
data[`has_img_${props.set}`] == undefined || data[`has_img_${props.set}`]
|
delete style.backgroundImage
|
||||||
|
delete style.backgroundSize
|
||||||
if (!setHasEmoji) {
|
delete style.backgroundRepeat
|
||||||
if (props.fallback) {
|
delete style.backgroundPosition
|
||||||
return props.fallback(data, props)
|
style.objectFit = 'contain'
|
||||||
} else {
|
}
|
||||||
return null
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
let setHasEmoji =
|
||||||
style = {
|
data[`has_img_${props.set}`] == undefined || data[`has_img_${props.set}`]
|
||||||
width: props.size,
|
|
||||||
height: props.size,
|
if (!setHasEmoji) {
|
||||||
display: 'inline-block',
|
if (props.fallback) {
|
||||||
backgroundImage: `url(${props.backgroundImageFn(
|
return props.fallback(data, props)
|
||||||
props.set,
|
} else {
|
||||||
props.sheetSize,
|
return null
|
||||||
)})`,
|
}
|
||||||
backgroundSize: `${100 * props.sheetColumns}% ${100 *
|
} else {
|
||||||
props.sheetRows}%`,
|
style = {
|
||||||
backgroundPosition: _getPosition(props),
|
width: props.size,
|
||||||
}
|
height: props.size,
|
||||||
}
|
display: 'inline-block',
|
||||||
}
|
backgroundImage: `url(${props.backgroundImageFn(
|
||||||
|
props.set,
|
||||||
var Tag = {
|
props.sheetSize,
|
||||||
name: 'span',
|
)})`,
|
||||||
props: {},
|
backgroundSize: `${100 * props.sheetColumns}% ${100 *
|
||||||
}
|
props.sheetRows}%`,
|
||||||
|
backgroundPosition: _getPosition(props),
|
||||||
if (props.onClick) {
|
}
|
||||||
Tag.name = 'button'
|
}
|
||||||
Tag.props = {
|
}
|
||||||
type: 'button',
|
|
||||||
}
|
var Tag = {
|
||||||
}
|
name: 'span',
|
||||||
|
props: {},
|
||||||
if (props.html) {
|
}
|
||||||
style = _convertStyleToCSS(style)
|
|
||||||
return `<${Tag.name} style='${style}' aria-label='${label}' ${
|
if (props.onClick && props.useButton) {
|
||||||
title ? `title='${title}'` : ''
|
Tag.name = 'button'
|
||||||
} class='${className}'>${children || ''}</${Tag.name}>`
|
Tag.props = {
|
||||||
} else {
|
type: 'button',
|
||||||
return (
|
}
|
||||||
<Tag.name
|
}
|
||||||
onClick={(e) => _handleClick(e, props)}
|
|
||||||
onMouseEnter={(e) => _handleOver(e, props)}
|
if (props.html) {
|
||||||
onMouseLeave={(e) => _handleLeave(e, props)}
|
style = _convertStyleToCSS(style)
|
||||||
aria-label={label}
|
return `<${Tag.name} style='${style}' aria-label='${label}' ${
|
||||||
title={title}
|
title ? `title='${title}'` : ''
|
||||||
className={className}
|
} class='${className}'>${children || ''}</${Tag.name}>`
|
||||||
{...Tag.props}
|
} else {
|
||||||
>
|
return (
|
||||||
<span style={style}>{children}</span>
|
<Tag.name
|
||||||
</Tag.name>
|
onClick={(e) => _handleClick(e, props)}
|
||||||
)
|
onMouseEnter={(e) => _handleOver(e, props)}
|
||||||
}
|
onMouseLeave={(e) => _handleLeave(e, props)}
|
||||||
}
|
onContextMenu={(e) => e.preventDefault()}
|
||||||
|
aria-label={label}
|
||||||
NimbleEmoji.propTypes /* remove-proptypes */ = {
|
title={title}
|
||||||
...EmojiPropTypes,
|
className={className}
|
||||||
data: PropTypes.object.isRequired,
|
{...Tag.props}
|
||||||
}
|
>
|
||||||
NimbleEmoji.defaultProps = EmojiDefaultProps
|
{
|
||||||
|
custom && !data.spriteUrl && props.lazy
|
||||||
export default NimbleEmoji
|
?
|
||||||
|
<img
|
||||||
|
style={style}
|
||||||
|
className="lazy"
|
||||||
|
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP89B8AAukB8/71MdcAAAAASUVORK5CYII="
|
||||||
|
data-src={imageUrl}
|
||||||
|
onContextMenu={(e) => e.preventDefault()}
|
||||||
|
/>
|
||||||
|
:
|
||||||
|
<span style={style}>{children}</span>
|
||||||
|
}
|
||||||
|
</Tag.name>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NimbleEmoji.propTypes /* remove-proptypes */ = {
|
||||||
|
...EmojiPropTypes,
|
||||||
|
data: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
NimbleEmoji.defaultProps = EmojiDefaultProps
|
||||||
|
|
||||||
|
export default NimbleEmoji
|
||||||
|
|
|
@ -57,7 +57,40 @@ test('with custom emoji and tooltip', () => {
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
custom,
|
custom,
|
||||||
})
|
})
|
||||||
|
expect(subject.categories.length).toEqual(11)
|
||||||
|
expect(subject.categories[10].name).toEqual('Custom')
|
||||||
subject.handleSearch(
|
subject.handleSearch(
|
||||||
new NimbleEmojiIndex(subject.data).search('custom_', { custom }),
|
new NimbleEmojiIndex(subject.data).search('custom_', { custom }),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('with custom categories', () => {
|
||||||
|
const custom = [
|
||||||
|
{
|
||||||
|
id: 'custom_name',
|
||||||
|
name: 'custom_name',
|
||||||
|
short_names: ['custom_name'],
|
||||||
|
text: '',
|
||||||
|
emoticons: [],
|
||||||
|
keywords: ['custom_name'],
|
||||||
|
imageUrl: 'https://example.com/emoji',
|
||||||
|
custom: true,
|
||||||
|
customCategory: 'Category 1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'custom_name2',
|
||||||
|
name: 'custom_name2',
|
||||||
|
short_names: ['custom_name2'],
|
||||||
|
text: '',
|
||||||
|
emoticons: [],
|
||||||
|
keywords: ['custom_name2'],
|
||||||
|
imageUrl: 'https://example.com/emoji',
|
||||||
|
custom: true,
|
||||||
|
customCategory: 'Category 2',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
const subject = render({ custom })
|
||||||
|
expect(subject.categories.length).toEqual(12)
|
||||||
|
expect(subject.categories[10].name).toEqual('Category 1')
|
||||||
|
expect(subject.categories[11].name).toEqual('Category 2')
|
||||||
|
})
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import '../../vendor/raf-polyfill'
|
|
||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
|
@ -49,8 +47,9 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
|
this.CUSTOM = []
|
||||||
|
|
||||||
this.RECENT_CATEGORY = { id: 'recent', name: 'Recent', emojis: null }
|
this.RECENT_CATEGORY = { id: 'recent', name: 'Recent', emojis: null }
|
||||||
this.CUSTOM_CATEGORY = { id: 'custom', name: 'Custom', emojis: [] }
|
|
||||||
this.SEARCH_CATEGORY = {
|
this.SEARCH_CATEGORY = {
|
||||||
id: 'search',
|
id: 'search',
|
||||||
name: 'Search',
|
name: 'Search',
|
||||||
|
@ -65,25 +64,45 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
this.data = props.data
|
this.data = props.data
|
||||||
this.i18n = deepMerge(I18N, props.i18n)
|
this.i18n = deepMerge(I18N, props.i18n)
|
||||||
this.icons = deepMerge(icons, props.icons)
|
this.icons = deepMerge(icons, props.icons)
|
||||||
this.state = {
|
this.state = { firstRender: true }
|
||||||
skin: props.skin || store.get('skin') || props.defaultSkin,
|
|
||||||
firstRender: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.categories = []
|
this.categories = []
|
||||||
let allCategories = [].concat(this.data.categories)
|
let allCategories = [].concat(this.data.categories)
|
||||||
|
|
||||||
if (props.custom.length > 0) {
|
if (props.custom.length > 0) {
|
||||||
this.CUSTOM_CATEGORY.emojis = props.custom.map((emoji) => {
|
const customCategories = {}
|
||||||
return {
|
let customCategoriesCreated = 0
|
||||||
|
|
||||||
|
props.custom.forEach((emoji) => {
|
||||||
|
if (!customCategories[emoji.customCategory]) {
|
||||||
|
customCategories[emoji.customCategory] = {
|
||||||
|
id: emoji.customCategory
|
||||||
|
? `custom-${emoji.customCategory}`
|
||||||
|
: 'custom',
|
||||||
|
name: emoji.customCategory || 'Custom',
|
||||||
|
emojis: [],
|
||||||
|
anchor: customCategoriesCreated === 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
customCategoriesCreated++
|
||||||
|
}
|
||||||
|
|
||||||
|
const category = customCategories[emoji.customCategory]
|
||||||
|
|
||||||
|
const customEmoji = {
|
||||||
...emoji,
|
...emoji,
|
||||||
// `<Category />` expects emoji to have an `id`.
|
// `<Category />` expects emoji to have an `id`.
|
||||||
id: emoji.short_names[0],
|
id: emoji.short_names[0],
|
||||||
custom: true,
|
custom: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
category.emojis.push(customEmoji)
|
||||||
|
this.CUSTOM.push(customEmoji)
|
||||||
})
|
})
|
||||||
|
|
||||||
allCategories.push(this.CUSTOM_CATEGORY)
|
allCategories = allCategories.concat(
|
||||||
|
Object.keys(customCategories).map((key) => customCategories[key]),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hideRecent = true
|
this.hideRecent = true
|
||||||
|
@ -174,14 +193,7 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
this.setPreviewRef = this.setPreviewRef.bind(this)
|
this.setPreviewRef = this.setPreviewRef.bind(this)
|
||||||
this.handleSkinChange = this.handleSkinChange.bind(this)
|
this.handleSkinChange = this.handleSkinChange.bind(this)
|
||||||
this.handleKeyDown = this.handleKeyDown.bind(this)
|
this.handleKeyDown = this.handleKeyDown.bind(this)
|
||||||
}
|
this.handleDarkMatchMediaChange = this.handleDarkMatchMediaChange.bind(this)
|
||||||
|
|
||||||
componentWillReceiveProps(props) {
|
|
||||||
if (props.skin) {
|
|
||||||
this.setState({ skin: props.skin })
|
|
||||||
} else if (props.defaultSkin && !store.get('skin')) {
|
|
||||||
this.setState({ skin: props.defaultSkin })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -203,6 +215,10 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
|
|
||||||
clearTimeout(this.leaveTimeout)
|
clearTimeout(this.leaveTimeout)
|
||||||
clearTimeout(this.firstRenderTimeout)
|
clearTimeout(this.firstRenderTimeout)
|
||||||
|
|
||||||
|
if (this.darkMatchMedia) {
|
||||||
|
this.darkMatchMedia.removeListener(this.handleDarkMatchMediaChange)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testStickyPosition() {
|
testStickyPosition() {
|
||||||
|
@ -217,6 +233,24 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
this.hasStickyPosition = !!stickyTestElement.style.position.length
|
this.hasStickyPosition = !!stickyTestElement.style.position.length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPreferredTheme() {
|
||||||
|
if (this.props.theme != 'auto') return this.props.theme
|
||||||
|
if (this.state.theme) return this.state.theme
|
||||||
|
if (typeof matchMedia !== 'function') return PickerDefaultProps.theme
|
||||||
|
|
||||||
|
if (!this.darkMatchMedia) {
|
||||||
|
this.darkMatchMedia = matchMedia('(prefers-color-scheme: dark)')
|
||||||
|
this.darkMatchMedia.addListener(this.handleDarkMatchMediaChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.darkMatchMedia.media.match(/^not/)) return PickerDefaultProps.theme
|
||||||
|
return this.darkMatchMedia.matches ? 'dark' : 'light'
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDarkMatchMediaChange() {
|
||||||
|
this.setState({ theme: this.darkMatchMedia.matches ? 'dark' : 'light' })
|
||||||
|
}
|
||||||
|
|
||||||
handleEmojiOver(emoji) {
|
handleEmojiOver(emoji) {
|
||||||
var { preview } = this
|
var { preview } = this
|
||||||
if (!preview) {
|
if (!preview) {
|
||||||
|
@ -224,7 +258,7 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use Array.prototype.find() when it is more widely supported.
|
// Use Array.prototype.find() when it is more widely supported.
|
||||||
const emojiData = this.CUSTOM_CATEGORY.emojis.filter(
|
const emojiData = this.CUSTOM.filter(
|
||||||
(customEmoji) => customEmoji.id === emoji.id,
|
(customEmoji) => customEmoji.id === emoji.id,
|
||||||
)[0]
|
)[0]
|
||||||
for (let key in emojiData) {
|
for (let key in emojiData) {
|
||||||
|
@ -260,9 +294,11 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
var component = this.categoryRefs['category-1']
|
var component = this.categoryRefs['category-1']
|
||||||
if (component) {
|
if (component) {
|
||||||
let maxMargin = component.maxMargin
|
let maxMargin = component.maxMargin
|
||||||
component.forceUpdate()
|
if (this.props.enableFrequentEmojiSort) {
|
||||||
|
component.forceUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
window.requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
if (!this.scroll) return
|
if (!this.scroll) return
|
||||||
component.memoizeSize()
|
component.memoizeSize()
|
||||||
if (maxMargin == component.maxMargin) return
|
if (maxMargin == component.maxMargin) return
|
||||||
|
@ -280,7 +316,7 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
handleScroll() {
|
handleScroll() {
|
||||||
if (!this.waitingForPaint) {
|
if (!this.waitingForPaint) {
|
||||||
this.waitingForPaint = true
|
this.waitingForPaint = true
|
||||||
window.requestAnimationFrame(this.handleScrollPaint)
|
requestAnimationFrame(this.handleScrollPaint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,7 +420,7 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
this.handleSearch(null)
|
this.handleSearch(null)
|
||||||
this.search.clear()
|
this.search.clear()
|
||||||
|
|
||||||
window.requestAnimationFrame(scrollToComponent)
|
requestAnimationFrame(scrollToComponent)
|
||||||
} else {
|
} else {
|
||||||
scrollToComponent()
|
scrollToComponent()
|
||||||
}
|
}
|
||||||
|
@ -418,9 +454,9 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
))
|
))
|
||||||
) {
|
) {
|
||||||
this.handleEmojiSelect(emoji)
|
this.handleEmojiSelect(emoji)
|
||||||
|
handled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
handled = true
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,37 +510,45 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var {
|
var {
|
||||||
perLine,
|
perLine,
|
||||||
emojiSize,
|
emojiSize,
|
||||||
set,
|
set,
|
||||||
sheetSize,
|
sheetSize,
|
||||||
sheetColumns,
|
sheetColumns,
|
||||||
sheetRows,
|
sheetRows,
|
||||||
style,
|
style,
|
||||||
title,
|
title,
|
||||||
emoji,
|
emoji,
|
||||||
color,
|
color,
|
||||||
native,
|
native,
|
||||||
backgroundImageFn,
|
backgroundImageFn,
|
||||||
emojisToShowFilter,
|
emojisToShowFilter,
|
||||||
showPreview,
|
showPreview,
|
||||||
showSkinTones,
|
showSkinTones,
|
||||||
emojiTooltip,
|
emojiTooltip,
|
||||||
include,
|
useButton,
|
||||||
exclude,
|
include,
|
||||||
recent,
|
exclude,
|
||||||
autoFocus,
|
recent,
|
||||||
skinEmoji,
|
autoFocus,
|
||||||
notFound,
|
skinEmoji,
|
||||||
notFoundEmoji,
|
notFound,
|
||||||
} = this.props,
|
notFoundEmoji,
|
||||||
{ skin } = this.state,
|
maxResults,
|
||||||
width = perLine * (emojiSize + 12) + 12 + 2 + measureScrollbar()
|
} = this.props
|
||||||
|
|
||||||
|
var width = perLine * (emojiSize + 12) + 12 + 2 + measureScrollbar()
|
||||||
|
var theme = this.getPreferredTheme()
|
||||||
|
var skin =
|
||||||
|
this.props.skin ||
|
||||||
|
this.state.skin ||
|
||||||
|
store.get('skin') ||
|
||||||
|
this.props.defaultSkin
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
style={{ width: width, ...style }}
|
style={{ width: width, ...style }}
|
||||||
className="emoji-mart"
|
className={`emoji-mart emoji-mart-${theme}`}
|
||||||
aria-label={title}
|
aria-label={title}
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
>
|
>
|
||||||
|
@ -528,8 +572,9 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
emojisToShowFilter={emojisToShowFilter}
|
emojisToShowFilter={emojisToShowFilter}
|
||||||
include={include}
|
include={include}
|
||||||
exclude={exclude}
|
exclude={exclude}
|
||||||
custom={this.CUSTOM_CATEGORY.emojis}
|
custom={this.CUSTOM}
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
|
maxResults={maxResults}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -555,7 +600,7 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
}
|
}
|
||||||
custom={
|
custom={
|
||||||
category.id == this.RECENT_CATEGORY.id
|
category.id == this.RECENT_CATEGORY.id
|
||||||
? this.CUSTOM_CATEGORY.emojis
|
? this.CUSTOM
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
emojiProps={{
|
emojiProps={{
|
||||||
|
@ -569,6 +614,7 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
forceSize: native,
|
forceSize: native,
|
||||||
tooltip: emojiTooltip,
|
tooltip: emojiTooltip,
|
||||||
backgroundImageFn: backgroundImageFn,
|
backgroundImageFn: backgroundImageFn,
|
||||||
|
useButton: useButton,
|
||||||
onOver: this.handleEmojiOver,
|
onOver: this.handleEmojiOver,
|
||||||
onLeave: this.handleEmojiLeave,
|
onLeave: this.handleEmojiLeave,
|
||||||
onClick: this.handleEmojiClick,
|
onClick: this.handleEmojiClick,
|
||||||
|
|
|
@ -65,7 +65,9 @@ export default class Search extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange() {
|
handleChange() {
|
||||||
this.search(this.input.value)
|
if (this.input) {
|
||||||
|
this.search(this.input.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKeyUp(e) {
|
handleKeyUp(e) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ export default class SkinsDot extends Skins {
|
||||||
handleKeyDown(event) {
|
handleKeyDown(event) {
|
||||||
// if either enter or space is pressed, then execute
|
// if either enter or space is pressed, then execute
|
||||||
if (event.keyCode === 13 || event.keyCode === 32) {
|
if (event.keyCode === 13 || event.keyCode === 32) {
|
||||||
|
event.preventDefault()
|
||||||
this.handleClick(event)
|
this.handleClick(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import NimbleEmoji from './emoji/nimble-emoji'
|
|
||||||
|
|
||||||
export default class Skins extends React.PureComponent {
|
export default class Skins extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
export default function(instance, Constructor) {
|
|
||||||
if (!(instance instanceof Constructor)) {
|
|
||||||
throw new TypeError('Cannot call a class as a function')
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
const _Object = Object
|
|
||||||
|
|
||||||
export default (function createClass() {
|
|
||||||
function defineProperties(target, props) {
|
|
||||||
for (var i = 0; i < props.length; i++) {
|
|
||||||
var descriptor = props[i]
|
|
||||||
descriptor.enumerable = descriptor.enumerable || false
|
|
||||||
descriptor.configurable = true
|
|
||||||
if ('value' in descriptor) descriptor.writable = true
|
|
||||||
_Object.defineProperty(target, descriptor.key, descriptor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return function(Constructor, protoProps, staticProps) {
|
|
||||||
if (protoProps) defineProperties(Constructor.prototype, protoProps)
|
|
||||||
if (staticProps) defineProperties(Constructor, staticProps)
|
|
||||||
return Constructor
|
|
||||||
}
|
|
||||||
})()
|
|
|
@ -1,16 +0,0 @@
|
||||||
const _Object = Object
|
|
||||||
|
|
||||||
export default _Object.assign ||
|
|
||||||
function(target) {
|
|
||||||
for (var i = 1; i < arguments.length; i++) {
|
|
||||||
var source = arguments[i]
|
|
||||||
|
|
||||||
for (var key in source) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
||||||
target[key] = source[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return target
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
const _Object = Object
|
|
||||||
|
|
||||||
export default function inherits(subClass, superClass) {
|
|
||||||
if (typeof superClass !== 'function' && superClass !== null) {
|
|
||||||
throw new TypeError(
|
|
||||||
'Super expression must either be null or a function, not ' +
|
|
||||||
typeof superClass,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
subClass.prototype = _Object.create(superClass && superClass.prototype, {
|
|
||||||
constructor: {
|
|
||||||
value: subClass,
|
|
||||||
enumerable: false,
|
|
||||||
writable: true,
|
|
||||||
configurable: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if (superClass) {
|
|
||||||
_Object.setPrototypeOf
|
|
||||||
? _Object.setPrototypeOf(subClass, superClass)
|
|
||||||
: (subClass.__proto__ = superClass)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
|
|
||||||
var hasOwnProperty = Object.prototype.hasOwnProperty,
|
|
||||||
hasDontEnumBug = !{ toString: null }.propertyIsEnumerable('toString'),
|
|
||||||
dontEnums = [
|
|
||||||
'toString',
|
|
||||||
'toLocaleString',
|
|
||||||
'valueOf',
|
|
||||||
'hasOwnProperty',
|
|
||||||
'isPrototypeOf',
|
|
||||||
'propertyIsEnumerable',
|
|
||||||
'constructor',
|
|
||||||
],
|
|
||||||
dontEnumsLength = dontEnums.length
|
|
||||||
|
|
||||||
export default function(obj) {
|
|
||||||
if (typeof obj !== 'function' && (typeof obj !== 'object' || obj === null)) {
|
|
||||||
throw new TypeError('Object.keys called on non-object')
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = [],
|
|
||||||
prop,
|
|
||||||
i
|
|
||||||
|
|
||||||
for (prop in obj) {
|
|
||||||
if (hasOwnProperty.call(obj, prop)) {
|
|
||||||
result.push(prop)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasDontEnumBug) {
|
|
||||||
for (i = 0; i < dontEnumsLength; i++) {
|
|
||||||
if (hasOwnProperty.call(obj, dontEnums[i])) {
|
|
||||||
result.push(dontEnums[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
const _Object = Object
|
|
||||||
|
|
||||||
export default _Object.getPrototypeOf ||
|
|
||||||
function(O) {
|
|
||||||
O = Object(O)
|
|
||||||
|
|
||||||
if (typeof O.constructor === 'function' && O instanceof O.constructor) {
|
|
||||||
return O.constructor.prototype
|
|
||||||
}
|
|
||||||
|
|
||||||
return O instanceof Object ? Object.prototype : null
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
export default function possibleConstructorReturn(self, call) {
|
|
||||||
if (!self) {
|
|
||||||
throw new ReferenceError(
|
|
||||||
"this hasn't been initialised - super() hasn't been called",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return call && (typeof call === 'object' || typeof call === 'function')
|
|
||||||
? call
|
|
||||||
: self
|
|
||||||
}
|
|
|
@ -5,9 +5,7 @@ const mapping = {
|
||||||
has_img_apple: 'd',
|
has_img_apple: 'd',
|
||||||
has_img_google: 'e',
|
has_img_google: 'e',
|
||||||
has_img_twitter: 'f',
|
has_img_twitter: 'f',
|
||||||
has_img_emojione: 'g',
|
|
||||||
has_img_facebook: 'h',
|
has_img_facebook: 'h',
|
||||||
has_img_messenger: 'i',
|
|
||||||
keywords: 'j',
|
keywords: 'j',
|
||||||
sheet: 'k',
|
sheet: 'k',
|
||||||
emoticons: 'l',
|
emoticons: 'l',
|
||||||
|
|
|
@ -39,3 +39,13 @@ test('can search for woman-facepalming', () => {
|
||||||
'woman-facepalming',
|
'woman-facepalming',
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('emojiIndex exports emojis', () => {
|
||||||
|
const emojis = emojiIndex.emojis
|
||||||
|
expect(emojis['thinking_face'].native).toEqual('\ud83e\udd14')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('emojiIndex exports emoticons', () => {
|
||||||
|
const emoticons = emojiIndex.emoticons
|
||||||
|
expect(emoticons[':)']).toEqual('slightly_smiling_face')
|
||||||
|
})
|
||||||
|
|
|
@ -181,7 +181,11 @@ export default class NimbleEmojiIndex {
|
||||||
var aScore = scores[a.id],
|
var aScore = scores[a.id],
|
||||||
bScore = scores[b.id]
|
bScore = scores[b.id]
|
||||||
|
|
||||||
return aScore - bScore
|
if (aScore == bScore) {
|
||||||
|
return a.id.localeCompare(b.id)
|
||||||
|
} else {
|
||||||
|
return aScore - bScore
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { buildSearch } from './data'
|
||||||
import stringFromCodePoint from '../polyfills/stringFromCodePoint'
|
import stringFromCodePoint from '../polyfills/stringFromCodePoint'
|
||||||
import { uncompress } from './data'
|
import { uncompress } from './data'
|
||||||
|
|
||||||
const _JSON = JSON
|
|
||||||
|
|
||||||
const COLONS_REGEX = /^(?:\:([^\:]+)\:)(?:\:skin-tone-(\d)\:)?$/
|
const COLONS_REGEX = /^(?:\:([^\:]+)\:)(?:\:skin-tone-(\d)\:)?$/
|
||||||
const SKINS = ['1F3FA', '1F3FB', '1F3FC', '1F3FD', '1F3FE', '1F3FF']
|
const SKINS = ['1F3FA', '1F3FB', '1F3FC', '1F3FD', '1F3FE', '1F3FF']
|
||||||
|
|
||||||
|
@ -23,6 +21,7 @@ function sanitize(emoji) {
|
||||||
emoticons,
|
emoticons,
|
||||||
unified,
|
unified,
|
||||||
custom,
|
custom,
|
||||||
|
customCategory,
|
||||||
imageUrl,
|
imageUrl,
|
||||||
} = emoji,
|
} = emoji,
|
||||||
id = emoji.id || short_names[0],
|
id = emoji.id || short_names[0],
|
||||||
|
@ -36,6 +35,7 @@ function sanitize(emoji) {
|
||||||
colons,
|
colons,
|
||||||
emoticons,
|
emoticons,
|
||||||
custom,
|
custom,
|
||||||
|
customCategory,
|
||||||
imageUrl,
|
imageUrl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,32 +107,34 @@ function getData(emoji, skin, set, data) {
|
||||||
emojiData.variations || (emojiData.variations = [])
|
emojiData.variations || (emojiData.variations = [])
|
||||||
|
|
||||||
if (emojiData.skin_variations && skin > 1) {
|
if (emojiData.skin_variations && skin > 1) {
|
||||||
emojiData = JSON.parse(_JSON.stringify(emojiData))
|
emojiData = JSON.parse(JSON.stringify(emojiData))
|
||||||
|
|
||||||
var skinKey = SKINS[skin - 1],
|
var skinKey = SKINS[skin - 1],
|
||||||
variationData = emojiData.skin_variations[skinKey]
|
variationData = emojiData.skin_variations[skinKey]
|
||||||
|
|
||||||
if (!variationData.variations && emojiData.variations) {
|
if (variationData) {
|
||||||
delete emojiData.variations
|
if (!variationData.variations && emojiData.variations) {
|
||||||
}
|
delete emojiData.variations
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(set &&
|
(set &&
|
||||||
(variationData[`has_img_${set}`] == undefined ||
|
(variationData[`has_img_${set}`] == undefined ||
|
||||||
variationData[`has_img_${set}`])) ||
|
variationData[`has_img_${set}`])) ||
|
||||||
!set
|
!set
|
||||||
) {
|
) {
|
||||||
emojiData.skin_tone = skin
|
emojiData.skin_tone = skin
|
||||||
|
|
||||||
for (let k in variationData) {
|
for (let k in variationData) {
|
||||||
let v = variationData[k]
|
let v = variationData[k]
|
||||||
emojiData[k] = v
|
emojiData[k] = v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emojiData.variations && emojiData.variations.length) {
|
if (emojiData.variations && emojiData.variations.length) {
|
||||||
emojiData = JSON.parse(_JSON.stringify(emojiData))
|
emojiData = JSON.parse(JSON.stringify(emojiData))
|
||||||
emojiData.unified = emojiData.variations.shift()
|
emojiData.unified = emojiData.variations.shift()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,12 @@ const EmojiDefaultProps = {
|
||||||
skin: 1,
|
skin: 1,
|
||||||
set: 'apple',
|
set: 'apple',
|
||||||
sheetSize: 64,
|
sheetSize: 64,
|
||||||
sheetColumns: 52,
|
sheetColumns: 57,
|
||||||
sheetRows: 52,
|
sheetRows: 57,
|
||||||
native: false,
|
native: false,
|
||||||
forceSize: false,
|
forceSize: false,
|
||||||
tooltip: false,
|
tooltip: false,
|
||||||
|
useButton: true,
|
||||||
backgroundImageFn: (set, sheetSize) =>
|
backgroundImageFn: (set, sheetSize) =>
|
||||||
`https://unpkg.com/emoji-datasource-${set}@${EMOJI_DATASOURCE_VERSION}/img/${set}/sheets-256/${sheetSize}.png`,
|
`https://unpkg.com/emoji-datasource-${set}@${EMOJI_DATASOURCE_VERSION}/img/${set}/sheets-256/${sheetSize}.png`,
|
||||||
}
|
}
|
||||||
|
@ -23,6 +24,7 @@ const PickerDefaultProps = {
|
||||||
emoji: 'department_store',
|
emoji: 'department_store',
|
||||||
color: '#ae65c5',
|
color: '#ae65c5',
|
||||||
set: EmojiDefaultProps.set,
|
set: EmojiDefaultProps.set,
|
||||||
|
theme: 'light',
|
||||||
skin: null,
|
skin: null,
|
||||||
defaultSkin: EmojiDefaultProps.skin,
|
defaultSkin: EmojiDefaultProps.skin,
|
||||||
native: EmojiDefaultProps.native,
|
native: EmojiDefaultProps.native,
|
||||||
|
@ -32,7 +34,9 @@ const PickerDefaultProps = {
|
||||||
showPreview: true,
|
showPreview: true,
|
||||||
showSkinTones: true,
|
showSkinTones: true,
|
||||||
emojiTooltip: EmojiDefaultProps.tooltip,
|
emojiTooltip: EmojiDefaultProps.tooltip,
|
||||||
|
useButton: EmojiDefaultProps.useButton,
|
||||||
autoFocus: false,
|
autoFocus: false,
|
||||||
|
enableFrequentEmojiSort: false,
|
||||||
custom: [],
|
custom: [],
|
||||||
skinEmoji: '',
|
skinEmoji: '',
|
||||||
notFound: () => {},
|
notFound: () => {},
|
||||||
|
|
|
@ -10,18 +10,12 @@ const EmojiPropTypes = {
|
||||||
native: PropTypes.bool,
|
native: PropTypes.bool,
|
||||||
forceSize: PropTypes.bool,
|
forceSize: PropTypes.bool,
|
||||||
tooltip: PropTypes.bool,
|
tooltip: PropTypes.bool,
|
||||||
|
useButton: PropTypes.bool,
|
||||||
skin: PropTypes.oneOf([1, 2, 3, 4, 5, 6]),
|
skin: PropTypes.oneOf([1, 2, 3, 4, 5, 6]),
|
||||||
sheetSize: PropTypes.oneOf([16, 20, 32, 64]),
|
sheetSize: PropTypes.oneOf([16, 20, 32, 64]),
|
||||||
sheetColumns: PropTypes.number,
|
sheetColumns: PropTypes.number,
|
||||||
sheetRows: PropTypes.number,
|
sheetRows: PropTypes.number,
|
||||||
set: PropTypes.oneOf([
|
set: PropTypes.oneOf(['apple', 'google', 'twitter', 'facebook']),
|
||||||
'apple',
|
|
||||||
'google',
|
|
||||||
'twitter',
|
|
||||||
'emojione',
|
|
||||||
'messenger',
|
|
||||||
'facebook',
|
|
||||||
]),
|
|
||||||
size: PropTypes.number.isRequired,
|
size: PropTypes.number.isRequired,
|
||||||
emoji: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
|
emoji: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
|
||||||
}
|
}
|
||||||
|
@ -46,10 +40,13 @@ const PickerPropTypes = {
|
||||||
showPreview: PropTypes.bool,
|
showPreview: PropTypes.bool,
|
||||||
showSkinTones: PropTypes.bool,
|
showSkinTones: PropTypes.bool,
|
||||||
emojiTooltip: EmojiPropTypes.tooltip,
|
emojiTooltip: EmojiPropTypes.tooltip,
|
||||||
|
useButton: EmojiPropTypes.useButton,
|
||||||
|
theme: PropTypes.oneOf(['auto', 'light', 'dark']),
|
||||||
include: PropTypes.arrayOf(PropTypes.string),
|
include: PropTypes.arrayOf(PropTypes.string),
|
||||||
exclude: PropTypes.arrayOf(PropTypes.string),
|
exclude: PropTypes.arrayOf(PropTypes.string),
|
||||||
recent: PropTypes.arrayOf(PropTypes.string),
|
recent: PropTypes.arrayOf(PropTypes.string),
|
||||||
autoFocus: PropTypes.bool,
|
autoFocus: PropTypes.bool,
|
||||||
|
enableFrequentEmojiSort: PropTypes.bool,
|
||||||
custom: PropTypes.arrayOf(
|
custom: PropTypes.arrayOf(
|
||||||
PropTypes.shape({
|
PropTypes.shape({
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
var NAMESPACE = 'emoji-mart'
|
var NAMESPACE = 'emoji-mart'
|
||||||
|
|
||||||
const _JSON = JSON
|
|
||||||
|
|
||||||
var isLocalStorageSupported =
|
var isLocalStorageSupported =
|
||||||
typeof window !== 'undefined' && 'localStorage' in window
|
typeof window !== 'undefined' && 'localStorage' in window
|
||||||
|
|
||||||
|
@ -32,7 +30,7 @@ function set(key, value) {
|
||||||
} else {
|
} else {
|
||||||
if (!isLocalStorageSupported) return
|
if (!isLocalStorageSupported) return
|
||||||
try {
|
try {
|
||||||
window.localStorage[`${NAMESPACE}.${key}`] = _JSON.stringify(value)
|
window.localStorage[`${NAMESPACE}.${key}`] = JSON.stringify(value)
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,13 +42,13 @@ function get(key) {
|
||||||
if (!isLocalStorageSupported) return
|
if (!isLocalStorageSupported) return
|
||||||
try {
|
try {
|
||||||
var value = window.localStorage[`${NAMESPACE}.${key}`]
|
var value = window.localStorage[`${NAMESPACE}.${key}`]
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
return JSON.parse(value)
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value) {
|
|
||||||
return JSON.parse(value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
|
|
||||||
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
|
|
||||||
|
|
||||||
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
|
|
||||||
|
|
||||||
// MIT license
|
|
||||||
|
|
||||||
var isWindowAvailable = typeof window !== 'undefined'
|
|
||||||
|
|
||||||
isWindowAvailable &&
|
|
||||||
(function() {
|
|
||||||
var lastTime = 0
|
|
||||||
var vendors = ['ms', 'moz', 'webkit', 'o']
|
|
||||||
|
|
||||||
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
|
||||||
window.requestAnimationFrame =
|
|
||||||
window[vendors[x] + 'RequestAnimationFrame']
|
|
||||||
window.cancelAnimationFrame =
|
|
||||||
window[vendors[x] + 'CancelAnimationFrame'] ||
|
|
||||||
window[vendors[x] + 'CancelRequestAnimationFrame']
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!window.requestAnimationFrame)
|
|
||||||
window.requestAnimationFrame = function(callback, element) {
|
|
||||||
var currTime = new Date().getTime()
|
|
||||||
var timeToCall = Math.max(0, 16 - (currTime - lastTime))
|
|
||||||
var id = window.setTimeout(function() {
|
|
||||||
callback(currTime + timeToCall)
|
|
||||||
}, timeToCall)
|
|
||||||
|
|
||||||
lastTime = currTime + timeToCall
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!window.cancelAnimationFrame)
|
|
||||||
window.cancelAnimationFrame = function(id) {
|
|
||||||
clearTimeout(id)
|
|
||||||
}
|
|
||||||
})()
|
|
|
@ -11,11 +11,18 @@ import {
|
||||||
color,
|
color,
|
||||||
} from '@storybook/addon-knobs'
|
} from '@storybook/addon-knobs'
|
||||||
|
|
||||||
import { Picker, Emoji, emojiIndex, NimbleEmojiIndex, getEmojiDataFromNative } from '../dist'
|
import {
|
||||||
|
Picker,
|
||||||
|
Emoji,
|
||||||
|
emojiIndex,
|
||||||
|
NimbleEmojiIndex,
|
||||||
|
getEmojiDataFromNative,
|
||||||
|
} from '../dist'
|
||||||
import data from '../data/all.json'
|
import data from '../data/all.json'
|
||||||
import '../css/emoji-mart.css'
|
import '../css/emoji-mart.css'
|
||||||
|
|
||||||
const SETS = ['apple', 'google', 'twitter', 'emojione', 'messenger', 'facebook']
|
const THEMES = ['auto', 'light', 'dark']
|
||||||
|
const SETS = ['apple', 'google', 'twitter', 'facebook']
|
||||||
const CUSTOM_EMOJIS = [
|
const CUSTOM_EMOJIS = [
|
||||||
{
|
{
|
||||||
name: 'Octocat',
|
name: 'Octocat',
|
||||||
|
@ -31,6 +38,12 @@ const CUSTOM_EMOJIS = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const CUSTOM_EMOJIS_WITH_CATEGORIES = CUSTOM_EMOJIS.map((emoji) => {
|
||||||
|
return Object.assign({}, emoji, {
|
||||||
|
customCategory: emoji.name === 'Squirrel' ? 'Mammals' : 'Mollusks',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
storiesOf('Picker', module)
|
storiesOf('Picker', module)
|
||||||
.addDecorator(withKnobs)
|
.addDecorator(withKnobs)
|
||||||
.add('Default', () => (
|
.add('Default', () => (
|
||||||
|
@ -39,16 +52,19 @@ storiesOf('Picker', module)
|
||||||
onSelect={action('selected')}
|
onSelect={action('selected')}
|
||||||
onSkinChange={action('skin changed')}
|
onSkinChange={action('skin changed')}
|
||||||
native={boolean('Unicode', true)}
|
native={boolean('Unicode', true)}
|
||||||
|
theme={select('Theme', THEMES, THEMES[0])}
|
||||||
set={select('Emoji pack', SETS, SETS[0])}
|
set={select('Emoji pack', SETS, SETS[0])}
|
||||||
emojiSize={number('Emoji size', 24)}
|
emojiSize={number('Emoji size', 24)}
|
||||||
perLine={number('Per line', 9)}
|
perLine={number('Per line', 9, { min: 6 })}
|
||||||
title={text('Idle text', 'Your Title Here')}
|
title={text('Idle text', 'Your Title Here')}
|
||||||
emoji={text('Idle emoji', 'department_store')}
|
emoji={text('Idle emoji', 'department_store')}
|
||||||
notFoundEmoji={text('Not found emoji', 'sleuth_or_spy')}
|
notFoundEmoji={text('Not found emoji', 'sleuth_or_spy')}
|
||||||
defaultSkin={number('Default skin tone', 1)}
|
defaultSkin={number('Default skin tone', 1, { min: 1, max: 6 })}
|
||||||
color={color('Highlight color', '#ae65c5')}
|
color={color('Highlight color', '#ae65c5')}
|
||||||
showPreview={boolean('Show preview', true)}
|
showPreview={boolean('Show preview', true)}
|
||||||
showSkinTones={boolean('Show skin tones', true)}
|
showSkinTones={boolean('Show skin tones', true)}
|
||||||
|
enableFrequentEmojiSort={boolean('Enable frequent sort', false)}
|
||||||
|
useButton={false}
|
||||||
custom={CUSTOM_EMOJIS}
|
custom={CUSTOM_EMOJIS}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
@ -61,6 +77,10 @@ storiesOf('Picker', module)
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
|
||||||
|
.add('Custom categories', () => (
|
||||||
|
<Picker custom={CUSTOM_EMOJIS_WITH_CATEGORIES} />
|
||||||
|
))
|
||||||
|
|
||||||
.add('Custom category icons', () => (
|
.add('Custom category icons', () => (
|
||||||
<Picker
|
<Picker
|
||||||
custom={CUSTOM_EMOJIS}
|
custom={CUSTOM_EMOJIS}
|
||||||
|
@ -80,6 +100,17 @@ storiesOf('Picker', module)
|
||||||
<path d="M2.204 14.049c-.06.276-.091.56-.091.847 0 3.443 4.402 6.249 9.814 6.249 5.41 0 9.812-2.804 9.812-6.249 0-.274-.029-.546-.082-.809l-.015-.032c-.021-.055-.029-.11-.029-.165-.302-1.175-1.117-2.241-2.296-3.103-.045-.016-.088-.039-.126-.07-.026-.02-.045-.042-.067-.064-1.792-1.234-4.356-2.008-7.196-2.008-2.815 0-5.354.759-7.146 1.971-.014.018-.029.033-.049.049-.039.033-.084.06-.13.075-1.206.862-2.042 1.937-2.354 3.123 0 .058-.014.114-.037.171l-.008.015zm9.773 5.441c-1.794 0-3.057-.389-3.863-1.197-.173-.174-.173-.457 0-.632.176-.165.46-.165.635 0 .63.629 1.685.943 3.228.943 1.542 0 2.591-.3 3.219-.929.165-.164.45-.164.629 0 .165.18.165.465 0 .645-.809.808-2.065 1.198-3.862 1.198l.014-.028zm-3.606-7.573c-.914 0-1.677.765-1.677 1.677 0 .91.763 1.65 1.677 1.65s1.651-.74 1.651-1.65c0-.912-.739-1.677-1.651-1.677zm7.233 0c-.914 0-1.678.765-1.678 1.677 0 .91.764 1.65 1.678 1.65s1.651-.74 1.651-1.65c0-.912-.739-1.677-1.651-1.677zm4.548-1.595c1.037.833 1.8 1.821 2.189 2.904.45-.336.719-.864.719-1.449 0-1.002-.815-1.816-1.818-1.816-.399 0-.778.129-1.09.363v-.002zM2.711 9.963c-1.003 0-1.817.816-1.817 1.818 0 .543.239 1.048.644 1.389.401-1.079 1.172-2.053 2.213-2.876-.302-.21-.663-.329-1.039-.329v-.002zm9.217 12.079c-5.906 0-10.709-3.205-10.709-7.142 0-.275.023-.544.068-.809C.494 13.598 0 12.729 0 11.777c0-1.496 1.227-2.713 2.725-2.713.674 0 1.303.246 1.797.682 1.856-1.191 4.357-1.941 7.112-1.992l1.812-5.524.404.095s.016 0 .016.002l4.223.993c.344-.798 1.138-1.36 2.065-1.36 1.229 0 2.231 1.004 2.231 2.234 0 1.232-1.003 2.234-2.231 2.234s-2.23-1.004-2.23-2.23l-3.851-.912-1.467 4.477c2.65.105 5.047.854 6.844 2.021.494-.464 1.144-.719 1.833-.719 1.498 0 2.718 1.213 2.718 2.711 0 .987-.54 1.886-1.378 2.365.029.255.059.494.059.749-.015 3.938-4.806 7.143-10.72 7.143l-.034.009zm8.179-19.187c-.74 0-1.34.599-1.34 1.338 0 .738.6 1.34 1.34 1.34.732 0 1.33-.6 1.33-1.334 0-.733-.598-1.332-1.347-1.332l.017-.012z" />
|
<path d="M2.204 14.049c-.06.276-.091.56-.091.847 0 3.443 4.402 6.249 9.814 6.249 5.41 0 9.812-2.804 9.812-6.249 0-.274-.029-.546-.082-.809l-.015-.032c-.021-.055-.029-.11-.029-.165-.302-1.175-1.117-2.241-2.296-3.103-.045-.016-.088-.039-.126-.07-.026-.02-.045-.042-.067-.064-1.792-1.234-4.356-2.008-7.196-2.008-2.815 0-5.354.759-7.146 1.971-.014.018-.029.033-.049.049-.039.033-.084.06-.13.075-1.206.862-2.042 1.937-2.354 3.123 0 .058-.014.114-.037.171l-.008.015zm9.773 5.441c-1.794 0-3.057-.389-3.863-1.197-.173-.174-.173-.457 0-.632.176-.165.46-.165.635 0 .63.629 1.685.943 3.228.943 1.542 0 2.591-.3 3.219-.929.165-.164.45-.164.629 0 .165.18.165.465 0 .645-.809.808-2.065 1.198-3.862 1.198l.014-.028zm-3.606-7.573c-.914 0-1.677.765-1.677 1.677 0 .91.763 1.65 1.677 1.65s1.651-.74 1.651-1.65c0-.912-.739-1.677-1.651-1.677zm7.233 0c-.914 0-1.678.765-1.678 1.677 0 .91.764 1.65 1.678 1.65s1.651-.74 1.651-1.65c0-.912-.739-1.677-1.651-1.677zm4.548-1.595c1.037.833 1.8 1.821 2.189 2.904.45-.336.719-.864.719-1.449 0-1.002-.815-1.816-1.818-1.816-.399 0-.778.129-1.09.363v-.002zM2.711 9.963c-1.003 0-1.817.816-1.817 1.818 0 .543.239 1.048.644 1.389.401-1.079 1.172-2.053 2.213-2.876-.302-.21-.663-.329-1.039-.329v-.002zm9.217 12.079c-5.906 0-10.709-3.205-10.709-7.142 0-.275.023-.544.068-.809C.494 13.598 0 12.729 0 11.777c0-1.496 1.227-2.713 2.725-2.713.674 0 1.303.246 1.797.682 1.856-1.191 4.357-1.941 7.112-1.992l1.812-5.524.404.095s.016 0 .016.002l4.223.993c.344-.798 1.138-1.36 2.065-1.36 1.229 0 2.231 1.004 2.231 2.234 0 1.232-1.003 2.234-2.231 2.234s-2.23-1.004-2.23-2.23l-3.851-.912-1.467 4.477c2.65.105 5.047.854 6.844 2.021.494-.464 1.144-.719 1.833-.719 1.498 0 2.718 1.213 2.718 2.711 0 .987-.54 1.886-1.378 2.365.029.255.059.494.059.749-.015 3.938-4.806 7.143-10.72 7.143l-.034.009zm8.179-19.187c-.74 0-1.34.599-1.34 1.338 0 .738.6 1.34 1.34 1.34.732 0 1.33-.6 1.33-1.334 0-.733-.598-1.332-1.347-1.332l.017-.012z" />
|
||||||
</svg>
|
</svg>
|
||||||
),
|
),
|
||||||
|
people: () => (
|
||||||
|
<svg
|
||||||
|
aria-labelledby="simpleicons-reddit-icon"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<title id="simpleicons-reddit-icon">Reddit icon</title>
|
||||||
|
<path d="M2.204 14.049c-.06.276-.091.56-.091.847 0 3.443 4.402 6.249 9.814 6.249 5.41 0 9.812-2.804 9.812-6.249 0-.274-.029-.546-.082-.809l-.015-.032c-.021-.055-.029-.11-.029-.165-.302-1.175-1.117-2.241-2.296-3.103-.045-.016-.088-.039-.126-.07-.026-.02-.045-.042-.067-.064-1.792-1.234-4.356-2.008-7.196-2.008-2.815 0-5.354.759-7.146 1.971-.014.018-.029.033-.049.049-.039.033-.084.06-.13.075-1.206.862-2.042 1.937-2.354 3.123 0 .058-.014.114-.037.171l-.008.015zm9.773 5.441c-1.794 0-3.057-.389-3.863-1.197-.173-.174-.173-.457 0-.632.176-.165.46-.165.635 0 .63.629 1.685.943 3.228.943 1.542 0 2.591-.3 3.219-.929.165-.164.45-.164.629 0 .165.18.165.465 0 .645-.809.808-2.065 1.198-3.862 1.198l.014-.028zm-3.606-7.573c-.914 0-1.677.765-1.677 1.677 0 .91.763 1.65 1.677 1.65s1.651-.74 1.651-1.65c0-.912-.739-1.677-1.651-1.677zm7.233 0c-.914 0-1.678.765-1.678 1.677 0 .91.764 1.65 1.678 1.65s1.651-.74 1.651-1.65c0-.912-.739-1.677-1.651-1.677zm4.548-1.595c1.037.833 1.8 1.821 2.189 2.904.45-.336.719-.864.719-1.449 0-1.002-.815-1.816-1.818-1.816-.399 0-.778.129-1.09.363v-.002zM2.711 9.963c-1.003 0-1.817.816-1.817 1.818 0 .543.239 1.048.644 1.389.401-1.079 1.172-2.053 2.213-2.876-.302-.21-.663-.329-1.039-.329v-.002zm9.217 12.079c-5.906 0-10.709-3.205-10.709-7.142 0-.275.023-.544.068-.809C.494 13.598 0 12.729 0 11.777c0-1.496 1.227-2.713 2.725-2.713.674 0 1.303.246 1.797.682 1.856-1.191 4.357-1.941 7.112-1.992l1.812-5.524.404.095s.016 0 .016.002l4.223.993c.344-.798 1.138-1.36 2.065-1.36 1.229 0 2.231 1.004 2.231 2.234 0 1.232-1.003 2.234-2.231 2.234s-2.23-1.004-2.23-2.23l-3.851-.912-1.467 4.477c2.65.105 5.047.854 6.844 2.021.494-.464 1.144-.719 1.833-.719 1.498 0 2.718 1.213 2.718 2.711 0 .987-.54 1.886-1.378 2.365.029.255.059.494.059.749-.015 3.938-4.806 7.143-10.72 7.143l-.034.009zm8.179-19.187c-.74 0-1.34.599-1.34 1.338 0 .738.6 1.34 1.34 1.34.732 0 1.33-.6 1.33-1.334 0-.733-.598-1.332-1.347-1.332l.017-.012z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
nature: () => (
|
nature: () => (
|
||||||
<svg
|
<svg
|
||||||
version="1.1"
|
version="1.1"
|
||||||
|
@ -249,14 +280,10 @@ storiesOf('Get emoji data from Native', module)
|
||||||
const emojiData = getEmojiDataFromNative(
|
const emojiData = getEmojiDataFromNative(
|
||||||
text('Unicode', '🏋🏿♂️'),
|
text('Unicode', '🏋🏿♂️'),
|
||||||
select('Emoji pack', SETS, SETS[0]),
|
select('Emoji pack', SETS, SETS[0]),
|
||||||
data
|
data,
|
||||||
)
|
)
|
||||||
if (!emojiData) {
|
if (!emojiData) {
|
||||||
return (
|
return <div>Couldn`t find any emoji data from native...</div>
|
||||||
<div>
|
|
||||||
Couldn`t find any emoji data from native...
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -268,9 +295,7 @@ storiesOf('Get emoji data from Native', module)
|
||||||
size={48}
|
size={48}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<pre>
|
<pre>emojiData: {JSON.stringify(emojiData, null, 2)}</pre>
|
||||||
emojiData: {JSON.stringify(emojiData, null, 2)}
|
|
||||||
</pre>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Simple smoke-test to make sure that SSR is working correctly
|
||||||
|
const ReactDOMServer = require('react-dom/server')
|
||||||
|
const React = require('react')
|
||||||
|
const { Picker, NimblePicker } = require('../dist/index.js')
|
||||||
|
const data = require('../data/all.json')
|
||||||
|
|
||||||
|
function testPicker() {
|
||||||
|
const element = React.createElement(Picker)
|
||||||
|
const string = ReactDOMServer.renderToString(element)
|
||||||
|
|
||||||
|
if (typeof string !== 'string') {
|
||||||
|
throw new Error('expected a string')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testNimblePicker() {
|
||||||
|
const element = React.createElement(NimblePicker, { data })
|
||||||
|
const string = ReactDOMServer.renderToString(element)
|
||||||
|
|
||||||
|
if (typeof string !== 'string') {
|
||||||
|
throw new Error('expected a string')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testPicker()
|
||||||
|
testNimblePicker()
|
Loading…
Reference in New Issue