Merge pull request #178 from davidcilley/less-destructive-add-data-prop
Add parent components and data property for components that reference data.js Issue#86release
commit
1edf3eaa96
|
@ -3,4 +3,3 @@ dist/
|
|||
dist-es/
|
||||
stats.json
|
||||
report.html
|
||||
/src/data/data.js
|
||||
|
|
65
README.md
65
README.md
|
@ -73,32 +73,36 @@ categories: {
|
|||
#### Sheet sizes
|
||||
Sheets are served from [unpkg](https://unpkg.com), a global CDN that serves files published to [npm](https://www.npmjs.com).
|
||||
|
||||
| Set | sheetSize | Size |
|
||||
| --------- | --------- | -------- |
|
||||
| apple | 16 | 334 KB |
|
||||
| apple | 20 | 459 KB |
|
||||
| apple | 32 | 1.08 MB |
|
||||
| apple | 64 | 2.94 MB |
|
||||
| emojione | 16 | 315 KB |
|
||||
| emojione | 20 | 435 KB |
|
||||
| emojione | 32 | 1020 KB |
|
||||
| emojione | 64 | 2.33 MB |
|
||||
| facebook | 16 | 322 KB |
|
||||
| facebook | 20 | 439 KB |
|
||||
| facebook | 32 | 1020 KB |
|
||||
| facebook | 64 | 2.5 MB |
|
||||
| google | 16 | 301 KB |
|
||||
| google | 20 | 409 KB |
|
||||
| google | 32 | 907 KB |
|
||||
| google | 64 | 2.17 MB |
|
||||
| messenger | 16 | 325 KB |
|
||||
| messenger | 20 | 449 MB |
|
||||
| messenger | 32 | 1.05 MB |
|
||||
| messenger | 64 | 2.69 MB |
|
||||
| twitter | 16 | 288 KB |
|
||||
| twitter | 20 | 389 KB |
|
||||
| twitter | 32 | 839 KB |
|
||||
| twitter | 64 | 1.82 MB |
|
||||
| Set | Size (`sheetSize: 16`) | Size (`sheetSize: 20`) | Size (`sheetSize: 32`) | Size (`sheetSize: 64`) |
|
||||
| --------- | ---------------------- | ---------------------- | ---------------------- | ---------------------- |
|
||||
| apple | 334 KB | 459 KB | 1.08 MB | 2.94 MB |
|
||||
| emojione | 315 KB | 435 KB | 1020 KB | 2.33 MB |
|
||||
| facebook | 322 KB | 439 KB | 1020 KB | 2.50 MB |
|
||||
| google | 301 KB | 409 KB | 907 KB | 2.17 MB |
|
||||
| messenger | 325 KB | 449 MB | 1.05 MB | 2.69 MB |
|
||||
| twitter | 288 KB | 389 KB | 839 KB | 1.82 MB |
|
||||
|
||||
#### 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.
|
||||
|
||||
| Set | Size |
|
||||
| --------- | ------ |
|
||||
| all | 551 KB |
|
||||
| apple | 465 KB |
|
||||
| emojione | 226 KB |
|
||||
| facebook | 405 KB |
|
||||
| google | 450 KB |
|
||||
| messenger | 197 KB |
|
||||
| twitter | 466 KB |
|
||||
|
||||
To use these data files (or any other custom data), use the `NimblePicker` component:
|
||||
|
||||
```js
|
||||
import data from 'emoji-mart/data/messenger.json'
|
||||
import { NimblePicker } from 'emoji-mart'
|
||||
|
||||
<NimblePicker set='messenger' data={data} />
|
||||
```
|
||||
|
||||
#### Examples of `emoji` object:
|
||||
```js
|
||||
|
@ -240,6 +244,15 @@ emojiIndex.search('christmas').map((o) => o.native)
|
|||
// => [🎄, 🎅🏼, 🔔, 🎁, ⛄️, ❄️]
|
||||
```
|
||||
|
||||
### 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
|
||||
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.
|
||||
|
||||
|
|
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
3439
docs/bundle.js
3439
docs/bundle.js
File diff suppressed because one or more lines are too long
|
@ -60,13 +60,13 @@
|
|||
"webpack": "^3.6.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rm -rf dist/ dist-es/ src/data/data.js",
|
||||
"clean": "rm -rf dist/ dist-es/",
|
||||
"build:data": "node scripts/build-data",
|
||||
"build:dist": "npm run build:cjs && npm run build:es",
|
||||
"build:cjs": "BABEL_ENV=cjs babel src --out-dir dist --copy-files",
|
||||
"build:es": "babel src --out-dir dist-es --copy-files",
|
||||
"build:docs": "cp css/emoji-mart.css docs && webpack --config ./docs/webpack.config.js",
|
||||
"build": "npm run clean && npm run build:data && npm run build:dist",
|
||||
"build": "npm run clean && npm run build:dist",
|
||||
"watch": "BABEL_ENV=cjs babel src --watch --out-dir dist --copy-files",
|
||||
"start": "npm run watch",
|
||||
"stats": "webpack --config ./spec/webpack.config.js --json > spec/stats.json",
|
||||
|
@ -77,7 +77,7 @@
|
|||
"prepublishOnly": "npm run build",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"build-storybook": "build-storybook",
|
||||
"prettier": "prettier --write \"{src,spec}/**/*.js\""
|
||||
"prettier": "prettier --write \"{src,scripts,spec}/**/*.js\""
|
||||
},
|
||||
"size-limit": [
|
||||
{
|
||||
|
|
|
@ -1,107 +1,11 @@
|
|||
var fs = require('fs'),
|
||||
emojiData = require('emoji-datasource'),
|
||||
emojiLib = require('emojilib'),
|
||||
inflection = require('inflection'),
|
||||
mkdirp = require('mkdirp')
|
||||
const build = require('./build')
|
||||
const sets = ['apple', 'emojione', 'facebook', 'google', 'messenger', 'twitter']
|
||||
|
||||
var data = { categories: [], emojis: {}, skins: {}, short_names: {} },
|
||||
categoriesIndex = {}
|
||||
build({ output: 'data/all.json' })
|
||||
|
||||
var categories = [
|
||||
['Smileys & People', 'people'],
|
||||
['Animals & Nature', 'nature'],
|
||||
['Food & Drink', 'foods'],
|
||||
['Activities', 'activity'],
|
||||
['Travel & Places', 'places'],
|
||||
['Objects', 'objects'],
|
||||
['Symbols', 'symbols'],
|
||||
['Flags', 'flags'],
|
||||
]
|
||||
|
||||
categories.forEach((category, i) => {
|
||||
let [name, id] = category
|
||||
data.categories[i] = { id: id, name: name, emojis: [] }
|
||||
categoriesIndex[name] = i
|
||||
})
|
||||
|
||||
emojiData.sort((a, b) => {
|
||||
var aTest = a.sort_order || a.short_name,
|
||||
bTest = b.sort_order || b.short_name
|
||||
|
||||
return aTest - bTest
|
||||
})
|
||||
|
||||
emojiData.forEach((datum) => {
|
||||
var category = datum.category,
|
||||
keywords = [],
|
||||
categoryIndex
|
||||
|
||||
if (!datum.category) {
|
||||
throw new Error('“' + datum.short_name + '” doesn’t have a category')
|
||||
}
|
||||
|
||||
datum.name || (datum.name = datum.short_name.replace(/\-/g, ' '))
|
||||
datum.name = inflection.titleize(datum.name || '')
|
||||
|
||||
if (!datum.name) {
|
||||
throw new Error('“' + datum.short_name + '” doesn’t have a name')
|
||||
}
|
||||
|
||||
datum.emoticons = datum.texts || []
|
||||
datum.text = datum.text || ''
|
||||
delete datum.texts
|
||||
|
||||
if (emojiLib.lib[datum.short_name]) {
|
||||
datum.keywords = emojiLib.lib[datum.short_name].keywords
|
||||
}
|
||||
|
||||
if (datum.category == 'Skin Tones') {
|
||||
data.skins[datum.short_name] = datum
|
||||
} else {
|
||||
categoryIndex = categoriesIndex[category]
|
||||
data.categories[categoryIndex].emojis.push(datum.short_name)
|
||||
data.emojis[datum.short_name] = datum
|
||||
}
|
||||
|
||||
datum.short_names.forEach((short_name, i) => {
|
||||
if (i == 0) { return }
|
||||
data.short_names[short_name] = datum.short_name
|
||||
sets.forEach((set) => {
|
||||
build({
|
||||
output: `data/${set}.json`,
|
||||
sets: [set],
|
||||
})
|
||||
|
||||
datum.short_names = datum.short_names.filter(i => i !== datum.short_name)
|
||||
datum.sheet = [datum.sheet_x, datum.sheet_y]
|
||||
|
||||
if (datum.text === '') delete datum.text
|
||||
if (datum.added_in === '6.0') delete datum.added_in
|
||||
|
||||
delete datum.docomo
|
||||
delete datum.au
|
||||
delete datum.softbank
|
||||
delete datum.google
|
||||
delete datum.image
|
||||
delete datum.short_name
|
||||
delete datum.category
|
||||
delete datum.sort_order
|
||||
delete datum.sheet_x
|
||||
delete datum.sheet_y
|
||||
|
||||
for (let key in datum) {
|
||||
let value = datum[key]
|
||||
|
||||
if (Array.isArray(value) && !value.length) {
|
||||
delete datum[key]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
var flags = data.categories[categoriesIndex['Flags']]
|
||||
flags.emojis = flags.emojis.filter((flag) => {
|
||||
// Until browsers support Flag UN
|
||||
if (flag == 'flag-un') return
|
||||
return true
|
||||
}).sort()
|
||||
|
||||
const stringified = JSON.stringify(data).replace(/\"([A-Za-z_]+)\":/g, '$1:')
|
||||
fs.writeFile('src/data/data.js', `export default ${stringified}`, (err) => {
|
||||
if (err) throw err
|
||||
})
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
var fs = require('fs'),
|
||||
emojiLib = require('emojilib'),
|
||||
inflection = require('inflection'),
|
||||
mkdirp = require('mkdirp')
|
||||
|
||||
var { compress } = require('../src/utils/data')
|
||||
|
||||
var categories = [
|
||||
['Smileys & People', 'people'],
|
||||
['Animals & Nature', 'nature'],
|
||||
['Food & Drink', 'foods'],
|
||||
['Activities', 'activity'],
|
||||
['Travel & Places', 'places'],
|
||||
['Objects', 'objects'],
|
||||
['Symbols', 'symbols'],
|
||||
['Flags', 'flags'],
|
||||
]
|
||||
|
||||
var sets = ['apple', 'emojione', 'facebook', 'google', 'messenger', 'twitter']
|
||||
|
||||
module.exports = (options) => {
|
||||
delete require.cache[require.resolve('emoji-datasource')]
|
||||
var emojiData = require('emoji-datasource')
|
||||
|
||||
var data = { compressed: true, categories: [], emojis: {}, aliases: {} },
|
||||
categoriesIndex = {}
|
||||
|
||||
categories.forEach((category, i) => {
|
||||
let [name, id] = category
|
||||
data.categories[i] = { id: id, name: name, emojis: [] }
|
||||
categoriesIndex[name] = i
|
||||
})
|
||||
|
||||
emojiData.sort((a, b) => {
|
||||
var aTest = a.sort_order || a.short_name,
|
||||
bTest = b.sort_order || b.short_name
|
||||
|
||||
return aTest - bTest
|
||||
})
|
||||
|
||||
emojiData.forEach((datum) => {
|
||||
var category = datum.category,
|
||||
keywords = [],
|
||||
categoryIndex
|
||||
|
||||
if (!datum.category) {
|
||||
throw new Error('“' + datum.short_name + '” doesn’t have a category')
|
||||
}
|
||||
|
||||
if (options.sets) {
|
||||
var keepEmoji = false
|
||||
|
||||
options.sets.forEach((set) => {
|
||||
if (keepEmoji) return
|
||||
if (datum[`has_img_${set}`]) {
|
||||
keepEmoji = true
|
||||
}
|
||||
})
|
||||
|
||||
if (!keepEmoji) {
|
||||
return
|
||||
}
|
||||
|
||||
sets.forEach((set) => {
|
||||
if (options.sets.length == 1 || options.sets.indexOf(set) == -1) {
|
||||
var key = `has_img_${set}`
|
||||
delete datum[key]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
datum.name || (datum.name = datum.short_name.replace(/\-/g, ' '))
|
||||
datum.name = inflection.titleize(datum.name || '')
|
||||
|
||||
if (!datum.name) {
|
||||
throw new Error('“' + datum.short_name + '” doesn’t have a name')
|
||||
}
|
||||
|
||||
datum.emoticons = datum.texts || []
|
||||
datum.text = datum.text || ''
|
||||
delete datum.texts
|
||||
|
||||
if (emojiLib.lib[datum.short_name]) {
|
||||
datum.keywords = emojiLib.lib[datum.short_name].keywords
|
||||
}
|
||||
|
||||
if (datum.category != 'Skin Tones') {
|
||||
categoryIndex = categoriesIndex[category]
|
||||
data.categories[categoryIndex].emojis.push(datum.short_name)
|
||||
data.emojis[datum.short_name] = datum
|
||||
}
|
||||
|
||||
datum.short_names.forEach((short_name, i) => {
|
||||
if (i == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
data.aliases[short_name] = datum.short_name
|
||||
})
|
||||
|
||||
delete datum.docomo
|
||||
delete datum.au
|
||||
delete datum.softbank
|
||||
delete datum.google
|
||||
delete datum.image
|
||||
delete datum.category
|
||||
delete datum.sort_order
|
||||
|
||||
compress(datum)
|
||||
})
|
||||
|
||||
var flags = data.categories[categoriesIndex['Flags']]
|
||||
flags.emojis = flags.emojis
|
||||
.filter((flag) => {
|
||||
// Until browsers support Flag UN
|
||||
if (flag == 'flag-un') return
|
||||
return true
|
||||
})
|
||||
.sort()
|
||||
|
||||
fs.writeFile(options.output, JSON.stringify(data), (err) => {
|
||||
if (err) throw err
|
||||
})
|
||||
}
|
|
@ -2,5 +2,5 @@ var pack = require('../package.json')
|
|||
|
||||
module.exports = {
|
||||
'process.env.NODE_ENV': 'production',
|
||||
EMOJI_DATASOURCE_VERSION: pack.devDependencies['emoji-datasource']
|
||||
EMOJI_DATASOURCE_VERSION: pack.devDependencies['emoji-datasource'],
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import emojiIndex from '../src/utils/emoji-index'
|
||||
import emojiIndex from '../src/utils/emoji-index/emoji-index'
|
||||
|
||||
describe('#emojiIndex', () => {
|
||||
describe('search', function() {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import React from 'react'
|
||||
import TestUtils from 'react-dom/test-utils'
|
||||
import Picker from '../src/components/picker'
|
||||
|
||||
import data from '../data/all.json'
|
||||
import { NimblePicker } from '../src/components'
|
||||
|
||||
const { click } = TestUtils.Simulate
|
||||
|
||||
|
@ -11,11 +13,11 @@ const {
|
|||
} = TestUtils
|
||||
|
||||
const render = (props = {}) => {
|
||||
const defaultProps = {}
|
||||
return renderIntoDocument(<Picker {...defaultProps} {...props} />)
|
||||
const defaultProps = { data }
|
||||
return renderIntoDocument(<NimblePicker {...defaultProps} {...props} />)
|
||||
}
|
||||
|
||||
describe('Picker', () => {
|
||||
describe('NimblePicker', () => {
|
||||
let subject
|
||||
|
||||
it('works', () => {
|
||||
|
|
|
@ -3,12 +3,13 @@ import PropTypes from 'prop-types'
|
|||
|
||||
import frequently from '../utils/frequently'
|
||||
import { getData } from '../utils'
|
||||
import { Emoji } from '.'
|
||||
import { NimbleEmoji } from '.'
|
||||
|
||||
export default class Category extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.data = props.data
|
||||
this.setContainerRef = this.setContainerRef.bind(this)
|
||||
this.setLabelRef = this.setLabelRef.bind(this)
|
||||
}
|
||||
|
@ -109,7 +110,7 @@ export default class Category extends React.Component {
|
|||
|
||||
return id
|
||||
})
|
||||
.filter((id) => !!getData(id))
|
||||
.filter((id) => !!getData(id, null, null, this.data))
|
||||
}
|
||||
|
||||
if (emojis.length === 0 && frequentlyUsed.length > 0) {
|
||||
|
@ -184,13 +185,16 @@ export default class Category extends React.Component {
|
|||
</div>
|
||||
|
||||
{emojis &&
|
||||
emojis.map((emoji) => Emoji({ emoji: emoji, ...emojiProps }))}
|
||||
emojis.map((emoji) =>
|
||||
NimbleEmoji({ emoji: emoji, data: this.data, ...emojiProps }),
|
||||
)}
|
||||
|
||||
{emojis &&
|
||||
!emojis.length && (
|
||||
<div>
|
||||
<div>
|
||||
{Emoji({
|
||||
{NimbleEmoji({
|
||||
data: this.data,
|
||||
...emojiProps,
|
||||
size: 38,
|
||||
emoji: 'sleuth_or_spy',
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import React from 'react'
|
||||
|
||||
import data from '../../../data/all.json'
|
||||
import NimbleEmoji from './nimble-emoji'
|
||||
|
||||
import { EmojiPropTypes, EmojiDefaultProps } from '../../utils/shared-props'
|
||||
|
||||
const Emoji = (props) => {
|
||||
for (let k in Emoji.defaultProps) {
|
||||
if (props[k] == undefined && Emoji.defaultProps[k] != undefined) {
|
||||
props[k] = Emoji.defaultProps[k]
|
||||
}
|
||||
}
|
||||
|
||||
return NimbleEmoji({ ...props })
|
||||
}
|
||||
|
||||
Emoji.propTypes = EmojiPropTypes
|
||||
Emoji.defaultProps = { ...EmojiDefaultProps, data }
|
||||
|
||||
export default Emoji
|
|
@ -1,11 +1,17 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import data from '../data'
|
||||
|
||||
import { getData, getSanitizedData, unifiedToNative } from '../utils'
|
||||
import { getData, getSanitizedData, unifiedToNative } from '../../utils'
|
||||
import { uncompress } from '../../utils/data'
|
||||
import { EmojiPropTypes, EmojiDefaultProps } from '../../utils/shared-props'
|
||||
|
||||
const SHEET_COLUMNS = 52
|
||||
|
||||
const _getData = (props) => {
|
||||
var { emoji, skin, set, data } = props
|
||||
return getData(emoji, skin, set, data)
|
||||
}
|
||||
|
||||
const _getPosition = (props) => {
|
||||
var { sheet_x, sheet_y } = _getData(props),
|
||||
multiply = 100 / (SHEET_COLUMNS - 1)
|
||||
|
@ -13,14 +19,9 @@ const _getPosition = (props) => {
|
|||
return `${multiply * sheet_x}% ${multiply * sheet_y}%`
|
||||
}
|
||||
|
||||
const _getData = (props) => {
|
||||
var { emoji, skin, set } = props
|
||||
return getData(emoji, skin, set)
|
||||
}
|
||||
|
||||
const _getSanitizedData = (props) => {
|
||||
var { emoji, skin, set } = props
|
||||
return getSanitizedData(emoji, skin, set)
|
||||
var { emoji, skin, set, data } = props
|
||||
return getSanitizedData(emoji, skin, set, data)
|
||||
}
|
||||
|
||||
const _handleClick = (e, props) => {
|
||||
|
@ -73,10 +74,14 @@ const _convertStyleToCSS = (style) => {
|
|||
return div.getAttribute('style')
|
||||
}
|
||||
|
||||
const Emoji = (props) => {
|
||||
for (let k in Emoji.defaultProps) {
|
||||
if (props[k] == undefined && Emoji.defaultProps[k] != undefined) {
|
||||
props[k] = Emoji.defaultProps[k]
|
||||
const NimbleEmoji = (props) => {
|
||||
if (props.data.compressed) {
|
||||
uncompress(props.data)
|
||||
}
|
||||
|
||||
for (let k in NimbleEmoji.defaultProps) {
|
||||
if (props[k] == undefined && NimbleEmoji.defaultProps[k] != undefined) {
|
||||
props[k] = NimbleEmoji.defaultProps[k]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +124,8 @@ const Emoji = (props) => {
|
|||
backgroundSize: 'contain',
|
||||
}
|
||||
} else {
|
||||
let setHasEmoji = _getData(props)[`has_img_${props.set}`]
|
||||
let setHasEmoji =
|
||||
data[`has_img_${props.set}`] == undefined || data[`has_img_${props.set}`]
|
||||
|
||||
if (!setHasEmoji) {
|
||||
if (props.fallback) {
|
||||
|
@ -163,41 +169,7 @@ const Emoji = (props) => {
|
|||
}
|
||||
}
|
||||
|
||||
Emoji.propTypes = {
|
||||
onOver: PropTypes.func,
|
||||
onLeave: PropTypes.func,
|
||||
onClick: PropTypes.func,
|
||||
fallback: PropTypes.func,
|
||||
backgroundImageFn: PropTypes.func,
|
||||
native: PropTypes.bool,
|
||||
forceSize: PropTypes.bool,
|
||||
tooltip: PropTypes.bool,
|
||||
skin: PropTypes.oneOf([1, 2, 3, 4, 5, 6]),
|
||||
sheetSize: PropTypes.oneOf([16, 20, 32, 64]),
|
||||
set: PropTypes.oneOf([
|
||||
'apple',
|
||||
'google',
|
||||
'twitter',
|
||||
'emojione',
|
||||
'messenger',
|
||||
'facebook',
|
||||
]),
|
||||
size: PropTypes.number.isRequired,
|
||||
emoji: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
|
||||
}
|
||||
NimbleEmoji.propTypes = { ...EmojiPropTypes, data: PropTypes.object.isRequired }
|
||||
NimbleEmoji.defaultProps = EmojiDefaultProps
|
||||
|
||||
Emoji.defaultProps = {
|
||||
skin: 1,
|
||||
set: 'apple',
|
||||
sheetSize: 64,
|
||||
native: false,
|
||||
forceSize: false,
|
||||
tooltip: false,
|
||||
backgroundImageFn: (set, sheetSize) =>
|
||||
`https://unpkg.com/emoji-datasource-${set}@${EMOJI_DATASOURCE_VERSION}/img/${set}/sheets-256/${sheetSize}.png`,
|
||||
onOver: () => {},
|
||||
onLeave: () => {},
|
||||
onClick: () => {},
|
||||
}
|
||||
|
||||
export default Emoji
|
||||
export default NimbleEmoji
|
|
@ -1,7 +1,11 @@
|
|||
export { default as Anchors } from './anchors'
|
||||
export { default as Category } from './category'
|
||||
export { default as Emoji } from './emoji'
|
||||
export { default as Picker } from './picker'
|
||||
export { default as Preview } from './preview'
|
||||
export { default as Search } from './search'
|
||||
export { default as Skins } from './skins'
|
||||
|
||||
export { default as Emoji } from './emoji/emoji'
|
||||
export { default as NimbleEmoji } from './emoji/nimble-emoji'
|
||||
|
||||
export { default as Picker } from './picker/picker'
|
||||
export { default as NimblePicker } from './picker/nimble-picker'
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import '../vendor/raf-polyfill'
|
||||
import '../../vendor/raf-polyfill'
|
||||
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import data from '../data'
|
||||
|
||||
import store from '../utils/store'
|
||||
import frequently from '../utils/frequently'
|
||||
import { deepMerge, measureScrollbar } from '../utils'
|
||||
import store from '../../utils/store'
|
||||
import frequently from '../../utils/frequently'
|
||||
import { deepMerge, measureScrollbar } from '../../utils'
|
||||
import { uncompress } from '../../utils/data'
|
||||
import { PickerPropTypes, PickerDefaultProps } from '../../utils/shared-props'
|
||||
|
||||
import { Anchors, Category, Emoji, Preview, Search } from '.'
|
||||
import { Anchors, Category, Preview, Search } from '..'
|
||||
|
||||
const I18N = {
|
||||
search: 'Search',
|
||||
|
@ -28,7 +29,7 @@ const I18N = {
|
|||
},
|
||||
}
|
||||
|
||||
export default class Picker extends React.PureComponent {
|
||||
export default class NimblePicker extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
|
@ -41,6 +42,11 @@ export default class Picker extends React.PureComponent {
|
|||
anchor: false,
|
||||
}
|
||||
|
||||
if (props.data.compressed) {
|
||||
uncompress(props.data)
|
||||
}
|
||||
|
||||
this.data = props.data
|
||||
this.i18n = deepMerge(I18N, props.i18n)
|
||||
this.state = {
|
||||
skin: props.skin || store.get('skin') || props.defaultSkin,
|
||||
|
@ -48,7 +54,7 @@ export default class Picker extends React.PureComponent {
|
|||
}
|
||||
|
||||
this.categories = []
|
||||
let allCategories = [].concat(data.categories)
|
||||
let allCategories = [].concat(this.data.categories)
|
||||
|
||||
if (props.custom.length > 0) {
|
||||
this.CUSTOM_CATEGORY.emojis = props.custom.map((emoji) => {
|
||||
|
@ -99,7 +105,7 @@ export default class Picker extends React.PureComponent {
|
|||
const { emojis } = category
|
||||
for (let emojiIndex = 0; emojiIndex < emojis.length; emojiIndex++) {
|
||||
const emoji = emojis[emojiIndex]
|
||||
if (props.emojisToShowFilter(data.emojis[emoji] || emoji)) {
|
||||
if (props.emojisToShowFilter(this.data.emojis[emoji] || emoji)) {
|
||||
newEmojis.push(emoji)
|
||||
}
|
||||
}
|
||||
|
@ -474,6 +480,7 @@ export default class Picker extends React.PureComponent {
|
|||
<div className="emoji-mart-bar">
|
||||
<Anchors
|
||||
ref={this.setAnchorsRef}
|
||||
data={this.data}
|
||||
i18n={this.i18n}
|
||||
color={color}
|
||||
categories={this.categories}
|
||||
|
@ -484,6 +491,7 @@ export default class Picker extends React.PureComponent {
|
|||
<Search
|
||||
ref={this.setSearchRef}
|
||||
onSearch={this.handleSearch}
|
||||
data={this.data}
|
||||
i18n={this.i18n}
|
||||
emojisToShowFilter={emojisToShowFilter}
|
||||
include={include}
|
||||
|
@ -508,6 +516,7 @@ export default class Picker extends React.PureComponent {
|
|||
perLine={perLine}
|
||||
native={native}
|
||||
hasStickyPosition={this.hasStickyPosition}
|
||||
data={this.data}
|
||||
i18n={this.i18n}
|
||||
recent={
|
||||
category.id == this.RECENT_CATEGORY.id ? recent : undefined
|
||||
|
@ -539,6 +548,7 @@ export default class Picker extends React.PureComponent {
|
|||
<div className="emoji-mart-bar">
|
||||
<Preview
|
||||
ref={this.setPreviewRef}
|
||||
data={this.data}
|
||||
title={title}
|
||||
emoji={emoji}
|
||||
showSkinTones={showSkinTones}
|
||||
|
@ -562,62 +572,8 @@ export default class Picker extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
Picker.propTypes = {
|
||||
onClick: PropTypes.func,
|
||||
onSelect: PropTypes.func,
|
||||
onSkinChange: PropTypes.func,
|
||||
perLine: PropTypes.number,
|
||||
emojiSize: PropTypes.number,
|
||||
i18n: PropTypes.object,
|
||||
style: PropTypes.object,
|
||||
title: PropTypes.string,
|
||||
emoji: PropTypes.string,
|
||||
color: PropTypes.string,
|
||||
set: Emoji.propTypes.set,
|
||||
skin: Emoji.propTypes.skin,
|
||||
native: PropTypes.bool,
|
||||
backgroundImageFn: Emoji.propTypes.backgroundImageFn,
|
||||
sheetSize: Emoji.propTypes.sheetSize,
|
||||
emojisToShowFilter: PropTypes.func,
|
||||
showPreview: PropTypes.bool,
|
||||
showSkinTones: PropTypes.bool,
|
||||
emojiTooltip: Emoji.propTypes.tooltip,
|
||||
include: PropTypes.arrayOf(PropTypes.string),
|
||||
exclude: PropTypes.arrayOf(PropTypes.string),
|
||||
recent: PropTypes.arrayOf(PropTypes.string),
|
||||
autoFocus: PropTypes.bool,
|
||||
custom: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
short_names: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
emoticons: PropTypes.arrayOf(PropTypes.string),
|
||||
keywords: PropTypes.arrayOf(PropTypes.string),
|
||||
imageUrl: PropTypes.string.isRequired,
|
||||
}),
|
||||
),
|
||||
}
|
||||
|
||||
Picker.defaultProps = {
|
||||
onClick: () => {},
|
||||
onSelect: () => {},
|
||||
onSkinChange: () => {},
|
||||
emojiSize: 24,
|
||||
perLine: 9,
|
||||
i18n: {},
|
||||
style: {},
|
||||
title: 'Emoji Mart™',
|
||||
emoji: 'department_store',
|
||||
color: '#ae65c5',
|
||||
set: Emoji.defaultProps.set,
|
||||
skin: null,
|
||||
defaultSkin: Emoji.defaultProps.skin,
|
||||
native: Emoji.defaultProps.native,
|
||||
sheetSize: Emoji.defaultProps.sheetSize,
|
||||
backgroundImageFn: Emoji.defaultProps.backgroundImageFn,
|
||||
emojisToShowFilter: null,
|
||||
showPreview: true,
|
||||
showSkinTones: true,
|
||||
emojiTooltip: Emoji.defaultProps.tooltip,
|
||||
autoFocus: false,
|
||||
custom: [],
|
||||
NimblePicker.propTypes = {
|
||||
...PickerPropTypes,
|
||||
data: PropTypes.object.isRequired,
|
||||
}
|
||||
NimblePicker.defaultProps = { ...PickerDefaultProps }
|
|
@ -0,0 +1,15 @@
|
|||
import React from 'react'
|
||||
|
||||
import data from '../../../data/all.json'
|
||||
import NimblePicker from './nimble-picker'
|
||||
|
||||
import { PickerPropTypes, PickerDefaultProps } from '../../utils/shared-props'
|
||||
|
||||
export default class Picker extends React.PureComponent {
|
||||
render() {
|
||||
return <NimblePicker {...this.props} {...this.state} />
|
||||
}
|
||||
}
|
||||
|
||||
Picker.propTypes = PickerPropTypes
|
||||
Picker.defaultProps = { ...PickerDefaultProps, data }
|
|
@ -1,12 +1,14 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { Emoji, Skins } from '.'
|
||||
import { getData } from '../utils'
|
||||
import { NimbleEmoji, Skins } from '.'
|
||||
|
||||
export default class Preview extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.data = props.data
|
||||
this.state = { emoji: null }
|
||||
}
|
||||
|
||||
|
@ -21,7 +23,7 @@ export default class Preview extends React.PureComponent {
|
|||
} = this.props
|
||||
|
||||
if (emoji) {
|
||||
var emojiData = getData(emoji),
|
||||
var emojiData = getData(emoji, null, null, this.data),
|
||||
{ emoticons = [] } = emojiData,
|
||||
knownEmoticons = [],
|
||||
listedEmoticons = []
|
||||
|
@ -38,7 +40,12 @@ export default class Preview extends React.PureComponent {
|
|||
return (
|
||||
<div className="emoji-mart-preview">
|
||||
<div className="emoji-mart-preview-emoji">
|
||||
{Emoji({ key: emoji.id, emoji: emoji, ...emojiProps })}
|
||||
{NimbleEmoji({
|
||||
key: emoji.id,
|
||||
emoji: emoji,
|
||||
data: this.data,
|
||||
...emojiProps,
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="emoji-mart-preview-data">
|
||||
|
@ -66,7 +73,7 @@ export default class Preview extends React.PureComponent {
|
|||
<div className="emoji-mart-preview-emoji">
|
||||
{idleEmoji &&
|
||||
idleEmoji.length &&
|
||||
Emoji({ emoji: idleEmoji, ...emojiProps })}
|
||||
NimbleEmoji({ emoji: idleEmoji, data: this.data, ...emojiProps })}
|
||||
</div>
|
||||
|
||||
<div className="emoji-mart-preview-data">
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import emojiIndex from '../utils/emoji-index'
|
||||
|
||||
import NimbleEmojiIndex from '../utils/emoji-index/nimble-emoji-index'
|
||||
|
||||
export default class Search extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.data = props.data
|
||||
this.emojiIndex = new NimbleEmojiIndex(this.data)
|
||||
this.setRef = this.setRef.bind(this)
|
||||
this.handleChange = this.handleChange.bind(this)
|
||||
}
|
||||
|
@ -14,7 +17,7 @@ export default class Search extends React.PureComponent {
|
|||
var value = this.input.value
|
||||
|
||||
this.props.onSearch(
|
||||
emojiIndex.search(value, {
|
||||
this.emojiIndex.search(value, {
|
||||
emojisToShowFilter: this.props.emojisToShowFilter,
|
||||
maxResults: this.props.maxResults,
|
||||
include: this.props.include,
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
import buildSearch from '../utils/build-search'
|
||||
import data from './data'
|
||||
|
||||
function uncompress(list) {
|
||||
for (var short_name in list) {
|
||||
var datum = list[short_name]
|
||||
|
||||
if (!datum.short_names) datum.short_names = []
|
||||
datum.short_names.unshift(short_name)
|
||||
|
||||
datum.sheet_x = datum.sheet[0]
|
||||
datum.sheet_y = datum.sheet[1]
|
||||
delete datum.sheet
|
||||
|
||||
if (!datum.text) datum.text = ''
|
||||
if (datum.added_in !== null && !datum.added_in) datum.added_in = '6.0'
|
||||
|
||||
datum.search = buildSearch({
|
||||
short_names: datum.short_names,
|
||||
name: datum.name,
|
||||
keywords: datum.keywords,
|
||||
emoticons: datum.emoticons,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
uncompress(data.emojis)
|
||||
uncompress(data.skins)
|
||||
|
||||
export default data
|
12
src/index.js
12
src/index.js
|
@ -1,6 +1,14 @@
|
|||
import emojiIndex from './utils/emoji-index'
|
||||
import emojiIndex from './utils/emoji-index/emoji-index'
|
||||
import store from './utils/store'
|
||||
import frequently from './utils/frequently'
|
||||
|
||||
export { Picker, Emoji, Category } from './components'
|
||||
export {
|
||||
Picker,
|
||||
NimblePicker,
|
||||
Emoji,
|
||||
NimbleEmoji,
|
||||
Category,
|
||||
} from './components'
|
||||
|
||||
export { NimbleEmojiIndex } from './utils/emoji-index/nimble-emoji-index'
|
||||
export { emojiIndex, store, frequently }
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
export default (data) => {
|
||||
const search = []
|
||||
|
||||
var addToSearch = (strings, split) => {
|
||||
if (!strings) {
|
||||
return
|
||||
}
|
||||
|
||||
;(Array.isArray(strings) ? strings : [strings]).forEach((string) => {
|
||||
;(split ? string.split(/[-|_|\s]+/) : [string]).forEach((s) => {
|
||||
s = s.toLowerCase()
|
||||
|
||||
if (search.indexOf(s) == -1) {
|
||||
search.push(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
addToSearch(data.short_names, true)
|
||||
addToSearch(data.name, true)
|
||||
addToSearch(data.keywords, false)
|
||||
addToSearch(data.emoticons, false)
|
||||
|
||||
return search.join(',')
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
const mapping = {
|
||||
name: 'a',
|
||||
unified: 'b',
|
||||
non_qualified: 'c',
|
||||
has_img_apple: 'd',
|
||||
has_img_google: 'e',
|
||||
has_img_twitter: 'f',
|
||||
has_img_emojione: 'g',
|
||||
has_img_facebook: 'h',
|
||||
has_img_messenger: 'i',
|
||||
keywords: 'j',
|
||||
sheet: 'k',
|
||||
emoticons: 'l',
|
||||
text: 'm',
|
||||
short_names: 'n',
|
||||
added_in: 'o',
|
||||
}
|
||||
|
||||
const buildSearch = (emoji) => {
|
||||
const search = []
|
||||
|
||||
var addToSearch = (strings, split) => {
|
||||
if (!strings) {
|
||||
return
|
||||
}
|
||||
|
||||
;(Array.isArray(strings) ? strings : [strings]).forEach((string) => {
|
||||
;(split ? string.split(/[-|_|\s]+/) : [string]).forEach((s) => {
|
||||
s = s.toLowerCase()
|
||||
|
||||
if (search.indexOf(s) == -1) {
|
||||
search.push(s)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
addToSearch(emoji.short_names, true)
|
||||
addToSearch(emoji.name, true)
|
||||
addToSearch(emoji.keywords, false)
|
||||
addToSearch(emoji.emoticons, false)
|
||||
|
||||
return search.join(',')
|
||||
}
|
||||
|
||||
const compress = (emoji) => {
|
||||
emoji.short_names = emoji.short_names.filter((short_name) => {
|
||||
return short_name !== emoji.short_name
|
||||
})
|
||||
delete emoji.short_name
|
||||
|
||||
emoji.sheet = [emoji.sheet_x, emoji.sheet_y]
|
||||
delete emoji.sheet_x
|
||||
delete emoji.sheet_y
|
||||
|
||||
emoji.added_in = parseInt(emoji.added_in)
|
||||
if (emoji.added_in === 6) {
|
||||
delete emoji.added_in
|
||||
}
|
||||
|
||||
for (let key in mapping) {
|
||||
emoji[mapping[key]] = emoji[key]
|
||||
delete emoji[key]
|
||||
}
|
||||
|
||||
for (let key in emoji) {
|
||||
let value = emoji[key]
|
||||
|
||||
if (Array.isArray(value) && !value.length) {
|
||||
delete emoji[key]
|
||||
} else if (typeof value === 'string' && !value.length) {
|
||||
delete emoji[key]
|
||||
} else if (value === null) {
|
||||
delete emoji[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uncompress = (data) => {
|
||||
data.compressed = false
|
||||
|
||||
for (let id in data.emojis) {
|
||||
let emoji = data.emojis[id]
|
||||
|
||||
for (let key in mapping) {
|
||||
emoji[key] = emoji[mapping[key]]
|
||||
delete emoji[mapping[key]]
|
||||
}
|
||||
|
||||
if (!emoji.short_names) emoji.short_names = []
|
||||
emoji.short_names.unshift(id)
|
||||
|
||||
emoji.sheet_x = emoji.sheet[0]
|
||||
emoji.sheet_y = emoji.sheet[1]
|
||||
delete emoji.sheet
|
||||
|
||||
if (!emoji.text) emoji.text = ''
|
||||
|
||||
if (!emoji.added_in) emoji.added_in = 6
|
||||
emoji.added_in = emoji.added_in.toFixed(1)
|
||||
|
||||
emoji.search = buildSearch(emoji)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { buildSearch, compress, uncompress }
|
|
@ -1,180 +0,0 @@
|
|||
import data from '../data'
|
||||
import { getData, getSanitizedData, intersect } from '.'
|
||||
|
||||
var originalPool = {}
|
||||
var index = {}
|
||||
var emojisList = {}
|
||||
var emoticonsList = {}
|
||||
var customEmojisList = []
|
||||
|
||||
for (let emoji in data.emojis) {
|
||||
let emojiData = data.emojis[emoji],
|
||||
{ short_names, emoticons } = emojiData,
|
||||
id = short_names[0]
|
||||
|
||||
if (emoticons) {
|
||||
emoticons.forEach((emoticon) => {
|
||||
if (emoticonsList[emoticon]) {
|
||||
return
|
||||
}
|
||||
|
||||
emoticonsList[emoticon] = id
|
||||
})
|
||||
}
|
||||
|
||||
emojisList[id] = getSanitizedData(id)
|
||||
originalPool[id] = emojiData
|
||||
}
|
||||
|
||||
function clearCustomEmojis(pool) {
|
||||
customEmojisList.forEach((emoji) => {
|
||||
let emojiId = emoji.id || emoji.short_names[0]
|
||||
|
||||
delete pool[emojiId]
|
||||
delete emojisList[emojiId]
|
||||
})
|
||||
}
|
||||
|
||||
function addCustomToPool(custom, pool) {
|
||||
if (customEmojisList.length) clearCustomEmojis(pool)
|
||||
|
||||
custom.forEach((emoji) => {
|
||||
let emojiId = emoji.id || emoji.short_names[0]
|
||||
|
||||
if (emojiId && !pool[emojiId]) {
|
||||
pool[emojiId] = getData(emoji)
|
||||
emojisList[emojiId] = getSanitizedData(emoji)
|
||||
}
|
||||
})
|
||||
|
||||
customEmojisList = custom
|
||||
index = {}
|
||||
}
|
||||
|
||||
function search(
|
||||
value,
|
||||
{ emojisToShowFilter, maxResults, include, exclude, custom = [] } = {},
|
||||
) {
|
||||
if (customEmojisList != custom) addCustomToPool(custom, originalPool)
|
||||
|
||||
maxResults || (maxResults = 75)
|
||||
include || (include = [])
|
||||
exclude || (exclude = [])
|
||||
|
||||
var results = null,
|
||||
pool = originalPool
|
||||
|
||||
if (value.length) {
|
||||
if (value == '-' || value == '-1') {
|
||||
return [emojisList['-1']]
|
||||
}
|
||||
|
||||
var values = value.toLowerCase().split(/[\s|,|\-|_]+/),
|
||||
allResults = []
|
||||
|
||||
if (values.length > 2) {
|
||||
values = [values[0], values[1]]
|
||||
}
|
||||
|
||||
if (include.length || exclude.length) {
|
||||
pool = {}
|
||||
|
||||
data.categories.forEach((category) => {
|
||||
let isIncluded =
|
||||
include && include.length ? include.indexOf(category.id) > -1 : true
|
||||
let isExcluded =
|
||||
exclude && exclude.length ? exclude.indexOf(category.id) > -1 : false
|
||||
if (!isIncluded || isExcluded) {
|
||||
return
|
||||
}
|
||||
|
||||
category.emojis.forEach(
|
||||
(emojiId) => (pool[emojiId] = data.emojis[emojiId]),
|
||||
)
|
||||
})
|
||||
|
||||
if (custom.length) {
|
||||
let customIsIncluded =
|
||||
include && include.length ? include.indexOf('custom') > -1 : true
|
||||
let customIsExcluded =
|
||||
exclude && exclude.length ? exclude.indexOf('custom') > -1 : false
|
||||
if (customIsIncluded && !customIsExcluded) {
|
||||
addCustomToPool(custom, pool)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allResults = values
|
||||
.map((value) => {
|
||||
var aPool = pool,
|
||||
aIndex = index,
|
||||
length = 0
|
||||
|
||||
for (let charIndex = 0; charIndex < value.length; charIndex++) {
|
||||
const char = value[charIndex]
|
||||
length++
|
||||
|
||||
aIndex[char] || (aIndex[char] = {})
|
||||
aIndex = aIndex[char]
|
||||
|
||||
if (!aIndex.results) {
|
||||
let scores = {}
|
||||
|
||||
aIndex.results = []
|
||||
aIndex.pool = {}
|
||||
|
||||
for (let id in aPool) {
|
||||
let emoji = aPool[id],
|
||||
{ search } = emoji,
|
||||
sub = value.substr(0, length),
|
||||
subIndex = search.indexOf(sub)
|
||||
|
||||
if (subIndex != -1) {
|
||||
let score = subIndex + 1
|
||||
if (sub == id) score = 0
|
||||
|
||||
aIndex.results.push(emojisList[id])
|
||||
aIndex.pool[id] = emoji
|
||||
|
||||
scores[id] = score
|
||||
}
|
||||
}
|
||||
|
||||
aIndex.results.sort((a, b) => {
|
||||
var aScore = scores[a.id],
|
||||
bScore = scores[b.id]
|
||||
|
||||
return aScore - bScore
|
||||
})
|
||||
}
|
||||
|
||||
aPool = aIndex.pool
|
||||
}
|
||||
|
||||
return aIndex.results
|
||||
})
|
||||
.filter((a) => a)
|
||||
|
||||
if (allResults.length > 1) {
|
||||
results = intersect.apply(null, allResults)
|
||||
} else if (allResults.length) {
|
||||
results = allResults[0]
|
||||
} else {
|
||||
results = []
|
||||
}
|
||||
}
|
||||
|
||||
if (results) {
|
||||
if (emojisToShowFilter) {
|
||||
results = results.filter((result) => emojisToShowFilter(pool[result.id]))
|
||||
}
|
||||
|
||||
if (results && results.length > maxResults) {
|
||||
results = results.slice(0, maxResults)
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
export default { search, emojis: emojisList, emoticons: emoticonsList }
|
|
@ -0,0 +1,11 @@
|
|||
import data from '../../../data/all.json'
|
||||
import NimbleEmojiIndex from './nimble-emoji-index'
|
||||
|
||||
const emojiIndex = new NimbleEmojiIndex(data)
|
||||
const { emojis, emoticons } = emojiIndex
|
||||
|
||||
function search() {
|
||||
return emojiIndex.search(...arguments)
|
||||
}
|
||||
|
||||
export default { search, emojis, emoticons }
|
|
@ -0,0 +1,196 @@
|
|||
import { getData, getSanitizedData, intersect } from '..'
|
||||
import { uncompress } from '../data'
|
||||
|
||||
export default class NimbleEmojiIndex {
|
||||
constructor(data) {
|
||||
if (data.compressed) {
|
||||
uncompress(data)
|
||||
}
|
||||
|
||||
this.data = data || {}
|
||||
this.originalPool = {}
|
||||
this.index = {}
|
||||
this.emojis = {}
|
||||
this.emoticons = {}
|
||||
this.customEmojisList = []
|
||||
|
||||
this.buildIndex()
|
||||
}
|
||||
|
||||
buildIndex() {
|
||||
for (let emoji in this.data.emojis) {
|
||||
let emojiData = this.data.emojis[emoji],
|
||||
{ short_names, emoticons } = emojiData,
|
||||
id = short_names[0]
|
||||
|
||||
if (emoticons) {
|
||||
emoticons.forEach((emoticon) => {
|
||||
if (this.emoticons[emoticon]) {
|
||||
return
|
||||
}
|
||||
|
||||
this.emoticons[emoticon] = id
|
||||
})
|
||||
}
|
||||
|
||||
this.emojis[id] = getSanitizedData(id, null, null, this.data)
|
||||
this.originalPool[id] = emojiData
|
||||
}
|
||||
}
|
||||
|
||||
clearCustomEmojis(pool) {
|
||||
this.customEmojisList.forEach((emoji) => {
|
||||
let emojiId = emoji.id || emoji.short_names[0]
|
||||
|
||||
delete pool[emojiId]
|
||||
delete emojisList[emojiId]
|
||||
})
|
||||
}
|
||||
|
||||
addCustomToPool(custom, pool) {
|
||||
if (this.customEmojisList.length) this.clearCustomEmojis(pool)
|
||||
|
||||
custom.forEach((emoji) => {
|
||||
let emojiId = emoji.id || emoji.short_names[0]
|
||||
|
||||
if (emojiId && !pool[emojiId]) {
|
||||
pool[emojiId] = getData(emoji, null, null, this.data)
|
||||
this.emojis[emojiId] = getSanitizedData(emoji, null, null, this.data)
|
||||
}
|
||||
})
|
||||
|
||||
this.customEmojisList = custom
|
||||
this.index = {}
|
||||
}
|
||||
|
||||
search(
|
||||
value,
|
||||
{ emojisToShowFilter, maxResults, include, exclude, custom = [] } = {},
|
||||
) {
|
||||
if (this.customEmojisList != custom)
|
||||
this.addCustomToPool(custom, this.originalPool)
|
||||
|
||||
maxResults || (maxResults = 75)
|
||||
include || (include = [])
|
||||
exclude || (exclude = [])
|
||||
|
||||
var results = null,
|
||||
pool = this.originalPool
|
||||
|
||||
if (value.length) {
|
||||
if (value == '-' || value == '-1') {
|
||||
return [this.emojis['-1']]
|
||||
}
|
||||
|
||||
var values = value.toLowerCase().split(/[\s|,|\-|_]+/),
|
||||
allResults = []
|
||||
|
||||
if (values.length > 2) {
|
||||
values = [values[0], values[1]]
|
||||
}
|
||||
|
||||
if (include.length || exclude.length) {
|
||||
pool = {}
|
||||
|
||||
this.data.categories.forEach((category) => {
|
||||
let isIncluded =
|
||||
include && include.length ? include.indexOf(category.id) > -1 : true
|
||||
let isExcluded =
|
||||
exclude && exclude.length
|
||||
? exclude.indexOf(category.id) > -1
|
||||
: false
|
||||
if (!isIncluded || isExcluded) {
|
||||
return
|
||||
}
|
||||
|
||||
category.emojis.forEach(
|
||||
(emojiId) => (pool[emojiId] = this.data.emojis[emojiId]),
|
||||
)
|
||||
})
|
||||
|
||||
if (custom.length) {
|
||||
let customIsIncluded =
|
||||
include && include.length ? include.indexOf('custom') > -1 : true
|
||||
let customIsExcluded =
|
||||
exclude && exclude.length ? exclude.indexOf('custom') > -1 : false
|
||||
if (customIsIncluded && !customIsExcluded) {
|
||||
this.addCustomToPool(custom, pool)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allResults = values
|
||||
.map((value) => {
|
||||
var aPool = pool,
|
||||
aIndex = this.index,
|
||||
length = 0
|
||||
|
||||
for (let charIndex = 0; charIndex < value.length; charIndex++) {
|
||||
const char = value[charIndex]
|
||||
length++
|
||||
|
||||
aIndex[char] || (aIndex[char] = {})
|
||||
aIndex = aIndex[char]
|
||||
|
||||
if (!aIndex.results) {
|
||||
let scores = {}
|
||||
|
||||
aIndex.results = []
|
||||
aIndex.pool = {}
|
||||
|
||||
for (let id in aPool) {
|
||||
let emoji = aPool[id],
|
||||
{ search } = emoji,
|
||||
sub = value.substr(0, length),
|
||||
subIndex = search.indexOf(sub)
|
||||
|
||||
if (subIndex != -1) {
|
||||
let score = subIndex + 1
|
||||
if (sub == id) score = 0
|
||||
|
||||
aIndex.results.push(this.emojis[id])
|
||||
aIndex.pool[id] = emoji
|
||||
|
||||
scores[id] = score
|
||||
}
|
||||
}
|
||||
|
||||
aIndex.results.sort((a, b) => {
|
||||
var aScore = scores[a.id],
|
||||
bScore = scores[b.id]
|
||||
|
||||
return aScore - bScore
|
||||
})
|
||||
}
|
||||
|
||||
aPool = aIndex.pool
|
||||
}
|
||||
|
||||
return aIndex.results
|
||||
})
|
||||
.filter((a) => a)
|
||||
|
||||
if (allResults.length > 1) {
|
||||
results = intersect.apply(null, allResults)
|
||||
} else if (allResults.length) {
|
||||
results = allResults[0]
|
||||
} else {
|
||||
results = []
|
||||
}
|
||||
}
|
||||
|
||||
if (results) {
|
||||
if (emojisToShowFilter) {
|
||||
results = results.filter((result) =>
|
||||
emojisToShowFilter(pool[result.id]),
|
||||
)
|
||||
}
|
||||
|
||||
if (results && results.length > maxResults) {
|
||||
results = results.slice(0, maxResults)
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
import buildSearch from './build-search'
|
||||
import data from '../data'
|
||||
import { buildSearch } from './data'
|
||||
import stringFromCodePoint from '../polyfills/stringFromCodePoint'
|
||||
|
||||
const _JSON = JSON
|
||||
|
@ -58,7 +57,7 @@ function getSanitizedData() {
|
|||
return sanitize(getData(...arguments))
|
||||
}
|
||||
|
||||
function getData(emoji, skin, set) {
|
||||
function getData(emoji, skin, set, data) {
|
||||
var emojiData = {}
|
||||
|
||||
if (typeof emoji == 'string') {
|
||||
|
@ -68,12 +67,12 @@ function getData(emoji, skin, set) {
|
|||
emoji = matches[1]
|
||||
|
||||
if (matches[2]) {
|
||||
skin = parseInt(matches[2])
|
||||
skin = parseInt(matches[2], 10)
|
||||
}
|
||||
}
|
||||
|
||||
if (data.short_names.hasOwnProperty(emoji)) {
|
||||
emoji = data.short_names[emoji]
|
||||
if (data.aliases.hasOwnProperty(emoji)) {
|
||||
emoji = data.aliases[emoji]
|
||||
}
|
||||
|
||||
if (data.emojis.hasOwnProperty(emoji)) {
|
||||
|
@ -82,8 +81,8 @@ function getData(emoji, skin, set) {
|
|||
return null
|
||||
}
|
||||
} else if (emoji.id) {
|
||||
if (data.short_names.hasOwnProperty(emoji.id)) {
|
||||
emoji.id = data.short_names[emoji.id]
|
||||
if (data.aliases.hasOwnProperty(emoji.id)) {
|
||||
emoji.id = data.aliases[emoji.id]
|
||||
}
|
||||
|
||||
if (data.emojis.hasOwnProperty(emoji.id)) {
|
||||
|
@ -114,7 +113,10 @@ function getData(emoji, skin, set) {
|
|||
delete emojiData.variations
|
||||
}
|
||||
|
||||
if (variationData[`has_img_${set}`]) {
|
||||
if (
|
||||
variationData[`has_img_${set}`] == undefined ||
|
||||
variationData[`has_img_${set}`]
|
||||
) {
|
||||
emojiData.skin_tone = skin
|
||||
|
||||
for (let k in variationData) {
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
const EmojiPropTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
onOver: PropTypes.func,
|
||||
onLeave: PropTypes.func,
|
||||
onClick: PropTypes.func,
|
||||
fallback: PropTypes.func,
|
||||
backgroundImageFn: PropTypes.func,
|
||||
native: PropTypes.bool,
|
||||
forceSize: PropTypes.bool,
|
||||
tooltip: PropTypes.bool,
|
||||
skin: PropTypes.oneOf([1, 2, 3, 4, 5, 6]),
|
||||
sheetSize: PropTypes.oneOf([16, 20, 32, 64]),
|
||||
set: PropTypes.oneOf([
|
||||
'apple',
|
||||
'google',
|
||||
'twitter',
|
||||
'emojione',
|
||||
'messenger',
|
||||
'facebook',
|
||||
]),
|
||||
size: PropTypes.number.isRequired,
|
||||
emoji: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
|
||||
}
|
||||
|
||||
const EmojiDefaultProps = {
|
||||
skin: 1,
|
||||
set: 'apple',
|
||||
sheetSize: 64,
|
||||
native: false,
|
||||
forceSize: false,
|
||||
tooltip: false,
|
||||
backgroundImageFn: (set, sheetSize) =>
|
||||
`https://unpkg.com/emoji-datasource-${set}@${EMOJI_DATASOURCE_VERSION}/img/${set}/sheets-256/${sheetSize}.png`,
|
||||
onOver: () => {},
|
||||
onLeave: () => {},
|
||||
onClick: () => {},
|
||||
}
|
||||
|
||||
const PickerPropTypes = {
|
||||
onClick: PropTypes.func,
|
||||
onSkinChange: PropTypes.func,
|
||||
perLine: PropTypes.number,
|
||||
emojiSize: PropTypes.number,
|
||||
i18n: PropTypes.object,
|
||||
style: PropTypes.object,
|
||||
title: PropTypes.string,
|
||||
emoji: PropTypes.string,
|
||||
color: PropTypes.string,
|
||||
set: EmojiPropTypes.set,
|
||||
skin: EmojiPropTypes.skin,
|
||||
native: PropTypes.bool,
|
||||
backgroundImageFn: EmojiPropTypes.backgroundImageFn,
|
||||
sheetSize: EmojiPropTypes.sheetSize,
|
||||
emojisToShowFilter: PropTypes.func,
|
||||
showPreview: PropTypes.bool,
|
||||
showSkinTones: PropTypes.bool,
|
||||
emojiTooltip: EmojiPropTypes.tooltip,
|
||||
include: PropTypes.arrayOf(PropTypes.string),
|
||||
exclude: PropTypes.arrayOf(PropTypes.string),
|
||||
recent: PropTypes.arrayOf(PropTypes.string),
|
||||
autoFocus: PropTypes.bool,
|
||||
custom: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
short_names: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
emoticons: PropTypes.arrayOf(PropTypes.string),
|
||||
keywords: PropTypes.arrayOf(PropTypes.string),
|
||||
imageUrl: PropTypes.string.isRequired,
|
||||
}),
|
||||
),
|
||||
}
|
||||
|
||||
const PickerDefaultProps = {
|
||||
onClick: () => {},
|
||||
onSkinChange: () => {},
|
||||
emojiSize: 24,
|
||||
perLine: 9,
|
||||
i18n: {},
|
||||
style: {},
|
||||
title: 'Emoji Mart™',
|
||||
emoji: 'department_store',
|
||||
color: '#ae65c5',
|
||||
set: EmojiDefaultProps.set,
|
||||
skin: null,
|
||||
defaultSkin: EmojiDefaultProps.skin,
|
||||
native: EmojiDefaultProps.native,
|
||||
sheetSize: EmojiDefaultProps.sheetSize,
|
||||
backgroundImageFn: EmojiDefaultProps.backgroundImageFn,
|
||||
emojisToShowFilter: null,
|
||||
showPreview: true,
|
||||
showSkinTones: true,
|
||||
emojiTooltip: EmojiDefaultProps.tooltip,
|
||||
autoFocus: false,
|
||||
custom: [],
|
||||
}
|
||||
|
||||
export {
|
||||
EmojiPropTypes,
|
||||
EmojiDefaultProps,
|
||||
PickerPropTypes,
|
||||
PickerDefaultProps,
|
||||
}
|
Loading…
Reference in New Issue