diff --git a/src/components/anchors.js b/src/components/anchors.js index 212dff9..aae89bb 100644 --- a/src/components/anchors.js +++ b/src/components/anchors.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import * as SVGs from '../svgs' -export default class Anchors extends React.Component { +export default class Anchors extends React.PureComponent { constructor(props) { super(props) @@ -14,6 +14,15 @@ export default class Anchors extends React.Component { this.state = { selected: defaultCategory.name } + + this.handleClick = this.handleClick.bind(this) + } + + handleClick (e) { + var index = e.currentTarget.getAttribute('data-index') + var { categories, onAnchorClick } = this.props + + onAnchorClick(categories[index], index) } render() { @@ -34,7 +43,8 @@ export default class Anchors extends React.Component { onAnchorClick(category, i)} + data-index={i} + onClick={this.handleClick} className={`emoji-mart-anchor ${isSelected ? 'emoji-mart-anchor-selected' : ''}`} style={{ color: isSelected ? color : null }} > diff --git a/src/components/category.js b/src/components/category.js index 49b70f5..282f386 100644 --- a/src/components/category.js +++ b/src/components/category.js @@ -5,6 +5,13 @@ import frequently from '../utils/frequently' import { Emoji } from '.' export default class Category extends React.Component { + constructor(props) { + super(props) + + this.setContainerRef = this.setContainerRef.bind(this) + this.setLabelRef = this.setLabelRef.bind(this) + } + componentDidMount() { this.parent = this.container.parentNode @@ -133,29 +140,26 @@ export default class Category extends React.Component { } } - return
+ return
- {i18n.categories[name.toLowerCase()]} + {i18n.categories[name.toLowerCase()]}
{emojis && emojis.map((emoji) => - Emoji({ - emoji: emoji, - ...emojiProps - }) + )} {emojis && !emojis.length &&
- {Emoji({ - ...emojiProps, - size: 38, - emoji: 'sleuth_or_spy', - onOver: null, - onLeave: null, - onClick: null, - })} +
diff --git a/src/components/emoji.js b/src/components/emoji.js index ae6dc2b..7e3edea 100644 --- a/src/components/emoji.js +++ b/src/components/emoji.js @@ -23,87 +23,98 @@ const _getSanitizedData = (props) => { return getSanitizedData(emoji, skin, set) } -const _handleClick = (e, props) => { - if (!props.onClick) { return } - var { onClick } = props, - emoji = _getSanitizedData(props) +export default class Emoji extends React.PureComponent { - onClick(emoji, e) -} + constructor (props) { + super(props) -const _handleOver = (e, props) => { - if (!props.onOver) { return } - var { onOver } = props, - emoji = _getSanitizedData(props) - - onOver(emoji, e) -} - -const _handleLeave = (e, props) => { - if (!props.onLeave) { return } - var { onLeave } = props, - emoji = _getSanitizedData(props) - - onLeave(emoji, e) -} - -const Emoji = (props) => { - for (let k in Emoji.defaultProps) { - if (props[k] == undefined && Emoji.defaultProps[k] != undefined) { - props[k] = Emoji.defaultProps[k] - } + this.handleClick = this.handleClick.bind(this) + this.handleEnter = this.handleEnter.bind(this) + this.handleLeave = this.handleLeave.bind(this) } - var { unified, custom, imageUrl } = _getData(props), - style = {}, - children = props.children + handleClick (e) { + if (!this.props.onClick) { return } - if (!unified && !custom) { - return null + const { onClick } = this.props, + emoji = _getSanitizedData(this.props) + + onClick(emoji, e) } - if (props.native && unified) { - style = { fontSize: props.size } - children = unifiedToNative(unified) + handleEnter (e) { + if (!this.props.onOver) { return } - if (props.forceSize) { - style.display = 'inline-block' - style.width = props.size - style.height = props.size - } - } else if (custom) { - style = { - width: props.size, - height: props.size, - display: 'inline-block', - backgroundImage: `url(${imageUrl})`, - backgroundSize: '100%', - } - } else { - let setHasEmoji = _getData(props)[`has_img_${props.set}`] + const { onOver } = this.props, + emoji = _getSanitizedData(this.props) - if (!setHasEmoji) { + onOver(emoji, e) + } + + handleLeave (e) { + if (!this.props.onLeave) { return } + + const { onLeave } = this.props, + emoji = _getSanitizedData(this.props) + + onLeave(emoji, e) + } + + render () { + var props = this.props; + + var { unified, custom, imageUrl } = _getData(props), + style = {}, + children = props.children + + if (!unified && !custom) { return null } - style = { - width: props.size, - height: props.size, - display: 'inline-block', - backgroundImage: `url(${props.backgroundImageFn(props.set, props.sheetSize)})`, - backgroundSize: `${100 * SHEET_COLUMNS}%`, - backgroundPosition: _getPosition(props), + if (props.native && unified) { + style = { fontSize: props.size } + children = unifiedToNative(unified) + + if (props.forceSize) { + style.display = 'inline-block' + style.width = props.size + style.height = props.size + } + } else if (custom) { + style = { + width: props.size, + height: props.size, + display: 'inline-block', + backgroundImage: `url(${imageUrl})`, + backgroundSize: '100%', + } + } else { + let setHasEmoji = _getData(props)[`has_img_${props.set}`] + + if (!setHasEmoji) { + return null + } + + style = { + width: props.size, + height: props.size, + display: 'inline-block', + backgroundImage: `url(${props.backgroundImageFn(props.set, props.sheetSize)})`, + backgroundSize: `${100 * SHEET_COLUMNS}%`, + backgroundPosition: _getPosition(props), + } } + + return + {children} + } - return _handleClick(e, props)} - onMouseEnter={(e) => _handleOver(e, props)} - onMouseLeave={(e) => _handleLeave(e, props)} - className='emoji-mart-emoji'> - {children} - } Emoji.propTypes = { @@ -134,5 +145,3 @@ Emoji.defaultProps = { onLeave: (() => {}), onClick: (() => {}), } - -export default Emoji diff --git a/src/components/picker.js b/src/components/picker.js index dd65d48..213f738 100644 --- a/src/components/picker.js +++ b/src/components/picker.js @@ -33,7 +33,7 @@ const I18N = { }, } -export default class Picker extends React.Component { +export default class Picker extends React.PureComponent { constructor(props) { super(props) @@ -116,6 +116,19 @@ export default class Picker extends React.Component { } this.categories.unshift(SEARCH_CATEGORY) + + 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.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) } componentWillReceiveProps(props) { @@ -206,7 +219,7 @@ export default class Picker extends React.Component { handleScroll() { if (!this.waitingForPaint) { this.waitingForPaint = true - window.requestAnimationFrame(this.handleScrollPaint.bind(this)) + window.requestAnimationFrame(this.handleScrollPaint) } } @@ -368,17 +381,17 @@ export default class Picker extends React.Component { return
-
+
{this.getCategories().map((category, i) => { return })} @@ -417,7 +430,7 @@ export default class Picker extends React.Component { {showPreview &&
} diff --git a/src/components/preview.js b/src/components/preview.js index 5d2b53a..7bf5662 100644 --- a/src/components/preview.js +++ b/src/components/preview.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types' import { Emoji, Skins } from '.' import { getData } from '../utils' -export default class Preview extends React.Component { +export default class Preview extends React.PureComponent { constructor(props) { super(props) this.state = { emoji: null } @@ -31,11 +31,7 @@ export default class Preview extends React.Component { return
- {Emoji({ - key: emoji.id, - emoji: emoji, - ...emojiProps, - })} +
@@ -55,10 +51,7 @@ export default class Preview extends React.Component { } else { return
- {idleEmoji && idleEmoji.length && Emoji({ - emoji: idleEmoji, - ...emojiProps, - })} + {idleEmoji && idleEmoji.length && }
diff --git a/src/components/search.js b/src/components/search.js index 53a12ba..ff00de8 100644 --- a/src/components/search.js +++ b/src/components/search.js @@ -2,7 +2,14 @@ import React from 'react' import PropTypes from 'prop-types' import emojiIndex from '../utils/emoji-index' -export default class Search extends React.Component { +export default class Search extends React.PureComponent { + constructor (props) { + super(props) + + this.setRef = this.setRef.bind(this) + this.handleChange = this.handleChange.bind(this) + } + handleChange() { var value = this.input.value @@ -28,9 +35,9 @@ export default class Search extends React.Component { return
diff --git a/src/components/skins.js b/src/components/skins.js index 8cfe5d5..f99c6ca 100644 --- a/src/components/skins.js +++ b/src/components/skins.js @@ -1,16 +1,19 @@ import React from 'react' import PropTypes from 'prop-types' -export default class Skins extends React.Component { +export default class Skins extends React.PureComponent { constructor(props) { super(props) this.state = { opened: false, } + + this.handleClick = this.handleClick.bind(this) } - handleClick(skin) { + handleClick(e) { + var skin = e.currentTarget.getAttribute('data-skin') var { onChange } = this.props if (!this.state.opened) { @@ -39,9 +42,9 @@ export default class Skins extends React.Component { className={`emoji-mart-skin-swatch ${selected ? 'emoji-mart-skin-swatch-selected' : ''}`} > this.handleClick(skinTone)} - className={`emoji-mart-skin emoji-mart-skin-tone-${skinTone}`}> - + onClick={this.handleClick} + data-skin={skinTone} + className={`emoji-mart-skin emoji-mart-skin-tone-${skinTone}`} /> ) }