diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..b429316
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,2 @@
+[*]
+indent_size = 2
diff --git a/.gitignore b/.gitignore
index a45ab12..5483f76 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ dist-es/
dist-modern/
stats.json
report.html
+package-lock.json
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..cda0efc
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,10 @@
+language: node_js
+node_js:
+- 10
+sudo: false
+script: yarn test
+before_script:
+- yarn prettier:check
+branches:
+ only:
+ - master
diff --git a/README.md b/README.md
index 5c0c963..4e16bdf 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
Emoji Mart is a Slack-like customizable
emoji picker component for React
Demo •
Changelog
+
Brought to you by the
Missive team
@@ -405,6 +406,13 @@ Apple / Google / Twitter / EmojiOne / Messenger / Facebook
## Not opinionated
**Emoji Mart** doesn’t automatically insert anything into a text input, nor does it show or hide itself. It simply returns an `emoji` object. It’s up to the developer to mount/unmount (it’s fast!) and position the picker. You can use the returned object as props for the `EmojiMart.Emoji` component. You could also use `emoji.colons` to insert text into a textarea or `emoji.native` to use the emoji.
+## Usage outside React
+
+**Emoji Mart** can be used with React alternatives such as [Preact](https://preactjs.com/), [Inferno](https://www.infernojs.org/), and [react-lite](https://github.com/Lucifier129/react-lite).
+
+Furthermore, you can use it as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) using [remount](https://github.com/rstacruz/remount), meaning that you can use it within any JavaScript framework (or vanilla JS).
+
+For an end-to-end example of how to do this, see [emoji-mart-outside-react](https://github.com/nolanlawson/emoji-mart-outside-react).
## Optimizing for production
diff --git a/package.json b/package.json
index 54c6c57..da04a31 100644
--- a/package.json
+++ b/package.json
@@ -49,7 +49,7 @@
"inflection": "1.10.0",
"jest": "^23.0.0",
"mkdirp": "0.5.1",
- "prettier": "1.11.1",
+ "prettier": "^1.16.4",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-test-renderer": "^16.8.4",
@@ -76,6 +76,7 @@
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
"prettier": "prettier --write \"{src,scripts}/**/*.js\"",
+ "prettier:check": "prettier --check \"{src,scripts}/**/*.js\"",
"prepare": "npm run build:dist"
},
"size-limit": [
diff --git a/src/components/category.js b/src/components/category.js
index 31beaa3..26e08b8 100644
--- a/src/components/category.js
+++ b/src/components/category.js
@@ -210,16 +210,15 @@ export default class Category extends React.Component {
))}
- {emojis &&
- !emojis.length && (
-
- )}
+ {emojis && !emojis.length && (
+
+ )}
)
}
diff --git a/src/components/search.js b/src/components/search.js
index b8cbfc8..6aec93f 100644
--- a/src/components/search.js
+++ b/src/components/search.js
@@ -94,9 +94,9 @@ export default class Search extends React.PureComponent {
autoFocus={autoFocus}
/>
{/*
- * Use a
in addition to the placeholder for accessibility, but place it off-screen
- * http://www.maxability.co.in/2016/01/placeholder-attribute-and-why-it-is-not-accessible/
- */}
+ * Use a in addition to the placeholder for accessibility, but place it off-screen
+ * http://www.maxability.co.in/2016/01/placeholder-attribute-and-why-it-is-not-accessible/
+ */}
{i18n.search}
diff --git a/src/polyfills/stringFromCodePoint.js b/src/polyfills/stringFromCodePoint.js
index 7e3f078..6b58dc9 100644
--- a/src/polyfills/stringFromCodePoint.js
+++ b/src/polyfills/stringFromCodePoint.js
@@ -30,7 +30,7 @@ export default _String.fromCodePoint ||
// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
codePoint -= 0x10000
highSurrogate = (codePoint >> 10) + 0xd800
- lowSurrogate = codePoint % 0x400 + 0xdc00
+ lowSurrogate = (codePoint % 0x400) + 0xdc00
codeUnits.push(highSurrogate, lowSurrogate)
}
if (index + 1 === length || codeUnits.length > MAX_SIZE) {
diff --git a/src/utils/emoji-index/__tests__/nimble-emoji-index.test.js b/src/utils/emoji-index/__tests__/nimble-emoji-index.test.js
new file mode 100644
index 0000000..a0f18d6
--- /dev/null
+++ b/src/utils/emoji-index/__tests__/nimble-emoji-index.test.js
@@ -0,0 +1,24 @@
+import NimbleEmojiIndex from '../nimble-emoji-index.js'
+import store from '../../store'
+
+import data from '../../../../data/all'
+
+const nimbleEmojiIndex = new NimbleEmojiIndex(data)
+
+function getEmojiData(skinTone) {
+ store.update({ skin: skinTone })
+
+ return nimbleEmojiIndex.search('thumbsup')[0]
+}
+
+test('should return emojis with skin tone 1', () => {
+ const skinTone = 1
+ const emoji = getEmojiData(skinTone)
+ expect(emoji.skin).toEqual(skinTone)
+})
+
+test('should return emojis with skin tone 6', () => {
+ const skinTone = 6
+ const emoji = getEmojiData(skinTone)
+ expect(emoji.skin).toEqual(skinTone)
+})
diff --git a/src/utils/emoji-index/nimble-emoji-index.js b/src/utils/emoji-index/nimble-emoji-index.js
index 8b1bdc3..42f2bfb 100644
--- a/src/utils/emoji-index/nimble-emoji-index.js
+++ b/src/utils/emoji-index/nimble-emoji-index.js
@@ -1,13 +1,15 @@
import { getData, getSanitizedData, intersect } from '..'
import { uncompress } from '../data'
+import store from '../store'
export default class NimbleEmojiIndex {
- constructor(data) {
+ constructor(data, set) {
if (data.compressed) {
uncompress(data)
}
this.data = data || {}
+ this.set = set || null
this.originalPool = {}
this.index = {}
this.emojis = {}
@@ -20,7 +22,7 @@ export default class NimbleEmojiIndex {
buildIndex() {
for (let emoji in this.data.emojis) {
let emojiData = this.data.emojis[emoji],
- { short_names, emoticons } = emojiData,
+ { short_names, emoticons, skin_variations } = emojiData,
id = short_names[0]
if (emoticons) {
@@ -33,7 +35,21 @@ export default class NimbleEmojiIndex {
})
}
- this.emojis[id] = getSanitizedData(id, null, null, this.data)
+ // If skin variations include them
+ if (skin_variations) {
+ this.emojis[id] = {}
+ for (let skinTone = 1; skinTone <= 6; skinTone++) {
+ this.emojis[id][skinTone] = getSanitizedData(
+ { id, skin: skinTone },
+ skinTone,
+ this.set,
+ this.data,
+ )
+ }
+ } else {
+ this.emojis[id] = getSanitizedData(id, null, this.set, this.data)
+ }
+
this.originalPool[id] = emojiData
}
}
@@ -70,6 +86,8 @@ export default class NimbleEmojiIndex {
if (this.customEmojisList != custom)
this.addCustomToPool(custom, this.originalPool)
+ const skinTone = store.get('skin') || 1
+
maxResults || (maxResults = 75)
include || (include = [])
exclude || (exclude = [])
@@ -79,7 +97,7 @@ export default class NimbleEmojiIndex {
if (value.length) {
if (value == '-' || value == '-1') {
- return [this.emojis['-1']]
+ return [this.emojis['-1'][skinTone]]
}
var values = value.toLowerCase().split(/[\s|,|\-|_]+/),
@@ -148,7 +166,11 @@ export default class NimbleEmojiIndex {
let score = subIndex + 1
if (sub == id) score = 0
- aIndex.results.push(this.emojis[id])
+ if (this.emojis[id] && this.emojis[id][skinTone]) {
+ aIndex.results.push(this.emojis[id][skinTone])
+ } else {
+ aIndex.results.push(this.emojis[id])
+ }
aIndex.pool[id] = emoji
scores[id] = score
diff --git a/src/utils/index.js b/src/utils/index.js
index 33e444a..2551dff 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -32,6 +32,7 @@ function sanitize(emoji) {
return {
id,
name,
+ short_names,
colons,
emoticons,
custom,
@@ -104,7 +105,7 @@ function getData(emoji, skin, set, data) {
emojiData.emoticons || (emojiData.emoticons = [])
emojiData.variations || (emojiData.variations = [])
- if (emojiData.skin_variations && skin > 1 && set) {
+ if (emojiData.skin_variations && skin > 1) {
emojiData = JSON.parse(_JSON.stringify(emojiData))
var skinKey = SKINS[skin - 1],
@@ -115,8 +116,10 @@ function getData(emoji, skin, set, data) {
}
if (
- variationData[`has_img_${set}`] == undefined ||
- variationData[`has_img_${set}`]
+ (set &&
+ (variationData[`has_img_${set}`] == undefined ||
+ variationData[`has_img_${set}`])) ||
+ !set
) {
emojiData.skin_tone = skin
diff --git a/stories/index.js b/stories/index.js
index 9fccb9d..248e630 100644
--- a/stories/index.js
+++ b/stories/index.js
@@ -11,7 +11,7 @@ import {
color,
} from '@storybook/addon-knobs'
-import { Picker, Emoji, emojiIndex, getEmojiDataFromNative } from '../dist'
+import { Picker, Emoji, emojiIndex, NimbleEmojiIndex, getEmojiDataFromNative } from '../dist'
import data from '../data/all.json'
import '../css/emoji-mart.css'
@@ -216,6 +216,33 @@ storiesOf('Headless Search', module)
)
})
+ .add('With skin tone from store', () => {
+ const nimbleEmojiIndex = new NimbleEmojiIndex(data)
+ let results = nimbleEmojiIndex.search(text('Search', 'thumbs'), {
+ custom: CUSTOM_EMOJIS,
+ })
+ if (!results) {
+ return null
+ }
+
+ return (
+
+ {results.map((emoji) => {
+ return (
+
+
+
+ )
+ })}
+
+ )
+ })
+
storiesOf('Get emoji data from Native', module)
.addDecorator(withKnobs)
.add('Default', () => {
diff --git a/yarn.lock b/yarn.lock
index 0f87bf2..f01f8c1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6805,10 +6805,10 @@ preserve@^0.2.0:
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
-prettier@1.11.1:
- version "1.11.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.11.1.tgz#61e43fc4cd44e68f2b0dfc2c38cd4bb0fccdcc75"
- integrity sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==
+prettier@^1.16.4:
+ version "1.16.4"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.4.tgz#73e37e73e018ad2db9c76742e2647e21790c9717"
+ integrity sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==
pretty-error@^2.0.2:
version "2.1.1"