Restructure data and components

release
Etienne Lemay 2018-04-29 20:55:13 -04:00
parent 2f5fe6164e
commit 2e97b1faa6
No known key found for this signature in database
GPG Key ID: EE7CF89146BB28E9
33 changed files with 365 additions and 340 deletions

1
.gitignore vendored
View File

@ -3,4 +3,3 @@ dist/
dist-es/
stats.json
report.html
/src/data/data.js

View File

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

1
data/all.json Normal file

File diff suppressed because one or more lines are too long

1
data/apple.json Normal file

File diff suppressed because one or more lines are too long

1
data/emojione.json Normal file

File diff suppressed because one or more lines are too long

1
data/facebook.json Normal file

File diff suppressed because one or more lines are too long

1
data/google.json Normal file

File diff suppressed because one or more lines are too long

1
data/messenger.json Normal file

File diff suppressed because one or more lines are too long

1
data/twitter.json Normal file

File diff suppressed because one or more lines are too long

View File

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

View File

@ -1,112 +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: {}, aliases: {} },
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 + '” doesnt 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 + '” doesnt 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.aliases[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
})

124
scripts/build.js Normal file
View File

@ -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 + '” doesnt 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 + '” doesnt 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
})
}

View File

@ -1,7 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import SVGs from '../../svgs'
import SVGs from '../svgs'
export default class Anchors extends React.PureComponent {
constructor(props) {

View File

@ -1,16 +1,11 @@
import React from 'react'
import PropTypes from 'prop-types'
import frequently from '../../utils/frequently'
import { getData } from '../../utils'
import { NimbleEmoji } from '..'
import frequently from '../utils/frequently'
import { getData } from '../utils'
import { NimbleEmoji } from '.'
import {
CategoryPropTypes,
CategoryDefaultProps,
} from '../../utils/shared-props'
export default class NimbleCategory extends React.Component {
export default class Category extends React.Component {
constructor(props) {
super(props)
@ -217,8 +212,17 @@ export default class NimbleCategory extends React.Component {
}
}
NimbleCategory.propTypes = {
...CategoryPropTypes,
data: PropTypes.object.isRequired,
Category.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),
}
Category.defaultProps = {
emojis: [],
hasStickyPosition: true,
}
NimbleCategory.defaultProps = CategoryDefaultProps

View File

@ -1,17 +0,0 @@
import React from 'react'
import data from '../../data'
import NimbleCategory from './nimble-category'
import {
CategoryPropTypes,
CategoryDefaultProps,
} from '../../utils/shared-props'
export default class Category extends React.Component {
render() {
return <NimbleCategory {...this.props} {...this.state} />
}
}
Category.propTypes = { ...CategoryPropTypes }
Category.defaultProps = { ...CategoryDefaultProps, data }

View File

@ -1,6 +1,6 @@
import React from 'react'
import data from '../../data'
import data from '../../../data/all.json'
import NimbleEmoji from './nimble-emoji'
import { EmojiPropTypes, EmojiDefaultProps } from '../../utils/shared-props'

View File

@ -2,6 +2,7 @@ import React from 'react'
import PropTypes from 'prop-types'
import { getData, getSanitizedData, unifiedToNative } from '../../utils'
import { uncompress } from '../../utils/data'
import { EmojiPropTypes, EmojiDefaultProps } from '../../utils/shared-props'
const SHEET_COLUMNS = 52
@ -74,6 +75,10 @@ const _convertStyleToCSS = (style) => {
}
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 NimbleEmoji = (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) {

View File

@ -1,18 +1,11 @@
export { default as Anchors } from './anchors/anchors'
export { default as Category } from './category/category'
export { default as NimbleCategory } from './category/nimble-category'
export { default as Anchors } from './anchors'
export { default as Category } from './category'
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'
export { default as Preview } from './preview/preview'
export { default as NimblePreview } from './preview/nimble-preview'
export { default as Search } from './search/search'
export { default as NimbleSearch } from './search/nimble-search'
export { default as Skins } from './skins/skins'

View File

@ -6,9 +6,10 @@ import PropTypes from 'prop-types'
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, NimbleCategory, NimblePreview, NimbleSearch } from '..'
import { Anchors, Category, Preview, Search } from '..'
const I18N = {
search: 'Search',
@ -41,6 +42,10 @@ export default class NimblePicker extends React.PureComponent {
anchor: false,
}
if (props.data.compressed) {
uncompress(props.data)
}
this.data = props.data
this.i18n = deepMerge(I18N, props.i18n)
this.state = {
@ -483,7 +488,7 @@ export default class NimblePicker extends React.PureComponent {
/>
</div>
<NimbleSearch
<Search
ref={this.setSearchRef}
onSearch={this.handleSearch}
data={this.data}
@ -502,7 +507,7 @@ export default class NimblePicker extends React.PureComponent {
>
{this.getCategories().map((category, i) => {
return (
<NimbleCategory
<Category
ref={this.setCategoryRef.bind(this, `category-${i}`)}
key={category.name}
id={category.id}
@ -541,7 +546,7 @@ export default class NimblePicker extends React.PureComponent {
{showPreview && (
<div className="emoji-mart-bar">
<NimblePreview
<Preview
ref={this.setPreviewRef}
data={this.data}
title={title}

View File

@ -1,6 +1,6 @@
import React from 'react'
import data from '../../data'
import data from '../../../data/all.json'
import NimblePicker from './nimble-picker'
import { PickerPropTypes, PickerDefaultProps } from '../../utils/shared-props'

View File

@ -1,11 +1,10 @@
import React from 'react'
import PropTypes from 'prop-types'
import { getData } from '../../utils'
import { NimbleEmoji, Skins } from '..'
import { PreviewPropTypes, PreviewDefaultProps } from '../../utils/shared-props'
import { getData } from '../utils'
import { NimbleEmoji, Skins } from '.'
export default class NimblePreview extends React.PureComponent {
export default class Preview extends React.PureComponent {
constructor(props) {
super(props)
@ -92,8 +91,15 @@ export default class NimblePreview extends React.PureComponent {
}
}
NimblePreview.propTypes = {
...PreviewPropTypes,
data: PropTypes.object.isRequired,
Preview.propTypes = {
showSkinTones: PropTypes.bool,
title: PropTypes.string.isRequired,
emoji: PropTypes.string.isRequired,
emojiProps: PropTypes.object.isRequired,
skinsProps: PropTypes.object.isRequired,
}
Preview.defaultProps = {
showSkinTones: true,
onChange: () => {},
}
NimblePreview.defaultProps = PreviewDefaultProps

View File

@ -1,15 +0,0 @@
import React from 'react'
import data from '../../data'
import NimblePreview from './nimble-preview'
import { PreviewPropTypes, PreviewDefaultProps } from '../../utils/shared-props'
export default class Preview extends React.PureComponent {
render() {
return <NimblePreview {...this.props} {...this.state} />
}
}
Preview.propTypes = PreviewPropTypes
Preview.defaultProps = { ...PreviewDefaultProps, data }

View File

@ -1,10 +1,9 @@
import React from 'react'
import PropTypes from 'prop-types'
import NimbleEmojiIndex from '../../utils/emoji-index/nimble-emoji-index'
import { SearchPropTypes, SearchDefaultProps } from '../../utils/shared-props'
import NimbleEmojiIndex from '../utils/emoji-index/nimble-emoji-index'
export default class NimbleSearch extends React.PureComponent {
export default class Search extends React.PureComponent {
constructor(props) {
super(props)
@ -53,8 +52,16 @@ export default class NimbleSearch extends React.PureComponent {
}
}
NimbleSearch.propTypes = {
...SearchPropTypes,
data: PropTypes.object.isRequired,
Search.propTypes = {
onSearch: PropTypes.func,
maxResults: PropTypes.number,
emojisToShowFilter: PropTypes.func,
autoFocus: PropTypes.bool,
}
Search.defaultProps = {
onSearch: () => {},
maxResults: 75,
emojisToShowFilter: null,
autoFocus: false,
}
NimbleSearch.defaultProps = SearchDefaultProps

View File

@ -1,15 +0,0 @@
import React from 'react'
import data from '../../data'
import NimbleSearch from './nimble-search'
import { SearchPropTypes, SearchDefaultProps } from '../../utils/shared-props'
export default class Search extends React.PureComponent {
render() {
return <NimbleSearch {...this.props} {...this.state} />
}
}
Search.propTypes = SearchPropTypes
Search.defaultProps = { ...SearchDefaultProps, data }

View File

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

View File

@ -8,7 +8,6 @@ export {
Emoji,
NimbleEmoji,
Category,
NimbleCategory,
} from './components'
export { NimbleEmojiIndex } from './utils/emoji-index/nimble-emoji-index'

View File

@ -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(',')
}

106
src/utils/data.js Normal file
View File

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

View File

@ -1,4 +1,4 @@
import data from '../../data'
import data from '../../../data/all.json'
import NimbleEmojiIndex from './nimble-emoji-index'
const emojiIndex = new NimbleEmojiIndex(data)

View File

@ -1,7 +1,12 @@
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 = {}

View File

@ -1,4 +1,4 @@
import buildSearch from './build-search'
import { buildSearch } from './data'
import stringFromCodePoint from '../polyfills/stringFromCodePoint'
const _JSON = JSON
@ -113,7 +113,10 @@ function getData(emoji, skin, set, data) {
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) {

View File

@ -1,20 +1,5 @@
import PropTypes from 'prop-types'
const CategoryPropTypes = {
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),
}
const CategoryDefaultProps = {
emojis: [],
hasStickyPosition: true,
}
const EmojiPropTypes = {
data: PropTypes.object.isRequired,
onOver: PropTypes.func,
@ -111,42 +96,9 @@ const PickerDefaultProps = {
custom: [],
}
const PreviewPropTypes = {
showSkinTones: PropTypes.bool,
title: PropTypes.string.isRequired,
emoji: PropTypes.string.isRequired,
emojiProps: PropTypes.object.isRequired,
skinsProps: PropTypes.object.isRequired,
}
const PreviewDefaultProps = {
showSkinTones: true,
onChange: () => {},
}
const SearchPropTypes = {
onSearch: PropTypes.func,
maxResults: PropTypes.number,
emojisToShowFilter: PropTypes.func,
autoFocus: PropTypes.bool,
}
const SearchDefaultProps = {
onSearch: () => {},
maxResults: 75,
emojisToShowFilter: null,
autoFocus: false,
}
export {
CategoryPropTypes,
CategoryDefaultProps,
EmojiPropTypes,
EmojiDefaultProps,
PickerPropTypes,
PickerDefaultProps,
PreviewPropTypes,
PreviewDefaultProps,
SearchPropTypes,
SearchDefaultProps,
}