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