Merge remote-tracking branch 'emojimart/master' into get_emoji_data_from_native

nolan/issue-325
Peder Johnsen 2019-03-23 20:35:16 +00:00
commit a8c491273c
13 changed files with 125 additions and 28 deletions

2
.editorconfig Normal file
View File

@ -0,0 +1,2 @@
[*]
indent_size = 2

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ dist-es/
dist-modern/
stats.json
report.html
package-lock.json

10
.travis.yml Normal file
View File

@ -0,0 +1,10 @@
language: node_js
node_js:
- 10
sudo: false
script: yarn test
before_script:
- yarn prettier:check
branches:
only:
- master

View File

@ -1,6 +1,7 @@
<div align="center">
<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/releases">Changelog</a>
<br><a href="https://travis-ci.org/nolanlawson/emoji-mart"><img src="https://travis-ci.org/nolanlawson/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><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
@ -405,6 +406,13 @@ Apple / Google / Twitter / EmojiOne / Messenger / Facebook
## Not opinionated
**Emoji Mart** doesnt automatically insert anything into a text input, nor does it show or hide itself. It simply returns an `emoji` object. Its up to the developer to mount/unmount (its 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

View File

@ -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": [

View File

@ -210,16 +210,15 @@ export default class Category extends React.Component {
))}
</ul>
{emojis &&
!emojis.length && (
<NotFound
i18n={i18n}
notFound={notFound}
notFoundEmoji={notFoundEmoji}
data={this.data}
emojiProps={emojiProps}
/>
)}
{emojis && !emojis.length && (
<NotFound
i18n={i18n}
notFound={notFound}
notFoundEmoji={notFoundEmoji}
data={this.data}
emojiProps={emojiProps}
/>
)}
</section>
)
}

View File

@ -94,9 +94,9 @@ export default class Search extends React.PureComponent {
autoFocus={autoFocus}
/>
{/*
* Use a <label> 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 <label> 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/
*/}
<label className="emoji-mart-sr-only" htmlFor={inputId}>
{i18n.search}
</label>

View File

@ -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) {

View File

@ -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)
})

View File

@ -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

View File

@ -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

View File

@ -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 (
<div>
{results.map((emoji) => {
return (
<span key={emoji.id} style={{ marginLeft: '1.4em' }}>
<Emoji
native={true}
emoji={emoji}
skin={emoji.skin || 1}
size={48}
/>
</span>
)
})}
</div>
)
})
storiesOf('Get emoji data from Native', module)
.addDecorator(withKnobs)
.add('Default', () => {

View File

@ -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"