Prettier 💄
parent
9ff4c8855c
commit
3021758115
|
@ -51,6 +51,7 @@
|
||||||
"karma-jasmine": "^1.1.0",
|
"karma-jasmine": "^1.1.0",
|
||||||
"karma-webpack": "^2.0.4",
|
"karma-webpack": "^2.0.4",
|
||||||
"mkdirp": "0.5.1",
|
"mkdirp": "0.5.1",
|
||||||
|
"prettier": "1.7.4",
|
||||||
"prop-types": "^15.6.0",
|
"prop-types": "^15.6.0",
|
||||||
"react": "^16.0.0",
|
"react": "^16.0.0",
|
||||||
"react-dom": "^16.0.0",
|
"react-dom": "^16.0.0",
|
||||||
|
@ -75,7 +76,8 @@
|
||||||
"test": "NODE_ENV=test karma start && size-limit",
|
"test": "NODE_ENV=test karma start && size-limit",
|
||||||
"prepublish": "npm run build",
|
"prepublish": "npm run build",
|
||||||
"storybook": "start-storybook -p 6006",
|
"storybook": "start-storybook -p 6006",
|
||||||
"build-storybook": "build-storybook"
|
"build-storybook": "build-storybook",
|
||||||
|
"prettier": "prettier --no-semi --single-quote --trailing-comma es5 --write \"src/**/*.js\""
|
||||||
},
|
},
|
||||||
"size-limit": [
|
"size-limit": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,18 +7,18 @@ export default class Anchors extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
const {categories} = props
|
const { categories } = props
|
||||||
|
|
||||||
const defaultCategory = categories.filter(category => category.first)[0]
|
const defaultCategory = categories.filter(category => category.first)[0]
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
selected: defaultCategory.name
|
selected: defaultCategory.name,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handleClick = this.handleClick.bind(this)
|
this.handleClick = this.handleClick.bind(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick (e) {
|
handleClick(e) {
|
||||||
var index = e.currentTarget.getAttribute('data-index')
|
var index = e.currentTarget.getAttribute('data-index')
|
||||||
var { categories, onAnchorClick } = this.props
|
var { categories, onAnchorClick } = this.props
|
||||||
|
|
||||||
|
@ -27,32 +27,39 @@ export default class Anchors extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var { categories, onAnchorClick, color, i18n } = this.props,
|
var { categories, onAnchorClick, color, i18n } = this.props,
|
||||||
{ selected } = this.state
|
{ selected } = this.state
|
||||||
|
|
||||||
return <div className='emoji-mart-anchors'>
|
return (
|
||||||
{categories.map((category, i) => {
|
<div className="emoji-mart-anchors">
|
||||||
var { name, anchor } = category,
|
{categories.map((category, i) => {
|
||||||
|
var { name, anchor } = category,
|
||||||
isSelected = name == selected
|
isSelected = name == selected
|
||||||
|
|
||||||
if (anchor === false) {
|
if (anchor === false) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
key={name}
|
key={name}
|
||||||
title={i18n.categories[name.toLowerCase()]}
|
title={i18n.categories[name.toLowerCase()]}
|
||||||
data-index={i}
|
data-index={i}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
className={`emoji-mart-anchor ${isSelected ? 'emoji-mart-anchor-selected' : ''}`}
|
className={`emoji-mart-anchor ${isSelected
|
||||||
style={{ color: isSelected ? color : null }}
|
? 'emoji-mart-anchor-selected'
|
||||||
>
|
: ''}`}
|
||||||
<div dangerouslySetInnerHTML={{ __html: SVGs[name] }}></div>
|
style={{ color: isSelected ? color : null }}
|
||||||
<span className='emoji-mart-anchor-bar' style={{ backgroundColor: color }}></span>
|
>
|
||||||
</span>
|
<div dangerouslySetInnerHTML={{ __html: SVGs[name] }} />
|
||||||
)
|
<span
|
||||||
})}
|
className="emoji-mart-anchor-bar"
|
||||||
</div>
|
style={{ backgroundColor: color }}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,5 +70,5 @@ Anchors.propTypes = {
|
||||||
|
|
||||||
Anchors.defaultProps = {
|
Anchors.defaultProps = {
|
||||||
categories: [],
|
categories: [],
|
||||||
onAnchorClick: (() => {}),
|
onAnchorClick: () => {},
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,24 @@ export default class Category extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
var { name, perLine, native, hasStickyPosition, emojis, emojiProps } = this.props,
|
var {
|
||||||
{ skin, size, set } = emojiProps,
|
name,
|
||||||
{ perLine: nextPerLine, native: nextNative, hasStickyPosition: nextHasStickyPosition, emojis: nextEmojis, emojiProps: nextEmojiProps } = nextProps,
|
perLine,
|
||||||
{ skin: nextSkin, size: nextSize, set: nextSet } = nextEmojiProps,
|
native,
|
||||||
shouldUpdate = false
|
hasStickyPosition,
|
||||||
|
emojis,
|
||||||
|
emojiProps,
|
||||||
|
} = this.props,
|
||||||
|
{ skin, size, set } = emojiProps,
|
||||||
|
{
|
||||||
|
perLine: nextPerLine,
|
||||||
|
native: nextNative,
|
||||||
|
hasStickyPosition: nextHasStickyPosition,
|
||||||
|
emojis: nextEmojis,
|
||||||
|
emojiProps: nextEmojiProps,
|
||||||
|
} = nextProps,
|
||||||
|
{ skin: nextSkin, size: nextSize, set: nextSet } = nextEmojiProps,
|
||||||
|
shouldUpdate = false
|
||||||
|
|
||||||
if (name == 'Recent' && perLine != nextPerLine) {
|
if (name == 'Recent' && perLine != nextPerLine) {
|
||||||
shouldUpdate = true
|
shouldUpdate = true
|
||||||
|
@ -36,7 +49,13 @@ export default class Category extends React.Component {
|
||||||
shouldUpdate = !(emojis == nextEmojis)
|
shouldUpdate = !(emojis == nextEmojis)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skin != nextSkin || size != nextSize || native != nextNative || set != nextSet || hasStickyPosition != nextHasStickyPosition) {
|
if (
|
||||||
|
skin != nextSkin ||
|
||||||
|
size != nextSize ||
|
||||||
|
native != nextNative ||
|
||||||
|
set != nextSet ||
|
||||||
|
hasStickyPosition != nextHasStickyPosition
|
||||||
|
) {
|
||||||
shouldUpdate = true
|
shouldUpdate = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +100,7 @@ export default class Category extends React.Component {
|
||||||
let frequentlyUsed = frequently.get(perLine)
|
let frequentlyUsed = frequently.get(perLine)
|
||||||
|
|
||||||
if (frequentlyUsed.length) {
|
if (frequentlyUsed.length) {
|
||||||
emojis = frequentlyUsed.map((id) => {
|
emojis = frequentlyUsed.map(id => {
|
||||||
const emoji = custom.filter(e => e.id === id)[0]
|
const emoji = custom.filter(e => e.id === id)[0]
|
||||||
if (emoji) {
|
if (emoji) {
|
||||||
return emoji
|
return emoji
|
||||||
|
@ -119,10 +138,10 @@ export default class Category extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var { name, hasStickyPosition, emojiProps, i18n } = this.props,
|
var { name, hasStickyPosition, emojiProps, i18n } = this.props,
|
||||||
emojis = this.getEmojis(),
|
emojis = this.getEmojis(),
|
||||||
labelStyles = {},
|
labelStyles = {},
|
||||||
labelSpanStyles = {},
|
labelSpanStyles = {},
|
||||||
containerStyles = {}
|
containerStyles = {}
|
||||||
|
|
||||||
if (!emojis) {
|
if (!emojis) {
|
||||||
containerStyles = {
|
containerStyles = {
|
||||||
|
@ -140,34 +159,45 @@ export default class Category extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div ref={this.setContainerRef} className={`emoji-mart-category ${emojis && !emojis.length ? 'emoji-mart-no-results' : ''}`} style={containerStyles}>
|
return (
|
||||||
<div style={labelStyles} data-name={name} className='emoji-mart-category-label'>
|
<div
|
||||||
<span style={labelSpanStyles} ref={this.setLabelRef}>{i18n.categories[name.toLowerCase()]}</span>
|
ref={this.setContainerRef}
|
||||||
</div>
|
className={`emoji-mart-category ${emojis && !emojis.length
|
||||||
|
? 'emoji-mart-no-results'
|
||||||
{emojis && emojis.map((emoji) =>
|
: ''}`}
|
||||||
Emoji({ emoji: emoji, ...emojiProps })
|
style={containerStyles}
|
||||||
)}
|
>
|
||||||
|
<div
|
||||||
{emojis && !emojis.length &&
|
style={labelStyles}
|
||||||
<div>
|
data-name={name}
|
||||||
<div>
|
className="emoji-mart-category-label"
|
||||||
{Emoji({
|
>
|
||||||
...emojiProps,
|
<span style={labelSpanStyles} ref={this.setLabelRef}>
|
||||||
size: 38,
|
{i18n.categories[name.toLowerCase()]}
|
||||||
emoji: 'sleuth_or_spy',
|
</span>
|
||||||
onOver: null,
|
|
||||||
onLeave: null,
|
|
||||||
onClick: null,
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='emoji-mart-no-results-label'>
|
|
||||||
{i18n.notfound}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
|
||||||
</div>
|
{emojis && emojis.map(emoji => Emoji({ emoji: emoji, ...emojiProps }))}
|
||||||
|
|
||||||
|
{emojis &&
|
||||||
|
!emojis.length && (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
{Emoji({
|
||||||
|
...emojiProps,
|
||||||
|
size: 38,
|
||||||
|
emoji: 'sleuth_or_spy',
|
||||||
|
onOver: null,
|
||||||
|
onLeave: null,
|
||||||
|
onClick: null,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="emoji-mart-no-results-label">{i18n.notfound}</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,48 +6,54 @@ import { getData, getSanitizedData, unifiedToNative } from '../utils'
|
||||||
|
|
||||||
const SHEET_COLUMNS = 49
|
const SHEET_COLUMNS = 49
|
||||||
|
|
||||||
const _getPosition = (props) => {
|
const _getPosition = props => {
|
||||||
var { sheet_x, sheet_y } = _getData(props),
|
var { sheet_x, sheet_y } = _getData(props),
|
||||||
multiply = 100 / (SHEET_COLUMNS - 1)
|
multiply = 100 / (SHEET_COLUMNS - 1)
|
||||||
|
|
||||||
return `${multiply * sheet_x}% ${multiply * sheet_y}%`
|
return `${multiply * sheet_x}% ${multiply * sheet_y}%`
|
||||||
}
|
}
|
||||||
|
|
||||||
const _getData = (props) => {
|
const _getData = props => {
|
||||||
var { emoji, skin, set } = props
|
var { emoji, skin, set } = props
|
||||||
return getData(emoji, skin, set)
|
return getData(emoji, skin, set)
|
||||||
}
|
}
|
||||||
|
|
||||||
const _getSanitizedData = (props) => {
|
const _getSanitizedData = props => {
|
||||||
var { emoji, skin, set } = props
|
var { emoji, skin, set } = props
|
||||||
return getSanitizedData(emoji, skin, set)
|
return getSanitizedData(emoji, skin, set)
|
||||||
}
|
}
|
||||||
|
|
||||||
const _handleClick = (e, props) => {
|
const _handleClick = (e, props) => {
|
||||||
if (!props.onClick) { return }
|
if (!props.onClick) {
|
||||||
|
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) { return }
|
if (!props.onOver) {
|
||||||
|
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) { return }
|
if (!props.onLeave) {
|
||||||
|
return
|
||||||
|
}
|
||||||
var { onLeave } = props,
|
var { onLeave } = props,
|
||||||
emoji = _getSanitizedData(props)
|
emoji = _getSanitizedData(props)
|
||||||
|
|
||||||
onLeave(emoji, e)
|
onLeave(emoji, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Emoji = (props) => {
|
const Emoji = props => {
|
||||||
for (let k in Emoji.defaultProps) {
|
for (let k in Emoji.defaultProps) {
|
||||||
if (props[k] == undefined && Emoji.defaultProps[k] != undefined) {
|
if (props[k] == undefined && Emoji.defaultProps[k] != undefined) {
|
||||||
props[k] = Emoji.defaultProps[k]
|
props[k] = Emoji.defaultProps[k]
|
||||||
|
@ -55,10 +61,10 @@ const Emoji = (props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
var { unified, custom, short_names, imageUrl } = _getData(props),
|
var { unified, custom, short_names, imageUrl } = _getData(props),
|
||||||
style = {},
|
style = {},
|
||||||
children = props.children,
|
children = props.children,
|
||||||
className = 'emoji-mart-emoji',
|
className = 'emoji-mart-emoji',
|
||||||
title = null
|
title = null
|
||||||
|
|
||||||
if (!unified && !custom) {
|
if (!unified && !custom) {
|
||||||
return null
|
return null
|
||||||
|
@ -98,21 +104,27 @@ const Emoji = (props) => {
|
||||||
width: props.size,
|
width: props.size,
|
||||||
height: props.size,
|
height: props.size,
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
backgroundImage: `url(${props.backgroundImageFn(props.set, props.sheetSize)})`,
|
backgroundImage: `url(${props.backgroundImageFn(
|
||||||
|
props.set,
|
||||||
|
props.sheetSize
|
||||||
|
)})`,
|
||||||
backgroundSize: `${100 * SHEET_COLUMNS}%`,
|
backgroundSize: `${100 * SHEET_COLUMNS}%`,
|
||||||
backgroundPosition: _getPosition(props),
|
backgroundPosition: _getPosition(props),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <span
|
return (
|
||||||
key={props.emoji.id || props.emoji}
|
<span
|
||||||
onClick={(e) => _handleClick(e, props)}
|
key={props.emoji.id || props.emoji}
|
||||||
onMouseEnter={(e) => _handleOver(e, props)}
|
onClick={e => _handleClick(e, props)}
|
||||||
onMouseLeave={(e) => _handleLeave(e, props)}
|
onMouseEnter={e => _handleOver(e, props)}
|
||||||
title={title}
|
onMouseLeave={e => _handleLeave(e, props)}
|
||||||
className={className}>
|
title={title}
|
||||||
<span style={style}>{children}</span>
|
className={className}
|
||||||
</span>
|
>
|
||||||
|
<span style={style}>{children}</span>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Emoji.propTypes = {
|
Emoji.propTypes = {
|
||||||
|
@ -125,12 +137,16 @@ Emoji.propTypes = {
|
||||||
tooltip: PropTypes.bool,
|
tooltip: 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]),
|
||||||
set: PropTypes.oneOf(['apple', 'google', 'twitter', 'emojione', 'messenger', 'facebook']),
|
set: PropTypes.oneOf([
|
||||||
|
'apple',
|
||||||
|
'google',
|
||||||
|
'twitter',
|
||||||
|
'emojione',
|
||||||
|
'messenger',
|
||||||
|
'facebook',
|
||||||
|
]),
|
||||||
size: PropTypes.number.isRequired,
|
size: PropTypes.number.isRequired,
|
||||||
emoji: PropTypes.oneOfType([
|
emoji: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
|
||||||
PropTypes.string,
|
|
||||||
PropTypes.object,
|
|
||||||
]).isRequired,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Emoji.defaultProps = {
|
Emoji.defaultProps = {
|
||||||
|
@ -140,10 +156,11 @@ Emoji.defaultProps = {
|
||||||
native: false,
|
native: false,
|
||||||
forceSize: false,
|
forceSize: false,
|
||||||
tooltip: false,
|
tooltip: false,
|
||||||
backgroundImageFn: ((set, sheetSize) => `https://unpkg.com/emoji-datasource-${set}@${EMOJI_DATASOURCE_VERSION}/img/${set}/sheets/${sheetSize}.png`),
|
backgroundImageFn: (set, sheetSize) =>
|
||||||
onOver: (() => {}),
|
`https://unpkg.com/emoji-datasource-${set}@${EMOJI_DATASOURCE_VERSION}/img/${set}/sheets/${sheetSize}.png`,
|
||||||
onLeave: (() => {}),
|
onOver: () => {},
|
||||||
onClick: (() => {}),
|
onLeave: () => {},
|
||||||
|
onClick: () => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Emoji
|
export default Emoji
|
||||||
|
|
|
@ -73,16 +73,28 @@ export default class Picker extends React.PureComponent {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let categoryIndex = 0; categoryIndex < allCategories.length; categoryIndex++) {
|
for (
|
||||||
|
let categoryIndex = 0;
|
||||||
|
categoryIndex < allCategories.length;
|
||||||
|
categoryIndex++
|
||||||
|
) {
|
||||||
const category = allCategories[categoryIndex]
|
const category = allCategories[categoryIndex]
|
||||||
let isIncluded = props.include && props.include.length ? props.include.indexOf(category.name.toLowerCase()) > -1 : true
|
let isIncluded =
|
||||||
let isExcluded = props.exclude && props.exclude.length ? props.exclude.indexOf(category.name.toLowerCase()) > -1 : false
|
props.include && props.include.length
|
||||||
if (!isIncluded || isExcluded) { continue }
|
? props.include.indexOf(category.name.toLowerCase()) > -1
|
||||||
|
: true
|
||||||
|
let isExcluded =
|
||||||
|
props.exclude && props.exclude.length
|
||||||
|
? props.exclude.indexOf(category.name.toLowerCase()) > -1
|
||||||
|
: false
|
||||||
|
if (!isIncluded || isExcluded) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if (props.emojisToShowFilter) {
|
if (props.emojisToShowFilter) {
|
||||||
let newEmojis = []
|
let newEmojis = []
|
||||||
|
|
||||||
const {emojis} = category
|
const { emojis } = category
|
||||||
for (let emojiIndex = 0; emojiIndex < emojis.length; emojiIndex++) {
|
for (let emojiIndex = 0; emojiIndex < emojis.length; emojiIndex++) {
|
||||||
const emoji = emojis[emojiIndex]
|
const emoji = emojis[emojiIndex]
|
||||||
if (props.emojisToShowFilter(data.emojis[emoji] || emoji)) {
|
if (props.emojisToShowFilter(data.emojis[emoji] || emoji)) {
|
||||||
|
@ -103,8 +115,14 @@ export default class Picker extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let includeRecent = props.include && props.include.length ? props.include.indexOf('recent') > -1 : true
|
let includeRecent =
|
||||||
let excludeRecent = props.exclude && props.exclude.length ? props.exclude.indexOf('recent') > -1 : false
|
props.include && props.include.length
|
||||||
|
? props.include.indexOf('recent') > -1
|
||||||
|
: true
|
||||||
|
let excludeRecent =
|
||||||
|
props.exclude && props.exclude.length
|
||||||
|
? props.exclude.indexOf('recent') > -1
|
||||||
|
: false
|
||||||
if (includeRecent && !excludeRecent) {
|
if (includeRecent && !excludeRecent) {
|
||||||
this.hideRecent = false
|
this.hideRecent = false
|
||||||
this.categories.unshift(RECENT_CATEGORY)
|
this.categories.unshift(RECENT_CATEGORY)
|
||||||
|
@ -116,18 +134,18 @@ export default class Picker extends React.PureComponent {
|
||||||
|
|
||||||
this.categories.unshift(SEARCH_CATEGORY)
|
this.categories.unshift(SEARCH_CATEGORY)
|
||||||
|
|
||||||
this.setAnchorsRef = this.setAnchorsRef.bind(this)
|
this.setAnchorsRef = this.setAnchorsRef.bind(this)
|
||||||
this.handleAnchorClick = this.handleAnchorClick.bind(this)
|
this.handleAnchorClick = this.handleAnchorClick.bind(this)
|
||||||
this.setSearchRef = this.setSearchRef.bind(this)
|
this.setSearchRef = this.setSearchRef.bind(this)
|
||||||
this.handleSearch = this.handleSearch.bind(this)
|
this.handleSearch = this.handleSearch.bind(this)
|
||||||
this.setScrollRef = this.setScrollRef.bind(this)
|
this.setScrollRef = this.setScrollRef.bind(this)
|
||||||
this.handleScroll = this.handleScroll.bind(this)
|
this.handleScroll = this.handleScroll.bind(this)
|
||||||
this.handleScrollPaint = this.handleScrollPaint.bind(this)
|
this.handleScrollPaint = this.handleScrollPaint.bind(this)
|
||||||
this.handleEmojiOver = this.handleEmojiOver.bind(this)
|
this.handleEmojiOver = this.handleEmojiOver.bind(this)
|
||||||
this.handleEmojiLeave = this.handleEmojiLeave.bind(this)
|
this.handleEmojiLeave = this.handleEmojiLeave.bind(this)
|
||||||
this.handleEmojiClick = this.handleEmojiClick.bind(this)
|
this.handleEmojiClick = this.handleEmojiClick.bind(this)
|
||||||
this.setPreviewRef = this.setPreviewRef.bind(this)
|
this.setPreviewRef = this.setPreviewRef.bind(this)
|
||||||
this.handleSkinChange = this.handleSkinChange.bind(this)
|
this.handleSkinChange = this.handleSkinChange.bind(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(props) {
|
componentWillReceiveProps(props) {
|
||||||
|
@ -162,20 +180,26 @@ export default class Picker extends React.PureComponent {
|
||||||
|
|
||||||
const prefixes = ['', '-webkit-', '-ms-', '-moz-', '-o-']
|
const prefixes = ['', '-webkit-', '-ms-', '-moz-', '-o-']
|
||||||
|
|
||||||
prefixes.forEach(prefix => stickyTestElement.style.position = `${prefix}sticky`)
|
prefixes.forEach(
|
||||||
|
prefix => (stickyTestElement.style.position = `${prefix}sticky`)
|
||||||
|
)
|
||||||
|
|
||||||
this.hasStickyPosition = !!stickyTestElement.style.position.length
|
this.hasStickyPosition = !!stickyTestElement.style.position.length
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEmojiOver(emoji) {
|
handleEmojiOver(emoji) {
|
||||||
var { preview } = this
|
var { preview } = this
|
||||||
if (!preview) { return }
|
if (!preview) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Use Array.prototype.find() when it is more widely supported.
|
// Use Array.prototype.find() when it is more widely supported.
|
||||||
const emojiData = CUSTOM_CATEGORY.emojis.filter(customEmoji => customEmoji.id === emoji.id)[0]
|
const emojiData = CUSTOM_CATEGORY.emojis.filter(
|
||||||
|
customEmoji => customEmoji.id === emoji.id
|
||||||
|
)[0]
|
||||||
for (let key in emojiData) {
|
for (let key in emojiData) {
|
||||||
if (emojiData.hasOwnProperty(key)) {
|
if (emojiData.hasOwnProperty(key)) {
|
||||||
emoji[key] = emojiData[key]
|
emoji[key] = emojiData[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +209,9 @@ export default class Picker extends React.PureComponent {
|
||||||
|
|
||||||
handleEmojiLeave(emoji) {
|
handleEmojiLeave(emoji) {
|
||||||
var { preview } = this
|
var { preview } = this
|
||||||
if (!preview) { return }
|
if (!preview) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.leaveTimeout = setTimeout(() => {
|
this.leaveTimeout = setTimeout(() => {
|
||||||
preview.setState({ emoji: null })
|
preview.setState({ emoji: null })
|
||||||
|
@ -236,14 +262,14 @@ export default class Picker extends React.PureComponent {
|
||||||
activeCategory = SEARCH_CATEGORY
|
activeCategory = SEARCH_CATEGORY
|
||||||
} else {
|
} else {
|
||||||
var target = this.scroll,
|
var target = this.scroll,
|
||||||
scrollTop = target.scrollTop,
|
scrollTop = target.scrollTop,
|
||||||
scrollingDown = scrollTop > (this.scrollTop || 0),
|
scrollingDown = scrollTop > (this.scrollTop || 0),
|
||||||
minTop = 0
|
minTop = 0
|
||||||
|
|
||||||
for (let i = 0, l = this.categories.length; i < l; i++) {
|
for (let i = 0, l = this.categories.length; i < l; i++) {
|
||||||
let ii = scrollingDown ? (this.categories.length - 1 - i) : i,
|
let ii = scrollingDown ? this.categories.length - 1 - i : i,
|
||||||
category = this.categories[ii],
|
category = this.categories[ii],
|
||||||
component = this.categoryRefs[`category-${ii}`]
|
component = this.categoryRefs[`category-${ii}`]
|
||||||
|
|
||||||
if (component) {
|
if (component) {
|
||||||
let active = component.handleScroll(scrollTop)
|
let active = component.handleScroll(scrollTop)
|
||||||
|
@ -261,7 +287,9 @@ export default class Picker extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scrollTop < minTop) {
|
if (scrollTop < minTop) {
|
||||||
activeCategory = this.categories.filter(category => !(category.anchor === false))[0]
|
activeCategory = this.categories.filter(
|
||||||
|
category => !(category.anchor === false)
|
||||||
|
)[0]
|
||||||
} else if (scrollTop + this.clientHeight >= this.scrollHeight) {
|
} else if (scrollTop + this.clientHeight >= this.scrollHeight) {
|
||||||
activeCategory = this.categories[this.categories.length - 1]
|
activeCategory = this.categories[this.categories.length - 1]
|
||||||
}
|
}
|
||||||
|
@ -269,7 +297,7 @@ export default class Picker extends React.PureComponent {
|
||||||
|
|
||||||
if (activeCategory) {
|
if (activeCategory) {
|
||||||
let { anchors } = this,
|
let { anchors } = this,
|
||||||
{ name: categoryName } = activeCategory
|
{ name: categoryName } = activeCategory
|
||||||
|
|
||||||
if (anchors.state.selected != categoryName) {
|
if (anchors.state.selected != categoryName) {
|
||||||
anchors.setState({ selected: categoryName })
|
anchors.setState({ selected: categoryName })
|
||||||
|
@ -298,8 +326,8 @@ export default class Picker extends React.PureComponent {
|
||||||
|
|
||||||
handleAnchorClick(category, i) {
|
handleAnchorClick(category, i) {
|
||||||
var component = this.categoryRefs[`category-${i}`],
|
var component = this.categoryRefs[`category-${i}`],
|
||||||
{ scroll, anchors } = this,
|
{ scroll, anchors } = this,
|
||||||
scrollToComponent = null
|
scrollToComponent = null
|
||||||
|
|
||||||
scrollToComponent = () => {
|
scrollToComponent = () => {
|
||||||
if (component) {
|
if (component) {
|
||||||
|
@ -346,7 +374,9 @@ export default class Picker extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
getCategories() {
|
getCategories() {
|
||||||
return this.state.firstRender ? this.categories.slice(0, 3) : this.categories
|
return this.state.firstRender
|
||||||
|
? this.categories.slice(0, 3)
|
||||||
|
: this.categories
|
||||||
}
|
}
|
||||||
|
|
||||||
setAnchorsRef(c) {
|
setAnchorsRef(c) {
|
||||||
|
@ -374,81 +404,110 @@ export default class Picker extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var { perLine, emojiSize, set, sheetSize, style, title, emoji, color, native, backgroundImageFn, emojisToShowFilter, showPreview, emojiTooltip, include, exclude, autoFocus } = this.props,
|
var {
|
||||||
{ skin } = this.state,
|
perLine,
|
||||||
width = (perLine * (emojiSize + 12)) + 12 + 2 + measureScrollbar()
|
emojiSize,
|
||||||
|
set,
|
||||||
|
sheetSize,
|
||||||
|
style,
|
||||||
|
title,
|
||||||
|
emoji,
|
||||||
|
color,
|
||||||
|
native,
|
||||||
|
backgroundImageFn,
|
||||||
|
emojisToShowFilter,
|
||||||
|
showPreview,
|
||||||
|
emojiTooltip,
|
||||||
|
include,
|
||||||
|
exclude,
|
||||||
|
autoFocus,
|
||||||
|
} = this.props,
|
||||||
|
{ skin } = this.state,
|
||||||
|
width = perLine * (emojiSize + 12) + 12 + 2 + measureScrollbar()
|
||||||
|
|
||||||
return <div style={{width: width, ...style}} className='emoji-mart'>
|
return (
|
||||||
<div className='emoji-mart-bar'>
|
<div style={{ width: width, ...style }} className="emoji-mart">
|
||||||
<Anchors
|
<div className="emoji-mart-bar">
|
||||||
ref={this.setAnchorsRef}
|
<Anchors
|
||||||
i18n={this.i18n}
|
ref={this.setAnchorsRef}
|
||||||
color={color}
|
|
||||||
categories={this.categories}
|
|
||||||
onAnchorClick={this.handleAnchorClick}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Search
|
|
||||||
ref={this.setSearchRef}
|
|
||||||
onSearch={this.handleSearch}
|
|
||||||
i18n={this.i18n}
|
|
||||||
emojisToShowFilter={emojisToShowFilter}
|
|
||||||
include={include}
|
|
||||||
exclude={exclude}
|
|
||||||
custom={CUSTOM_CATEGORY.emojis}
|
|
||||||
autoFocus={autoFocus}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div ref={this.setScrollRef} className='emoji-mart-scroll' onScroll={this.handleScroll}>
|
|
||||||
{this.getCategories().map((category, i) => {
|
|
||||||
return <Category
|
|
||||||
ref={this.setCategoryRef.bind(this, `category-${i}`)}
|
|
||||||
key={category.name}
|
|
||||||
name={category.name}
|
|
||||||
emojis={category.emojis}
|
|
||||||
perLine={perLine}
|
|
||||||
native={native}
|
|
||||||
hasStickyPosition={this.hasStickyPosition}
|
|
||||||
i18n={this.i18n}
|
i18n={this.i18n}
|
||||||
custom={category.name == 'Recent' ? CUSTOM_CATEGORY.emojis : undefined}
|
color={color}
|
||||||
emojiProps={{
|
categories={this.categories}
|
||||||
native: native,
|
onAnchorClick={this.handleAnchorClick}
|
||||||
skin: skin,
|
|
||||||
size: emojiSize,
|
|
||||||
set: set,
|
|
||||||
sheetSize: sheetSize,
|
|
||||||
forceSize: native,
|
|
||||||
tooltip: emojiTooltip,
|
|
||||||
backgroundImageFn: backgroundImageFn,
|
|
||||||
onOver: this.handleEmojiOver,
|
|
||||||
onLeave: this.handleEmojiLeave,
|
|
||||||
onClick: this.handleEmojiClick,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
})}
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{showPreview && <div className='emoji-mart-bar'>
|
<Search
|
||||||
<Preview
|
ref={this.setSearchRef}
|
||||||
ref={this.setPreviewRef}
|
onSearch={this.handleSearch}
|
||||||
title={title}
|
i18n={this.i18n}
|
||||||
emoji={emoji}
|
emojisToShowFilter={emojisToShowFilter}
|
||||||
emojiProps={{
|
include={include}
|
||||||
native: native,
|
exclude={exclude}
|
||||||
size: 38,
|
custom={CUSTOM_CATEGORY.emojis}
|
||||||
skin: skin,
|
autoFocus={autoFocus}
|
||||||
set: set,
|
|
||||||
sheetSize: sheetSize,
|
|
||||||
backgroundImageFn: backgroundImageFn,
|
|
||||||
}}
|
|
||||||
skinsProps={{
|
|
||||||
skin: skin,
|
|
||||||
onChange: this.handleSkinChange
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>}
|
|
||||||
</div>
|
<div
|
||||||
|
ref={this.setScrollRef}
|
||||||
|
className="emoji-mart-scroll"
|
||||||
|
onScroll={this.handleScroll}
|
||||||
|
>
|
||||||
|
{this.getCategories().map((category, i) => {
|
||||||
|
return (
|
||||||
|
<Category
|
||||||
|
ref={this.setCategoryRef.bind(this, `category-${i}`)}
|
||||||
|
key={category.name}
|
||||||
|
name={category.name}
|
||||||
|
emojis={category.emojis}
|
||||||
|
perLine={perLine}
|
||||||
|
native={native}
|
||||||
|
hasStickyPosition={this.hasStickyPosition}
|
||||||
|
i18n={this.i18n}
|
||||||
|
custom={
|
||||||
|
category.name == 'Recent' ? CUSTOM_CATEGORY.emojis : undefined
|
||||||
|
}
|
||||||
|
emojiProps={{
|
||||||
|
native: native,
|
||||||
|
skin: skin,
|
||||||
|
size: emojiSize,
|
||||||
|
set: set,
|
||||||
|
sheetSize: sheetSize,
|
||||||
|
forceSize: native,
|
||||||
|
tooltip: emojiTooltip,
|
||||||
|
backgroundImageFn: backgroundImageFn,
|
||||||
|
onOver: this.handleEmojiOver,
|
||||||
|
onLeave: this.handleEmojiLeave,
|
||||||
|
onClick: this.handleEmojiClick,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{showPreview && (
|
||||||
|
<div className="emoji-mart-bar">
|
||||||
|
<Preview
|
||||||
|
ref={this.setPreviewRef}
|
||||||
|
title={title}
|
||||||
|
emoji={emoji}
|
||||||
|
emojiProps={{
|
||||||
|
native: native,
|
||||||
|
size: 38,
|
||||||
|
skin: skin,
|
||||||
|
set: set,
|
||||||
|
sheetSize: sheetSize,
|
||||||
|
backgroundImageFn: backgroundImageFn,
|
||||||
|
}}
|
||||||
|
skinsProps={{
|
||||||
|
skin: skin,
|
||||||
|
onChange: this.handleSkinChange,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,17 +531,19 @@ Picker.propTypes = {
|
||||||
include: PropTypes.arrayOf(PropTypes.string),
|
include: PropTypes.arrayOf(PropTypes.string),
|
||||||
exclude: PropTypes.arrayOf(PropTypes.string),
|
exclude: PropTypes.arrayOf(PropTypes.string),
|
||||||
autoFocus: PropTypes.bool,
|
autoFocus: PropTypes.bool,
|
||||||
custom: PropTypes.arrayOf(PropTypes.shape({
|
custom: PropTypes.arrayOf(
|
||||||
name: PropTypes.string.isRequired,
|
PropTypes.shape({
|
||||||
short_names: PropTypes.arrayOf(PropTypes.string).isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
emoticons: PropTypes.arrayOf(PropTypes.string),
|
short_names: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||||
keywords: PropTypes.arrayOf(PropTypes.string),
|
emoticons: PropTypes.arrayOf(PropTypes.string),
|
||||||
imageUrl: PropTypes.string.isRequired,
|
keywords: PropTypes.arrayOf(PropTypes.string),
|
||||||
})),
|
imageUrl: PropTypes.string.isRequired,
|
||||||
|
})
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
Picker.defaultProps = {
|
Picker.defaultProps = {
|
||||||
onClick: (() => {}),
|
onClick: () => {},
|
||||||
emojiSize: 24,
|
emojiSize: 24,
|
||||||
perLine: 9,
|
perLine: 9,
|
||||||
i18n: {},
|
i18n: {},
|
||||||
|
|
|
@ -1,42 +1,37 @@
|
||||||
import React from 'react';
|
import React from 'react'
|
||||||
import TestUtils from 'react-dom/test-utils';
|
import TestUtils from 'react-dom/test-utils'
|
||||||
import Picker from './picker';
|
import Picker from './picker'
|
||||||
|
|
||||||
const {
|
const { click } = TestUtils.Simulate
|
||||||
click
|
|
||||||
} = TestUtils.Simulate;
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
renderIntoDocument,
|
renderIntoDocument,
|
||||||
scryRenderedComponentsWithType,
|
scryRenderedComponentsWithType,
|
||||||
findRenderedComponentWithType,
|
findRenderedComponentWithType,
|
||||||
} = TestUtils;
|
} = TestUtils
|
||||||
|
|
||||||
describe('Picker', () => {
|
describe('Picker', () => {
|
||||||
let subject;
|
let subject
|
||||||
|
|
||||||
it('works', () => {
|
it('works', () => {
|
||||||
subject = render();
|
subject = render()
|
||||||
expect(subject).toBeDefined();
|
expect(subject).toBeDefined()
|
||||||
});
|
})
|
||||||
|
|
||||||
describe('categories', () => {
|
describe('categories', () => {
|
||||||
it('shows 10 by default', () => {
|
it('shows 10 by default', () => {
|
||||||
subject = render();
|
subject = render()
|
||||||
expect(subject.categories.length).toEqual(10);
|
expect(subject.categories.length).toEqual(10)
|
||||||
});
|
})
|
||||||
|
|
||||||
it('will not show some based upon our filter', () => {
|
it('will not show some based upon our filter', () => {
|
||||||
subject = render({emojisToShowFilter: (unified) => false});
|
subject = render({ emojisToShowFilter: unified => false })
|
||||||
expect(subject.categories.length).toEqual(2);
|
expect(subject.categories.length).toEqual(2)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
function render(props = {}) {
|
function render(props = {}) {
|
||||||
const defaultProps = {
|
const defaultProps = {}
|
||||||
};
|
return renderIntoDocument(<Picker {...defaultProps} {...props} />)
|
||||||
return renderIntoDocument(
|
|
||||||
<Picker {...defaultProps} {...props} />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
|
@ -12,13 +12,13 @@ export default class Preview extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var { emoji } = this.state,
|
var { emoji } = this.state,
|
||||||
{ emojiProps, skinsProps, title, emoji: idleEmoji } = this.props
|
{ emojiProps, skinsProps, title, emoji: idleEmoji } = this.props
|
||||||
|
|
||||||
if (emoji) {
|
if (emoji) {
|
||||||
var emojiData = getData(emoji),
|
var emojiData = getData(emoji),
|
||||||
{ emoticons = [] } = emojiData,
|
{ emoticons = [] } = emojiData,
|
||||||
knownEmoticons = [],
|
knownEmoticons = [],
|
||||||
listedEmoticons = []
|
listedEmoticons = []
|
||||||
|
|
||||||
emoticons.forEach(emoticon => {
|
emoticons.forEach(emoticon => {
|
||||||
if (knownEmoticons.indexOf(emoticon.toLowerCase()) >= 0) {
|
if (knownEmoticons.indexOf(emoticon.toLowerCase()) >= 0) {
|
||||||
|
@ -29,43 +29,49 @@ export default class Preview extends React.PureComponent {
|
||||||
listedEmoticons.push(emoticon)
|
listedEmoticons.push(emoticon)
|
||||||
})
|
})
|
||||||
|
|
||||||
return <div className='emoji-mart-preview'>
|
return (
|
||||||
<div className='emoji-mart-preview-emoji'>
|
<div className="emoji-mart-preview">
|
||||||
{Emoji({ key: emoji.id, emoji: emoji, ...emojiProps })}
|
<div className="emoji-mart-preview-emoji">
|
||||||
</div>
|
{Emoji({ key: emoji.id, emoji: emoji, ...emojiProps })}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='emoji-mart-preview-data'>
|
<div className="emoji-mart-preview-data">
|
||||||
<div className='emoji-mart-preview-name'>{emoji.name}</div>
|
<div className="emoji-mart-preview-name">{emoji.name}</div>
|
||||||
<div className='emoji-mart-preview-shortnames'>
|
<div className="emoji-mart-preview-shortnames">
|
||||||
{emojiData.short_names.map((short_name) =>
|
{emojiData.short_names.map(short_name => (
|
||||||
<span key={short_name} className='emoji-mart-preview-shortname'>:{short_name}:</span>
|
<span key={short_name} className="emoji-mart-preview-shortname">
|
||||||
)}
|
:{short_name}:
|
||||||
</div>
|
</span>
|
||||||
<div className='emoji-mart-preview-emoticons'>
|
))}
|
||||||
{listedEmoticons.map((emoticon) =>
|
</div>
|
||||||
<span key={emoticon} className='emoji-mart-preview-emoticon'>{emoticon}</span>
|
<div className="emoji-mart-preview-emoticons">
|
||||||
)}
|
{listedEmoticons.map(emoticon => (
|
||||||
|
<span key={emoticon} className="emoji-mart-preview-emoticon">
|
||||||
|
{emoticon}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
} else {
|
} else {
|
||||||
return <div className='emoji-mart-preview'>
|
return (
|
||||||
<div className='emoji-mart-preview-emoji'>
|
<div className="emoji-mart-preview">
|
||||||
{idleEmoji && idleEmoji.length && Emoji({ emoji: idleEmoji, ...emojiProps })}
|
<div className="emoji-mart-preview-emoji">
|
||||||
</div>
|
{idleEmoji &&
|
||||||
|
idleEmoji.length &&
|
||||||
|
Emoji({ emoji: idleEmoji, ...emojiProps })}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='emoji-mart-preview-data'>
|
<div className="emoji-mart-preview-data">
|
||||||
<span className='emoji-mart-title-label'>
|
<span className="emoji-mart-title-label">{title}</span>
|
||||||
{title}
|
</div>
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='emoji-mart-preview-skins'>
|
<div className="emoji-mart-preview-skins">
|
||||||
<Skins
|
<Skins {...skinsProps} />
|
||||||
{...skinsProps}
|
</div>
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
||||||
import emojiIndex from '../utils/emoji-index'
|
import emojiIndex from '../utils/emoji-index'
|
||||||
|
|
||||||
export default class Search extends React.PureComponent {
|
export default class Search extends React.PureComponent {
|
||||||
constructor (props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.setRef = this.setRef.bind(this)
|
this.setRef = this.setRef.bind(this)
|
||||||
|
@ -13,13 +13,15 @@ export default class Search extends React.PureComponent {
|
||||||
handleChange() {
|
handleChange() {
|
||||||
var value = this.input.value
|
var value = this.input.value
|
||||||
|
|
||||||
this.props.onSearch(emojiIndex.search(value, {
|
this.props.onSearch(
|
||||||
emojisToShowFilter: this.props.emojisToShowFilter,
|
emojiIndex.search(value, {
|
||||||
maxResults: this.props.maxResults,
|
emojisToShowFilter: this.props.emojisToShowFilter,
|
||||||
include: this.props.include,
|
maxResults: this.props.maxResults,
|
||||||
exclude: this.props.exclude,
|
include: this.props.include,
|
||||||
custom: this.props.custom,
|
exclude: this.props.exclude,
|
||||||
}))
|
custom: this.props.custom,
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
setRef(c) {
|
setRef(c) {
|
||||||
|
@ -33,15 +35,17 @@ export default class Search extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
var { i18n, autoFocus } = this.props
|
var { i18n, autoFocus } = this.props
|
||||||
|
|
||||||
return <div className='emoji-mart-search'>
|
return (
|
||||||
<input
|
<div className="emoji-mart-search">
|
||||||
ref={this.setRef}
|
<input
|
||||||
type='text'
|
ref={this.setRef}
|
||||||
onChange={this.handleChange}
|
type="text"
|
||||||
placeholder={i18n.search}
|
onChange={this.handleChange}
|
||||||
autoFocus={autoFocus}
|
placeholder={i18n.search}
|
||||||
/>
|
autoFocus={autoFocus}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +57,7 @@ Search.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
Search.defaultProps = {
|
Search.defaultProps = {
|
||||||
onSearch: (() => {}),
|
onSearch: () => {},
|
||||||
maxResults: 75,
|
maxResults: 75,
|
||||||
emojisToShowFilter: null,
|
emojisToShowFilter: null,
|
||||||
autoFocus: false,
|
autoFocus: false,
|
||||||
|
|
|
@ -39,21 +39,30 @@ export default class Skins extends React.PureComponent {
|
||||||
skinToneNodes.push(
|
skinToneNodes.push(
|
||||||
<span
|
<span
|
||||||
key={`skin-tone-${skinTone}`}
|
key={`skin-tone-${skinTone}`}
|
||||||
className={`emoji-mart-skin-swatch ${selected ? 'emoji-mart-skin-swatch-selected' : ''}`}
|
className={`emoji-mart-skin-swatch ${selected
|
||||||
|
? 'emoji-mart-skin-swatch-selected'
|
||||||
|
: ''}`}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
data-skin={skinTone}
|
data-skin={skinTone}
|
||||||
className={`emoji-mart-skin emoji-mart-skin-tone-${skinTone}`} />
|
className={`emoji-mart-skin emoji-mart-skin-tone-${skinTone}`}
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div>
|
return (
|
||||||
<div className={`emoji-mart-skin-swatches ${opened ? 'emoji-mart-skin-swatches-opened' : ''}`}>
|
<div>
|
||||||
{skinToneNodes}
|
<div
|
||||||
|
className={`emoji-mart-skin-swatches ${opened
|
||||||
|
? 'emoji-mart-skin-swatches-opened'
|
||||||
|
: ''}`}
|
||||||
|
>
|
||||||
|
{skinToneNodes}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,5 +72,5 @@ Skins.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
Skins.defaultProps = {
|
Skins.defaultProps = {
|
||||||
onChange: (() => {}),
|
onChange: () => {},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import buildSearch from '../utils/build-search'
|
import buildSearch from '../utils/build-search'
|
||||||
import data from './data'
|
import data from './data'
|
||||||
|
|
||||||
function uncompress (list) {
|
function uncompress(list) {
|
||||||
for (var short_name in list) {
|
for (var short_name in list) {
|
||||||
var datum = list[short_name]
|
var datum = list[short_name]
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ function uncompress (list) {
|
||||||
short_names: datum.short_names,
|
short_names: datum.short_names,
|
||||||
name: datum.name,
|
name: datum.name,
|
||||||
keywords: datum.keywords,
|
keywords: datum.keywords,
|
||||||
emoticons: datum.emoticons
|
emoticons: datum.emoticons,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,17 @@ const _Object = Object
|
||||||
export default (function createClass() {
|
export default (function createClass() {
|
||||||
function defineProperties(target, props) {
|
function defineProperties(target, props) {
|
||||||
for (var i = 0; i < props.length; i++) {
|
for (var i = 0; i < props.length; i++) {
|
||||||
var descriptor = props[i];
|
var descriptor = props[i]
|
||||||
descriptor.enumerable = descriptor.enumerable || false;
|
descriptor.enumerable = descriptor.enumerable || false
|
||||||
descriptor.configurable = true;
|
descriptor.configurable = true
|
||||||
if ("value" in descriptor) descriptor.writable = true;
|
if ('value' in descriptor) descriptor.writable = true
|
||||||
_Object.defineProperty(target, descriptor.key, descriptor);
|
_Object.defineProperty(target, descriptor.key, descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return function (Constructor, protoProps, staticProps) {
|
return function(Constructor, protoProps, staticProps) {
|
||||||
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
if (protoProps) defineProperties(Constructor.prototype, protoProps)
|
||||||
if (staticProps) defineProperties(Constructor, staticProps);
|
if (staticProps) defineProperties(Constructor, staticProps)
|
||||||
return Constructor;
|
return Constructor
|
||||||
};
|
}
|
||||||
}());
|
})()
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
const _Object = Object
|
const _Object = Object
|
||||||
|
|
||||||
export default _Object.assign || function (target) {
|
export default _Object.assign ||
|
||||||
for (var i = 1; i < arguments.length; i++) {
|
function(target) {
|
||||||
var source = arguments[i];
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
|
var source = arguments[i]
|
||||||
|
|
||||||
for (var key in source) {
|
for (var key in source) {
|
||||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||||
target[key] = source[key];
|
target[key] = source[key]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return target;
|
return target
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
const _Object = Object
|
const _Object = Object
|
||||||
|
|
||||||
export default function inherits(subClass, superClass) {
|
export default function inherits(subClass, superClass) {
|
||||||
if (typeof superClass !== "function" && superClass !== null) {
|
if (typeof superClass !== 'function' && superClass !== null) {
|
||||||
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
throw new TypeError(
|
||||||
|
'Super expression must either be null or a function, not ' +
|
||||||
|
typeof superClass
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
subClass.prototype = _Object.create(superClass && superClass.prototype, {
|
subClass.prototype = _Object.create(superClass && superClass.prototype, {
|
||||||
|
@ -10,10 +13,12 @@ export default function inherits(subClass, superClass) {
|
||||||
value: subClass,
|
value: subClass,
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
writable: true,
|
writable: true,
|
||||||
configurable: true
|
configurable: true,
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
if (superClass) {
|
if (superClass) {
|
||||||
_Object.setPrototypeOf ? _Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
_Object.setPrototypeOf
|
||||||
|
? _Object.setPrototypeOf(subClass, superClass)
|
||||||
|
: (subClass.__proto__ = superClass)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
const _Object = Object
|
const _Object = Object
|
||||||
|
|
||||||
export default _Object.getPrototypeOf || function (O) {
|
export default _Object.getPrototypeOf ||
|
||||||
O = Object(O)
|
function(O) {
|
||||||
|
O = Object(O)
|
||||||
|
|
||||||
if (typeof O.constructor === 'function' && O instanceof O.constructor) {
|
if (typeof O.constructor === 'function' && O instanceof O.constructor) {
|
||||||
return O.constructor.prototype
|
return O.constructor.prototype
|
||||||
|
}
|
||||||
|
|
||||||
|
return O instanceof Object ? Object.prototype : null
|
||||||
}
|
}
|
||||||
|
|
||||||
return O instanceof Object ? Object.prototype : null
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
export default function possibleConstructorReturn(self, call) {
|
export default function possibleConstructorReturn(self, call) {
|
||||||
if (!self) {
|
if (!self) {
|
||||||
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
throw new ReferenceError(
|
||||||
|
"this hasn't been initialised - super() hasn't been called"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
return call && (typeof call === 'object' || typeof call === 'function')
|
||||||
};
|
? call
|
||||||
|
: self
|
||||||
|
}
|
||||||
|
|
|
@ -1,39 +1,42 @@
|
||||||
const _String = String
|
const _String = String
|
||||||
|
|
||||||
export default _String.fromCodePoint || function stringFromCodePoint() {
|
export default _String.fromCodePoint ||
|
||||||
var MAX_SIZE = 0x4000;
|
function stringFromCodePoint() {
|
||||||
var codeUnits = [];
|
var MAX_SIZE = 0x4000
|
||||||
var highSurrogate;
|
var codeUnits = []
|
||||||
var lowSurrogate;
|
var highSurrogate
|
||||||
var index = -1;
|
var lowSurrogate
|
||||||
var length = arguments.length;
|
var index = -1
|
||||||
if (!length) {
|
var length = arguments.length
|
||||||
return '';
|
if (!length) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
var result = ''
|
||||||
|
while (++index < length) {
|
||||||
|
var codePoint = Number(arguments[index])
|
||||||
|
if (
|
||||||
|
!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
|
||||||
|
codePoint < 0 || // not a valid Unicode code point
|
||||||
|
codePoint > 0x10ffff || // not a valid Unicode code point
|
||||||
|
Math.floor(codePoint) != codePoint // not an integer
|
||||||
|
) {
|
||||||
|
throw RangeError('Invalid code point: ' + codePoint)
|
||||||
|
}
|
||||||
|
if (codePoint <= 0xffff) {
|
||||||
|
// BMP code point
|
||||||
|
codeUnits.push(codePoint)
|
||||||
|
} else {
|
||||||
|
// Astral code point; split in surrogate halves
|
||||||
|
// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
|
||||||
|
codePoint -= 0x10000
|
||||||
|
highSurrogate = (codePoint >> 10) + 0xd800
|
||||||
|
lowSurrogate = codePoint % 0x400 + 0xdc00
|
||||||
|
codeUnits.push(highSurrogate, lowSurrogate)
|
||||||
|
}
|
||||||
|
if (index + 1 === length || codeUnits.length > MAX_SIZE) {
|
||||||
|
result += String.fromCharCode.apply(null, codeUnits)
|
||||||
|
codeUnits.length = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
var result = '';
|
|
||||||
while (++index < length) {
|
|
||||||
var codePoint = Number(arguments[index]);
|
|
||||||
if (
|
|
||||||
!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
|
|
||||||
codePoint < 0 || // not a valid Unicode code point
|
|
||||||
codePoint > 0x10FFFF || // not a valid Unicode code point
|
|
||||||
Math.floor(codePoint) != codePoint // not an integer
|
|
||||||
) {
|
|
||||||
throw RangeError('Invalid code point: ' + codePoint);
|
|
||||||
}
|
|
||||||
if (codePoint <= 0xFFFF) { // BMP code point
|
|
||||||
codeUnits.push(codePoint);
|
|
||||||
} else { // Astral code point; split in surrogate halves
|
|
||||||
// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
|
|
||||||
codePoint -= 0x10000;
|
|
||||||
highSurrogate = (codePoint >> 10) + 0xD800;
|
|
||||||
lowSurrogate = (codePoint % 0x400) + 0xDC00;
|
|
||||||
codeUnits.push(highSurrogate, lowSurrogate);
|
|
||||||
}
|
|
||||||
if (index + 1 === length || codeUnits.length > MAX_SIZE) {
|
|
||||||
result += String.fromCharCode.apply(null, codeUnits);
|
|
||||||
codeUnits.length = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ export default data => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
(Array.isArray(strings) ? strings : [strings]).forEach((string) => {
|
;(Array.isArray(strings) ? strings : [strings]).forEach(string => {
|
||||||
(split ? string.split(/[-|_|\s]+/) : [string]).forEach((s) => {
|
;(split ? string.split(/[-|_|\s]+/) : [string]).forEach(s => {
|
||||||
s = s.toLowerCase()
|
s = s.toLowerCase()
|
||||||
|
|
||||||
if (search.indexOf(s) == -1) {
|
if (search.indexOf(s) == -1) {
|
||||||
|
|
|
@ -8,8 +8,8 @@ var emoticonsList = {}
|
||||||
|
|
||||||
for (let emoji in data.emojis) {
|
for (let emoji in data.emojis) {
|
||||||
let emojiData = data.emojis[emoji],
|
let emojiData = data.emojis[emoji],
|
||||||
{ short_names, emoticons } = emojiData,
|
{ short_names, emoticons } = emojiData,
|
||||||
id = short_names[0]
|
id = short_names[0]
|
||||||
|
|
||||||
if (emoticons) {
|
if (emoticons) {
|
||||||
emoticons.forEach(emoticon => {
|
emoticons.forEach(emoticon => {
|
||||||
|
@ -26,7 +26,7 @@ for (let emoji in data.emojis) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCustomToPool(custom, pool) {
|
function addCustomToPool(custom, pool) {
|
||||||
custom.forEach((emoji) => {
|
custom.forEach(emoji => {
|
||||||
let emojiId = emoji.id || emoji.short_names[0]
|
let emojiId = emoji.id || emoji.short_names[0]
|
||||||
|
|
||||||
if (emojiId && !pool[emojiId]) {
|
if (emojiId && !pool[emojiId]) {
|
||||||
|
@ -36,7 +36,10 @@ function addCustomToPool(custom, pool) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function search(value, { emojisToShowFilter, maxResults, include, exclude, custom = [] } = {}) {
|
function search(
|
||||||
|
value,
|
||||||
|
{ emojisToShowFilter, maxResults, include, exclude, custom = [] } = {}
|
||||||
|
) {
|
||||||
addCustomToPool(custom, originalPool)
|
addCustomToPool(custom, originalPool)
|
||||||
|
|
||||||
maxResults || (maxResults = 75)
|
maxResults || (maxResults = 75)
|
||||||
|
@ -44,7 +47,7 @@ function search(value, { emojisToShowFilter, maxResults, include, exclude, custo
|
||||||
exclude || (exclude = [])
|
exclude || (exclude = [])
|
||||||
|
|
||||||
var results = null,
|
var results = null,
|
||||||
pool = originalPool
|
pool = originalPool
|
||||||
|
|
||||||
if (value.length) {
|
if (value.length) {
|
||||||
if (value == '-' || value == '-1') {
|
if (value == '-' || value == '-1') {
|
||||||
|
@ -52,7 +55,7 @@ function search(value, { emojisToShowFilter, maxResults, include, exclude, custo
|
||||||
}
|
}
|
||||||
|
|
||||||
var values = value.toLowerCase().split(/[\s|,|\-|_]+/),
|
var values = value.toLowerCase().split(/[\s|,|\-|_]+/),
|
||||||
allResults = []
|
allResults = []
|
||||||
|
|
||||||
if (values.length > 2) {
|
if (values.length > 2) {
|
||||||
values = [values[0], values[1]]
|
values = [values[0], values[1]]
|
||||||
|
@ -62,72 +65,84 @@ function search(value, { emojisToShowFilter, maxResults, include, exclude, custo
|
||||||
pool = {}
|
pool = {}
|
||||||
|
|
||||||
data.categories.forEach(category => {
|
data.categories.forEach(category => {
|
||||||
let isIncluded = include && include.length ? include.indexOf(category.name.toLowerCase()) > -1 : true
|
let isIncluded =
|
||||||
let isExcluded = exclude && exclude.length ? exclude.indexOf(category.name.toLowerCase()) > -1 : false
|
include && include.length
|
||||||
|
? include.indexOf(category.name.toLowerCase()) > -1
|
||||||
|
: true
|
||||||
|
let isExcluded =
|
||||||
|
exclude && exclude.length
|
||||||
|
? exclude.indexOf(category.name.toLowerCase()) > -1
|
||||||
|
: false
|
||||||
if (!isIncluded || isExcluded) {
|
if (!isIncluded || isExcluded) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
category.emojis.forEach(emojiId => pool[emojiId] = data.emojis[emojiId])
|
category.emojis.forEach(
|
||||||
|
emojiId => (pool[emojiId] = data.emojis[emojiId])
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (custom.length) {
|
if (custom.length) {
|
||||||
let customIsIncluded = include && include.length ? include.indexOf('custom') > -1 : true
|
let customIsIncluded =
|
||||||
let customIsExcluded = exclude && exclude.length ? exclude.indexOf('custom') > -1 : false
|
include && include.length ? include.indexOf('custom') > -1 : true
|
||||||
|
let customIsExcluded =
|
||||||
|
exclude && exclude.length ? exclude.indexOf('custom') > -1 : false
|
||||||
if (customIsIncluded && !customIsExcluded) {
|
if (customIsIncluded && !customIsExcluded) {
|
||||||
addCustomToPool(custom, pool)
|
addCustomToPool(custom, pool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allResults = values.map((value) => {
|
allResults = values
|
||||||
var aPool = pool,
|
.map(value => {
|
||||||
|
var aPool = pool,
|
||||||
aIndex = index,
|
aIndex = index,
|
||||||
length = 0
|
length = 0
|
||||||
|
|
||||||
for (let charIndex = 0; charIndex < value.length; charIndex++) {
|
for (let charIndex = 0; charIndex < value.length; charIndex++) {
|
||||||
const char = value[charIndex]
|
const char = value[charIndex]
|
||||||
length++
|
length++
|
||||||
|
|
||||||
aIndex[char] || (aIndex[char] = {})
|
aIndex[char] || (aIndex[char] = {})
|
||||||
aIndex = aIndex[char]
|
aIndex = aIndex[char]
|
||||||
|
|
||||||
if (!aIndex.results) {
|
if (!aIndex.results) {
|
||||||
let scores = {}
|
let scores = {}
|
||||||
|
|
||||||
aIndex.results = []
|
aIndex.results = []
|
||||||
aIndex.pool = {}
|
aIndex.pool = {}
|
||||||
|
|
||||||
for (let id in aPool) {
|
for (let id in aPool) {
|
||||||
let emoji = aPool[id],
|
let emoji = aPool[id],
|
||||||
{ search } = emoji,
|
{ search } = emoji,
|
||||||
sub = value.substr(0, length),
|
sub = value.substr(0, length),
|
||||||
subIndex = search.indexOf(sub)
|
subIndex = search.indexOf(sub)
|
||||||
|
|
||||||
if (subIndex != -1) {
|
if (subIndex != -1) {
|
||||||
let score = subIndex + 1
|
let score = subIndex + 1
|
||||||
if (sub == id) score = 0
|
if (sub == id) score = 0
|
||||||
|
|
||||||
aIndex.results.push(emojisList[id])
|
aIndex.results.push(emojisList[id])
|
||||||
aIndex.pool[id] = emoji
|
aIndex.pool[id] = emoji
|
||||||
|
|
||||||
scores[id] = score
|
scores[id] = score
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
aIndex.results.sort((a, b) => {
|
aIndex.results.sort((a, b) => {
|
||||||
var aScore = scores[a.id],
|
var aScore = scores[a.id],
|
||||||
bScore = scores[b.id]
|
bScore = scores[b.id]
|
||||||
|
|
||||||
return aScore - bScore
|
return aScore - bScore
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
aPool = aIndex.pool
|
||||||
}
|
}
|
||||||
|
|
||||||
aPool = aIndex.pool
|
return aIndex.results
|
||||||
}
|
})
|
||||||
|
.filter(a => a)
|
||||||
return aIndex.results
|
|
||||||
}).filter(a => a)
|
|
||||||
|
|
||||||
if (allResults.length > 1) {
|
if (allResults.length > 1) {
|
||||||
results = intersect.apply(null, allResults)
|
results = intersect.apply(null, allResults)
|
||||||
|
@ -140,7 +155,9 @@ function search(value, { emojisToShowFilter, maxResults, include, exclude, custo
|
||||||
|
|
||||||
if (results) {
|
if (results) {
|
||||||
if (emojisToShowFilter) {
|
if (emojisToShowFilter) {
|
||||||
results = results.filter((result) => emojisToShowFilter(data.emojis[result.id].unified))
|
results = results.filter(result =>
|
||||||
|
emojisToShowFilter(data.emojis[result.id].unified)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results && results.length > maxResults) {
|
if (results && results.length > maxResults) {
|
||||||
|
|
|
@ -1,36 +1,42 @@
|
||||||
import emojiIndex from './emoji-index';
|
import emojiIndex from './emoji-index'
|
||||||
|
|
||||||
describe('#emojiIndex', () => {
|
describe('#emojiIndex', () => {
|
||||||
describe('search', function() {
|
describe('search', function() {
|
||||||
it('should work', () => {
|
it('should work', () => {
|
||||||
expect(emojiIndex.search('pineapple')).toEqual([{
|
expect(emojiIndex.search('pineapple')).toEqual([
|
||||||
id: 'pineapple',
|
{
|
||||||
name: 'Pineapple',
|
id: 'pineapple',
|
||||||
colons: ':pineapple:',
|
name: 'Pineapple',
|
||||||
emoticons: [ ],
|
colons: ':pineapple:',
|
||||||
unified: '1f34d',
|
emoticons: [],
|
||||||
skin: null,
|
unified: '1f34d',
|
||||||
native: '🍍'
|
skin: null,
|
||||||
}]);
|
native: '🍍',
|
||||||
});
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
it('should filter only emojis we care about, exclude pineapple', () => {
|
it('should filter only emojis we care about, exclude pineapple', () => {
|
||||||
let emojisToShowFilter = (unified) => unified !== '1F34D';
|
let emojisToShowFilter = unified => unified !== '1F34D'
|
||||||
expect(emojiIndex.search('apple', { emojisToShowFilter }).map((obj) => obj.id))
|
expect(
|
||||||
.not.toContain('pineapple');
|
emojiIndex.search('apple', { emojisToShowFilter }).map(obj => obj.id)
|
||||||
});
|
).not.toContain('pineapple')
|
||||||
|
})
|
||||||
|
|
||||||
it('can include/exclude categories', () => {
|
it('can include/exclude categories', () => {
|
||||||
expect(emojiIndex.search('flag', { include: ['people'] }))
|
expect(emojiIndex.search('flag', { include: ['people'] })).toEqual([])
|
||||||
.toEqual([])
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can search for thinking_face', () => {
|
it('can search for thinking_face', () => {
|
||||||
expect(emojiIndex.search('thinking_fac').map(x => x.id)).toEqual(['thinking_face'])
|
expect(emojiIndex.search('thinking_fac').map(x => x.id)).toEqual([
|
||||||
|
'thinking_face',
|
||||||
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can search for woman-facepalming', () => {
|
it('can search for woman-facepalming', () => {
|
||||||
expect(emojiIndex.search('woman-facep').map(x => x.id)).toEqual(['woman-facepalming']);
|
expect(emojiIndex.search('woman-facep').map(x => x.id)).toEqual([
|
||||||
|
'woman-facepalming',
|
||||||
|
])
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
|
@ -52,11 +52,13 @@ function get(perLine) {
|
||||||
|
|
||||||
for (let key in frequently) {
|
for (let key in frequently) {
|
||||||
if (frequently.hasOwnProperty(key)) {
|
if (frequently.hasOwnProperty(key)) {
|
||||||
frequentlyKeys.push(key);
|
frequentlyKeys.push(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const sorted = frequentlyKeys.sort((a, b) => frequently[a] - frequently[b]).reverse()
|
const sorted = frequentlyKeys
|
||||||
|
.sort((a, b) => frequently[a] - frequently[b])
|
||||||
|
.reverse()
|
||||||
const sliced = sorted.slice(0, quantity)
|
const sliced = sorted.slice(0, quantity)
|
||||||
|
|
||||||
const last = store.get('last')
|
const last = store.get('last')
|
||||||
|
|
|
@ -5,22 +5,28 @@ import stringFromCodePoint from '../polyfills/stringFromCodePoint'
|
||||||
const _JSON = JSON
|
const _JSON = JSON
|
||||||
|
|
||||||
const COLONS_REGEX = /^(?:\:([^\:]+)\:)(?:\:skin-tone-(\d)\:)?$/
|
const COLONS_REGEX = /^(?:\:([^\:]+)\:)(?:\:skin-tone-(\d)\:)?$/
|
||||||
const SKINS = [
|
const SKINS = ['1F3FA', '1F3FB', '1F3FC', '1F3FD', '1F3FE', '1F3FF']
|
||||||
'1F3FA', '1F3FB', '1F3FC',
|
|
||||||
'1F3FD', '1F3FE', '1F3FF',
|
|
||||||
]
|
|
||||||
|
|
||||||
function unifiedToNative(unified) {
|
function unifiedToNative(unified) {
|
||||||
var unicodes = unified.split('-'),
|
var unicodes = unified.split('-'),
|
||||||
codePoints = unicodes.map((u) => `0x${u}`)
|
codePoints = unicodes.map(u => `0x${u}`)
|
||||||
|
|
||||||
return stringFromCodePoint.apply(null, codePoints)
|
return stringFromCodePoint.apply(null, codePoints)
|
||||||
}
|
}
|
||||||
|
|
||||||
function sanitize(emoji) {
|
function sanitize(emoji) {
|
||||||
var { name, short_names, skin_tone, skin_variations, emoticons, unified, custom, imageUrl } = emoji,
|
var {
|
||||||
id = emoji.id || short_names[0],
|
name,
|
||||||
colons = `:${id}:`
|
short_names,
|
||||||
|
skin_tone,
|
||||||
|
skin_variations,
|
||||||
|
emoticons,
|
||||||
|
unified,
|
||||||
|
custom,
|
||||||
|
imageUrl,
|
||||||
|
} = emoji,
|
||||||
|
id = emoji.id || short_names[0],
|
||||||
|
colons = `:${id}:`
|
||||||
|
|
||||||
if (custom) {
|
if (custom) {
|
||||||
return {
|
return {
|
||||||
|
@ -29,7 +35,7 @@ function sanitize(emoji) {
|
||||||
colons,
|
colons,
|
||||||
emoticons,
|
emoticons,
|
||||||
custom,
|
custom,
|
||||||
imageUrl
|
imageUrl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +106,7 @@ function getData(emoji, skin, set) {
|
||||||
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.variations && emojiData.variations) {
|
||||||
delete emojiData.variations
|
delete emojiData.variations
|
||||||
|
@ -145,7 +151,7 @@ function deepMerge(a, b) {
|
||||||
|
|
||||||
for (let key in a) {
|
for (let key in a) {
|
||||||
let originalValue = a[key],
|
let originalValue = a[key],
|
||||||
value = originalValue
|
value = originalValue
|
||||||
|
|
||||||
if (b.hasOwnProperty(key)) {
|
if (b.hasOwnProperty(key)) {
|
||||||
value = b[key]
|
value = b[key]
|
||||||
|
@ -185,5 +191,5 @@ export {
|
||||||
intersect,
|
intersect,
|
||||||
deepMerge,
|
deepMerge,
|
||||||
unifiedToNative,
|
unifiedToNative,
|
||||||
measureScrollbar
|
measureScrollbar,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ var NAMESPACE = 'emoji-mart'
|
||||||
|
|
||||||
const _JSON = JSON
|
const _JSON = JSON
|
||||||
|
|
||||||
var isLocalStorageSupported = typeof window !== 'undefined' &&
|
var isLocalStorageSupported =
|
||||||
'localStorage' in window
|
typeof window !== 'undefined' && 'localStorage' in window
|
||||||
|
|
||||||
function update(state) {
|
function update(state) {
|
||||||
for (let key in state) {
|
for (let key in state) {
|
||||||
|
@ -16,8 +16,7 @@ function set(key, value) {
|
||||||
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) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function get(key) {
|
function get(key) {
|
||||||
|
|
|
@ -7,28 +7,33 @@
|
||||||
|
|
||||||
var isWindowAvailable = typeof window !== 'undefined'
|
var isWindowAvailable = typeof window !== 'undefined'
|
||||||
|
|
||||||
isWindowAvailable && (function() {
|
isWindowAvailable &&
|
||||||
var lastTime = 0;
|
(function() {
|
||||||
var vendors = ['ms', 'moz', 'webkit', 'o'];
|
var lastTime = 0
|
||||||
|
var vendors = ['ms', 'moz', 'webkit', 'o']
|
||||||
|
|
||||||
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
||||||
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
|
window.requestAnimationFrame =
|
||||||
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
|
window[vendors[x] + 'RequestAnimationFrame']
|
||||||
|| window[vendors[x]+'CancelRequestAnimationFrame'];
|
window.cancelAnimationFrame =
|
||||||
|
window[vendors[x] + 'CancelAnimationFrame'] ||
|
||||||
|
window[vendors[x] + 'CancelRequestAnimationFrame']
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!window.requestAnimationFrame)
|
if (!window.requestAnimationFrame)
|
||||||
window.requestAnimationFrame = function(callback, element) {
|
window.requestAnimationFrame = function(callback, element) {
|
||||||
var currTime = new Date().getTime();
|
var currTime = new Date().getTime()
|
||||||
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
var timeToCall = Math.max(0, 16 - (currTime - lastTime))
|
||||||
var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
|
var id = window.setTimeout(function() {
|
||||||
|
callback(currTime + timeToCall)
|
||||||
|
}, timeToCall)
|
||||||
|
|
||||||
lastTime = currTime + timeToCall;
|
lastTime = currTime + timeToCall
|
||||||
return id;
|
return id
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!window.cancelAnimationFrame)
|
if (!window.cancelAnimationFrame)
|
||||||
window.cancelAnimationFrame = function(id) {
|
window.cancelAnimationFrame = function(id) {
|
||||||
clearTimeout(id);
|
clearTimeout(id)
|
||||||
};
|
}
|
||||||
}());
|
})()
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
var path = require('path')
|
var path = require('path')
|
||||||
var pack = require('../package.json')
|
var pack = require('../package.json')
|
||||||
var webpack = require('webpack')
|
var webpack = require('webpack')
|
||||||
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
|
||||||
|
.BundleAnalyzerPlugin
|
||||||
|
|
||||||
var PROD = process.env.NODE_ENV === 'production';
|
var PROD = process.env.NODE_ENV === 'production'
|
||||||
var TEST = process.env.NODE_ENV === 'test';
|
var TEST = process.env.NODE_ENV === 'test'
|
||||||
|
|
||||||
var config = {
|
var config = {
|
||||||
entry: path.resolve('src/index.js'),
|
entry: path.resolve('src/index.js'),
|
||||||
|
@ -22,28 +23,22 @@ var config = {
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
use: 'babel-loader',
|
use: 'babel-loader',
|
||||||
include: [
|
include: [path.resolve('src'), path.resolve('data')],
|
||||||
path.resolve('src'),
|
|
||||||
path.resolve('node_modules/measure-scrollbar'),
|
|
||||||
path.resolve('data'),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.svg$/,
|
test: /\.svg$/,
|
||||||
use: [
|
use: [
|
||||||
{
|
{
|
||||||
loader: 'babel-loader'
|
loader: 'babel-loader',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
loader: 'svg-jsx-loader',
|
loader: 'svg-jsx-loader',
|
||||||
options: {
|
options: {
|
||||||
es6: true
|
es6: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
include: [
|
include: [path.resolve('src/svgs')],
|
||||||
path.resolve('src/svgs'),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -64,7 +59,7 @@ var config = {
|
||||||
if (!TEST) {
|
if (!TEST) {
|
||||||
config.externals = config.externals.concat([
|
config.externals = config.externals.concat([
|
||||||
{
|
{
|
||||||
'react': {
|
react: {
|
||||||
root: 'React',
|
root: 'React',
|
||||||
commonjs2: 'react',
|
commonjs2: 'react',
|
||||||
commonjs: 'react',
|
commonjs: 'react',
|
||||||
|
|
|
@ -4751,6 +4751,10 @@ preserve@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
|
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
|
||||||
|
|
||||||
|
prettier@1.7.4:
|
||||||
|
version "1.7.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.7.4.tgz#5e8624ae9363c80f95ec644584ecdf55d74f93fa"
|
||||||
|
|
||||||
private@^0.1.6, private@^0.1.7, private@~0.1.5:
|
private@^0.1.6, private@^0.1.7, private@~0.1.5:
|
||||||
version "0.1.7"
|
version "0.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1"
|
resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1"
|
||||||
|
|
Loading…
Reference in New Issue