2016-05-31 14:36:52 +00:00
|
|
|
import React from 'react'
|
2017-05-05 01:38:03 +00:00
|
|
|
import PropTypes from 'prop-types'
|
2016-06-02 17:21:31 +00:00
|
|
|
|
2018-07-31 19:01:34 +00:00
|
|
|
import * as icons from '../../svgs'
|
2018-04-26 15:47:30 +00:00
|
|
|
import store from '../../utils/store'
|
|
|
|
import frequently from '../../utils/frequently'
|
2019-02-13 19:56:42 +00:00
|
|
|
import { deepMerge, measureScrollbar, getSanitizedData } from '../../utils'
|
2018-04-30 00:55:13 +00:00
|
|
|
import { uncompress } from '../../utils/data'
|
2018-12-18 19:24:52 +00:00
|
|
|
import { PickerPropTypes } from '../../utils/shared-props'
|
2016-07-20 18:45:28 +00:00
|
|
|
|
2018-11-13 10:19:16 +00:00
|
|
|
import Anchors from '../anchors'
|
|
|
|
import Category from '../category'
|
|
|
|
import Preview from '../preview'
|
|
|
|
import Search from '../search'
|
2018-12-18 19:24:52 +00:00
|
|
|
import { PickerDefaultProps } from '../../utils/shared-default-props'
|
2016-06-02 15:26:48 +00:00
|
|
|
|
2016-10-27 03:22:59 +00:00
|
|
|
const I18N = {
|
|
|
|
search: 'Search',
|
2019-03-09 21:03:00 +00:00
|
|
|
clear: 'Clear', // Accessible label on "clear" button
|
2017-04-18 15:20:17 +00:00
|
|
|
notfound: 'No Emoji Found',
|
2018-08-10 18:02:33 +00:00
|
|
|
skintext: 'Choose your default skin tone',
|
2016-10-27 03:22:59 +00:00
|
|
|
categories: {
|
|
|
|
search: 'Search Results',
|
|
|
|
recent: 'Frequently Used',
|
|
|
|
people: 'Smileys & People',
|
|
|
|
nature: 'Animals & Nature',
|
|
|
|
foods: 'Food & Drink',
|
|
|
|
activity: 'Activity',
|
|
|
|
places: 'Travel & Places',
|
|
|
|
objects: 'Objects',
|
|
|
|
symbols: 'Symbols',
|
|
|
|
flags: 'Flags',
|
2017-05-26 07:48:26 +00:00
|
|
|
custom: 'Custom',
|
2016-10-27 03:22:59 +00:00
|
|
|
},
|
2019-03-10 17:57:43 +00:00
|
|
|
categorieslabel: 'Emoji categories', // Accessible title for the list of categories
|
2019-03-09 22:19:24 +00:00
|
|
|
skintones: {
|
|
|
|
1: 'Default Skin Tone',
|
|
|
|
2: 'Light Skin Tone',
|
|
|
|
3: 'Medium-Light Skin Tone',
|
|
|
|
4: 'Medium Skin Tone',
|
|
|
|
5: 'Medium-Dark Skin Tone',
|
|
|
|
6: 'Dark Skin Tone',
|
|
|
|
},
|
2016-10-27 03:22:59 +00:00
|
|
|
}
|
|
|
|
|
2018-03-28 21:30:47 +00:00
|
|
|
export default class NimblePicker extends React.PureComponent {
|
2016-05-31 18:39:30 +00:00
|
|
|
constructor(props) {
|
|
|
|
super(props)
|
|
|
|
|
2019-06-27 20:18:16 +00:00
|
|
|
this.CUSTOM = []
|
|
|
|
|
2018-03-02 18:25:39 +00:00
|
|
|
this.RECENT_CATEGORY = { id: 'recent', name: 'Recent', emojis: null }
|
|
|
|
this.SEARCH_CATEGORY = {
|
|
|
|
id: 'search',
|
|
|
|
name: 'Search',
|
|
|
|
emojis: null,
|
|
|
|
anchor: false,
|
|
|
|
}
|
|
|
|
|
2018-04-30 00:55:13 +00:00
|
|
|
if (props.data.compressed) {
|
|
|
|
uncompress(props.data)
|
|
|
|
}
|
|
|
|
|
2018-03-28 21:30:47 +00:00
|
|
|
this.data = props.data
|
2016-10-27 03:22:59 +00:00
|
|
|
this.i18n = deepMerge(I18N, props.i18n)
|
2018-07-31 19:01:34 +00:00
|
|
|
this.icons = deepMerge(icons, props.icons)
|
2016-05-31 18:39:30 +00:00
|
|
|
this.state = {
|
2018-03-02 18:45:33 +00:00
|
|
|
skin: props.skin || store.get('skin') || props.defaultSkin,
|
2016-07-15 16:24:50 +00:00
|
|
|
firstRender: true,
|
2016-05-31 18:39:30 +00:00
|
|
|
}
|
2017-01-30 21:01:41 +00:00
|
|
|
|
2017-04-07 21:09:30 +00:00
|
|
|
this.categories = []
|
2018-03-28 21:30:47 +00:00
|
|
|
let allCategories = [].concat(this.data.categories)
|
2017-05-27 16:27:47 +00:00
|
|
|
|
|
|
|
if (props.custom.length > 0) {
|
2019-06-27 20:18:16 +00:00
|
|
|
const customCategories = {}
|
|
|
|
let customCategoriesCreated = 0
|
|
|
|
|
|
|
|
props.custom.forEach((emoji) => {
|
|
|
|
if (!customCategories[emoji.customCategory]) {
|
|
|
|
customCategories[emoji.customCategory] = {
|
|
|
|
id: emoji.customCategory
|
|
|
|
? `custom-${emoji.customCategory}`
|
|
|
|
: 'custom',
|
|
|
|
name: emoji.customCategory || 'Custom',
|
|
|
|
emojis: [],
|
|
|
|
anchor: customCategoriesCreated === 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
customCategoriesCreated++
|
|
|
|
}
|
|
|
|
|
|
|
|
const category = customCategories[emoji.customCategory]
|
|
|
|
|
|
|
|
const customEmoji = {
|
2017-05-27 16:27:47 +00:00
|
|
|
...emoji,
|
|
|
|
// `<Category />` expects emoji to have an `id`.
|
|
|
|
id: emoji.short_names[0],
|
|
|
|
custom: true,
|
|
|
|
}
|
2019-06-27 20:18:16 +00:00
|
|
|
|
|
|
|
category.emojis.push(customEmoji)
|
|
|
|
this.CUSTOM.push(customEmoji)
|
2017-05-27 16:27:47 +00:00
|
|
|
})
|
|
|
|
|
2019-12-24 02:03:16 +00:00
|
|
|
allCategories = allCategories.concat(
|
|
|
|
Object.keys(customCategories).map((key) => customCategories[key]),
|
|
|
|
)
|
2017-05-27 16:27:47 +00:00
|
|
|
}
|
2017-01-30 21:01:41 +00:00
|
|
|
|
2017-05-29 11:36:49 +00:00
|
|
|
this.hideRecent = true
|
2017-05-25 15:57:03 +00:00
|
|
|
|
2017-04-07 20:54:07 +00:00
|
|
|
if (props.include != undefined) {
|
2017-09-29 23:45:52 +00:00
|
|
|
allCategories.sort((a, b) => {
|
2017-12-15 20:04:51 +00:00
|
|
|
if (props.include.indexOf(a.id) > props.include.indexOf(b.id)) {
|
2017-04-07 20:54:07 +00:00
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2018-02-15 13:39:17 +00:00
|
|
|
return -1
|
2017-04-07 20:54:07 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-10-07 04:02:02 +00:00
|
|
|
for (
|
|
|
|
let categoryIndex = 0;
|
|
|
|
categoryIndex < allCategories.length;
|
|
|
|
categoryIndex++
|
|
|
|
) {
|
2017-09-17 08:54:22 +00:00
|
|
|
const category = allCategories[categoryIndex]
|
2017-10-07 04:02:02 +00:00
|
|
|
let isIncluded =
|
|
|
|
props.include && props.include.length
|
2017-12-15 20:04:51 +00:00
|
|
|
? props.include.indexOf(category.id) > -1
|
2017-10-07 04:02:02 +00:00
|
|
|
: true
|
|
|
|
let isExcluded =
|
|
|
|
props.exclude && props.exclude.length
|
2017-12-15 20:04:51 +00:00
|
|
|
? props.exclude.indexOf(category.id) > -1
|
2017-10-07 04:02:02 +00:00
|
|
|
: false
|
|
|
|
if (!isIncluded || isExcluded) {
|
|
|
|
continue
|
|
|
|
}
|
2017-04-04 16:00:32 +00:00
|
|
|
|
2017-04-18 14:22:32 +00:00
|
|
|
if (props.emojisToShowFilter) {
|
|
|
|
let newEmojis = []
|
2017-04-01 09:02:55 +00:00
|
|
|
|
2017-10-07 04:02:02 +00:00
|
|
|
const { emojis } = category
|
2017-09-17 08:54:22 +00:00
|
|
|
for (let emojiIndex = 0; emojiIndex < emojis.length; emojiIndex++) {
|
|
|
|
const emoji = emojis[emojiIndex]
|
2018-03-28 21:30:47 +00:00
|
|
|
if (props.emojisToShowFilter(this.data.emojis[emoji] || emoji)) {
|
2017-04-18 14:22:32 +00:00
|
|
|
newEmojis.push(emoji)
|
|
|
|
}
|
2017-01-30 21:01:41 +00:00
|
|
|
}
|
|
|
|
|
2017-04-18 14:22:32 +00:00
|
|
|
if (newEmojis.length) {
|
|
|
|
let newCategory = {
|
|
|
|
emojis: newEmojis,
|
|
|
|
name: category.name,
|
2018-01-09 20:20:18 +00:00
|
|
|
id: category.id,
|
2017-04-18 14:22:32 +00:00
|
|
|
}
|
2017-04-04 16:00:32 +00:00
|
|
|
|
2017-04-18 14:22:32 +00:00
|
|
|
this.categories.push(newCategory)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this.categories.push(category)
|
2017-01-30 21:01:41 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-04 16:00:32 +00:00
|
|
|
|
2017-10-07 04:02:02 +00:00
|
|
|
let includeRecent =
|
|
|
|
props.include && props.include.length
|
2018-03-02 18:25:39 +00:00
|
|
|
? props.include.indexOf(this.RECENT_CATEGORY.id) > -1
|
2017-10-07 04:02:02 +00:00
|
|
|
: true
|
|
|
|
let excludeRecent =
|
|
|
|
props.exclude && props.exclude.length
|
2018-03-02 18:25:39 +00:00
|
|
|
? props.exclude.indexOf(this.RECENT_CATEGORY.id) > -1
|
2017-10-07 04:02:02 +00:00
|
|
|
: false
|
2017-05-29 11:36:49 +00:00
|
|
|
if (includeRecent && !excludeRecent) {
|
|
|
|
this.hideRecent = false
|
2018-03-02 18:25:39 +00:00
|
|
|
this.categories.unshift(this.RECENT_CATEGORY)
|
2017-04-07 21:09:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.categories[0]) {
|
|
|
|
this.categories[0].first = true
|
|
|
|
}
|
2017-01-30 21:01:41 +00:00
|
|
|
|
2018-03-02 18:25:39 +00:00
|
|
|
this.categories.unshift(this.SEARCH_CATEGORY)
|
2017-09-29 14:46:29 +00:00
|
|
|
|
2017-10-07 04:02:02 +00:00
|
|
|
this.setAnchorsRef = this.setAnchorsRef.bind(this)
|
2017-09-29 14:46:29 +00:00
|
|
|
this.handleAnchorClick = this.handleAnchorClick.bind(this)
|
2017-10-07 04:02:02 +00:00
|
|
|
this.setSearchRef = this.setSearchRef.bind(this)
|
|
|
|
this.handleSearch = this.handleSearch.bind(this)
|
|
|
|
this.setScrollRef = this.setScrollRef.bind(this)
|
|
|
|
this.handleScroll = this.handleScroll.bind(this)
|
2017-09-29 14:46:29 +00:00
|
|
|
this.handleScrollPaint = this.handleScrollPaint.bind(this)
|
2017-10-07 04:02:02 +00:00
|
|
|
this.handleEmojiOver = this.handleEmojiOver.bind(this)
|
|
|
|
this.handleEmojiLeave = this.handleEmojiLeave.bind(this)
|
|
|
|
this.handleEmojiClick = this.handleEmojiClick.bind(this)
|
2018-03-15 19:36:07 +00:00
|
|
|
this.handleEmojiSelect = this.handleEmojiSelect.bind(this)
|
2017-10-07 04:02:02 +00:00
|
|
|
this.setPreviewRef = this.setPreviewRef.bind(this)
|
|
|
|
this.handleSkinChange = this.handleSkinChange.bind(this)
|
2018-03-15 19:36:07 +00:00
|
|
|
this.handleKeyDown = this.handleKeyDown.bind(this)
|
2016-05-31 18:39:30 +00:00
|
|
|
}
|
|
|
|
|
2019-12-21 16:43:36 +00:00
|
|
|
static getDerivedStateFromProps(props, state) {
|
2018-03-02 18:45:33 +00:00
|
|
|
if (props.skin) {
|
2019-12-21 16:43:36 +00:00
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
skin: props.skin,
|
|
|
|
}
|
2018-03-02 18:45:33 +00:00
|
|
|
} else if (props.defaultSkin && !store.get('skin')) {
|
2019-12-21 16:43:36 +00:00
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
skin: props.defaultSkin,
|
|
|
|
}
|
2016-07-06 17:35:09 +00:00
|
|
|
}
|
2019-12-21 16:43:36 +00:00
|
|
|
return state
|
2016-06-09 00:22:06 +00:00
|
|
|
}
|
|
|
|
|
2016-07-15 16:24:50 +00:00
|
|
|
componentDidMount() {
|
|
|
|
if (this.state.firstRender) {
|
2016-10-04 00:49:35 +00:00
|
|
|
this.testStickyPosition()
|
2016-07-15 16:31:22 +00:00
|
|
|
this.firstRenderTimeout = setTimeout(() => {
|
2016-07-15 16:24:50 +00:00
|
|
|
this.setState({ firstRender: false })
|
|
|
|
}, 60)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-31 18:39:30 +00:00
|
|
|
componentDidUpdate() {
|
2016-07-08 17:56:29 +00:00
|
|
|
this.updateCategoriesSize()
|
2016-05-31 18:39:30 +00:00
|
|
|
this.handleScroll()
|
|
|
|
}
|
|
|
|
|
2016-07-15 16:31:22 +00:00
|
|
|
componentWillUnmount() {
|
2018-03-02 18:25:39 +00:00
|
|
|
this.SEARCH_CATEGORY.emojis = null
|
2016-07-18 18:42:21 +00:00
|
|
|
|
2016-07-15 16:31:22 +00:00
|
|
|
clearTimeout(this.leaveTimeout)
|
|
|
|
clearTimeout(this.firstRenderTimeout)
|
|
|
|
}
|
|
|
|
|
2016-05-31 18:39:30 +00:00
|
|
|
testStickyPosition() {
|
2017-09-17 08:54:22 +00:00
|
|
|
const stickyTestElement = document.createElement('div')
|
|
|
|
|
|
|
|
const prefixes = ['', '-webkit-', '-ms-', '-moz-', '-o-']
|
|
|
|
|
2017-10-07 04:02:02 +00:00
|
|
|
prefixes.forEach(
|
2018-03-27 18:51:26 +00:00
|
|
|
(prefix) => (stickyTestElement.style.position = `${prefix}sticky`),
|
2017-10-07 04:02:02 +00:00
|
|
|
)
|
2016-05-31 16:35:08 +00:00
|
|
|
|
|
|
|
this.hasStickyPosition = !!stickyTestElement.style.position.length
|
|
|
|
}
|
|
|
|
|
2016-05-31 14:36:52 +00:00
|
|
|
handleEmojiOver(emoji) {
|
2017-09-27 19:26:50 +00:00
|
|
|
var { preview } = this
|
2017-10-07 04:02:02 +00:00
|
|
|
if (!preview) {
|
|
|
|
return
|
|
|
|
}
|
2017-09-28 02:02:30 +00:00
|
|
|
|
2017-06-23 09:32:26 +00:00
|
|
|
// Use Array.prototype.find() when it is more widely supported.
|
2019-06-27 20:18:16 +00:00
|
|
|
const emojiData = this.CUSTOM.filter(
|
2018-03-27 18:51:26 +00:00
|
|
|
(customEmoji) => customEmoji.id === emoji.id,
|
2017-10-07 04:02:02 +00:00
|
|
|
)[0]
|
2017-09-17 08:54:22 +00:00
|
|
|
for (let key in emojiData) {
|
|
|
|
if (emojiData.hasOwnProperty(key)) {
|
2017-10-07 04:02:02 +00:00
|
|
|
emoji[key] = emojiData[key]
|
2017-09-17 08:54:22 +00:00
|
|
|
}
|
|
|
|
}
|
2017-09-28 02:02:30 +00:00
|
|
|
|
2017-09-17 08:54:22 +00:00
|
|
|
preview.setState({ emoji })
|
2016-05-31 20:53:06 +00:00
|
|
|
clearTimeout(this.leaveTimeout)
|
|
|
|
}
|
|
|
|
|
|
|
|
handleEmojiLeave(emoji) {
|
2017-09-28 02:02:30 +00:00
|
|
|
var { preview } = this
|
2017-10-07 04:02:02 +00:00
|
|
|
if (!preview) {
|
|
|
|
return
|
|
|
|
}
|
2017-09-28 02:02:30 +00:00
|
|
|
|
2016-05-31 20:53:06 +00:00
|
|
|
this.leaveTimeout = setTimeout(() => {
|
|
|
|
preview.setState({ emoji: null })
|
|
|
|
}, 16)
|
2016-05-31 14:36:52 +00:00
|
|
|
}
|
|
|
|
|
2016-07-21 19:10:33 +00:00
|
|
|
handleEmojiClick(emoji, e) {
|
|
|
|
this.props.onClick(emoji, e)
|
2018-03-15 19:36:07 +00:00
|
|
|
this.handleEmojiSelect(emoji)
|
|
|
|
}
|
|
|
|
|
|
|
|
handleEmojiSelect(emoji) {
|
|
|
|
this.props.onSelect(emoji)
|
2017-10-07 14:26:09 +00:00
|
|
|
if (!this.hideRecent && !this.props.recent) frequently.add(emoji)
|
2016-07-07 18:22:02 +00:00
|
|
|
|
2017-09-27 19:26:50 +00:00
|
|
|
var component = this.categoryRefs['category-1']
|
2016-07-08 17:56:29 +00:00
|
|
|
if (component) {
|
2016-07-07 18:22:02 +00:00
|
|
|
let maxMargin = component.maxMargin
|
|
|
|
component.forceUpdate()
|
|
|
|
|
2019-12-29 23:24:18 +00:00
|
|
|
requestAnimationFrame(() => {
|
2017-09-29 23:14:24 +00:00
|
|
|
if (!this.scroll) return
|
2016-07-08 17:56:29 +00:00
|
|
|
component.memoizeSize()
|
2016-07-07 18:22:02 +00:00
|
|
|
if (maxMargin == component.maxMargin) return
|
|
|
|
|
2016-07-08 17:56:29 +00:00
|
|
|
this.updateCategoriesSize()
|
2016-07-07 18:22:02 +00:00
|
|
|
this.handleScrollPaint()
|
2016-10-14 01:38:24 +00:00
|
|
|
|
2018-03-02 18:25:39 +00:00
|
|
|
if (this.SEARCH_CATEGORY.emojis) {
|
2016-10-14 01:38:24 +00:00
|
|
|
component.updateDisplay('none')
|
|
|
|
}
|
2016-07-07 18:22:02 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-31 16:35:08 +00:00
|
|
|
handleScroll() {
|
2016-06-02 15:26:48 +00:00
|
|
|
if (!this.waitingForPaint) {
|
|
|
|
this.waitingForPaint = true
|
2019-12-29 23:24:18 +00:00
|
|
|
requestAnimationFrame(this.handleScrollPaint)
|
2016-06-02 15:26:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
handleScrollPaint() {
|
|
|
|
this.waitingForPaint = false
|
|
|
|
|
2017-09-27 19:26:50 +00:00
|
|
|
if (!this.scroll) {
|
2016-07-15 16:24:50 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:36:41 +00:00
|
|
|
let activeCategory = null
|
|
|
|
|
2018-03-02 18:25:39 +00:00
|
|
|
if (this.SEARCH_CATEGORY.emojis) {
|
|
|
|
activeCategory = this.SEARCH_CATEGORY
|
2017-05-27 17:36:41 +00:00
|
|
|
} else {
|
2017-09-27 19:26:50 +00:00
|
|
|
var target = this.scroll,
|
2017-10-07 04:02:02 +00:00
|
|
|
scrollTop = target.scrollTop,
|
|
|
|
scrollingDown = scrollTop > (this.scrollTop || 0),
|
|
|
|
minTop = 0
|
2017-05-27 17:36:41 +00:00
|
|
|
|
|
|
|
for (let i = 0, l = this.categories.length; i < l; i++) {
|
2017-10-07 04:02:02 +00:00
|
|
|
let ii = scrollingDown ? this.categories.length - 1 - i : i,
|
|
|
|
category = this.categories[ii],
|
|
|
|
component = this.categoryRefs[`category-${ii}`]
|
2017-05-27 17:36:41 +00:00
|
|
|
|
|
|
|
if (component) {
|
|
|
|
let active = component.handleScroll(scrollTop)
|
|
|
|
|
|
|
|
if (!minTop || component.top < minTop) {
|
|
|
|
if (component.top > 0) {
|
|
|
|
minTop = component.top
|
|
|
|
}
|
2016-07-15 16:24:50 +00:00
|
|
|
}
|
|
|
|
|
2017-05-27 17:36:41 +00:00
|
|
|
if (active && !activeCategory) {
|
|
|
|
activeCategory = category
|
|
|
|
}
|
2016-05-31 16:35:08 +00:00
|
|
|
}
|
2016-06-02 15:26:48 +00:00
|
|
|
}
|
|
|
|
|
2017-05-27 17:36:41 +00:00
|
|
|
if (scrollTop < minTop) {
|
2017-10-07 04:02:02 +00:00
|
|
|
activeCategory = this.categories.filter(
|
2018-03-27 18:51:26 +00:00
|
|
|
(category) => !(category.anchor === false),
|
2017-10-07 04:02:02 +00:00
|
|
|
)[0]
|
2017-05-27 17:36:41 +00:00
|
|
|
} else if (scrollTop + this.clientHeight >= this.scrollHeight) {
|
|
|
|
activeCategory = this.categories[this.categories.length - 1]
|
2017-04-07 21:09:30 +00:00
|
|
|
}
|
2016-07-08 21:03:41 +00:00
|
|
|
}
|
|
|
|
|
2016-06-02 15:26:48 +00:00
|
|
|
if (activeCategory) {
|
2017-09-27 19:26:50 +00:00
|
|
|
let { anchors } = this,
|
2017-10-07 04:02:02 +00:00
|
|
|
{ name: categoryName } = activeCategory
|
2016-06-02 15:26:48 +00:00
|
|
|
|
|
|
|
if (anchors.state.selected != categoryName) {
|
|
|
|
anchors.setState({ selected: categoryName })
|
|
|
|
}
|
2016-05-31 16:35:08 +00:00
|
|
|
}
|
2016-06-02 15:26:48 +00:00
|
|
|
|
|
|
|
this.scrollTop = scrollTop
|
2016-05-31 16:35:08 +00:00
|
|
|
}
|
|
|
|
|
2016-05-31 18:39:30 +00:00
|
|
|
handleSearch(emojis) {
|
2018-03-02 18:25:39 +00:00
|
|
|
this.SEARCH_CATEGORY.emojis = emojis
|
2016-07-08 17:56:29 +00:00
|
|
|
|
2017-04-07 21:09:30 +00:00
|
|
|
for (let i = 0, l = this.categories.length; i < l; i++) {
|
2017-09-27 19:26:50 +00:00
|
|
|
let component = this.categoryRefs[`category-${i}`]
|
2016-07-08 17:56:29 +00:00
|
|
|
|
|
|
|
if (component && component.props.name != 'Search') {
|
2017-02-15 22:28:25 +00:00
|
|
|
let display = emojis ? 'none' : 'inherit'
|
2016-07-08 21:03:41 +00:00
|
|
|
component.updateDisplay(display)
|
2016-07-08 17:56:29 +00:00
|
|
|
}
|
2016-05-31 18:39:30 +00:00
|
|
|
}
|
2016-07-08 17:56:29 +00:00
|
|
|
|
|
|
|
this.forceUpdate()
|
2019-03-23 16:25:51 +00:00
|
|
|
if (this.scroll) {
|
|
|
|
this.scroll.scrollTop = 0
|
|
|
|
}
|
2017-04-23 17:25:45 +00:00
|
|
|
this.handleScroll()
|
2016-05-31 18:39:30 +00:00
|
|
|
}
|
|
|
|
|
2016-06-02 18:58:19 +00:00
|
|
|
handleAnchorClick(category, i) {
|
2017-09-27 19:26:50 +00:00
|
|
|
var component = this.categoryRefs[`category-${i}`],
|
2017-10-07 04:02:02 +00:00
|
|
|
{ scroll, anchors } = this,
|
|
|
|
scrollToComponent = null
|
2016-06-02 18:58:19 +00:00
|
|
|
|
2016-07-08 20:28:43 +00:00
|
|
|
scrollToComponent = () => {
|
|
|
|
if (component) {
|
|
|
|
let { top } = component
|
|
|
|
|
2017-04-07 21:09:30 +00:00
|
|
|
if (category.first) {
|
2016-07-08 20:28:43 +00:00
|
|
|
top = 0
|
|
|
|
} else {
|
|
|
|
top += 1
|
|
|
|
}
|
2016-06-02 18:58:19 +00:00
|
|
|
|
2016-07-08 20:28:43 +00:00
|
|
|
scroll.scrollTop = top
|
2016-06-02 18:58:19 +00:00
|
|
|
}
|
2016-07-08 20:28:43 +00:00
|
|
|
}
|
|
|
|
|
2018-03-02 18:25:39 +00:00
|
|
|
if (this.SEARCH_CATEGORY.emojis) {
|
2016-07-08 20:28:43 +00:00
|
|
|
this.handleSearch(null)
|
2017-09-27 19:26:50 +00:00
|
|
|
this.search.clear()
|
2016-06-02 18:58:19 +00:00
|
|
|
|
2019-12-29 23:24:18 +00:00
|
|
|
requestAnimationFrame(scrollToComponent)
|
2016-07-08 20:28:43 +00:00
|
|
|
} else {
|
|
|
|
scrollToComponent()
|
2016-06-02 18:58:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-09 00:22:06 +00:00
|
|
|
handleSkinChange(skin) {
|
2018-03-02 18:33:14 +00:00
|
|
|
var newState = { skin: skin },
|
|
|
|
{ onSkinChange } = this.props
|
2016-07-06 17:35:09 +00:00
|
|
|
|
|
|
|
this.setState(newState)
|
|
|
|
store.update(newState)
|
2018-03-02 18:33:14 +00:00
|
|
|
|
|
|
|
onSkinChange(skin)
|
2016-06-09 00:22:06 +00:00
|
|
|
}
|
|
|
|
|
2018-03-15 19:36:07 +00:00
|
|
|
handleKeyDown(e) {
|
|
|
|
let handled = false
|
2018-03-27 18:43:02 +00:00
|
|
|
|
2018-03-15 19:36:07 +00:00
|
|
|
switch (e.keyCode) {
|
|
|
|
case 13:
|
2018-03-27 18:43:02 +00:00
|
|
|
let emoji
|
|
|
|
|
2018-03-27 18:51:26 +00:00
|
|
|
if (
|
|
|
|
this.SEARCH_CATEGORY.emojis &&
|
2019-03-10 17:47:28 +00:00
|
|
|
this.SEARCH_CATEGORY.emojis.length &&
|
2019-02-13 19:56:42 +00:00
|
|
|
(emoji = getSanitizedData(
|
|
|
|
this.SEARCH_CATEGORY.emojis[0],
|
|
|
|
this.state.skin,
|
|
|
|
this.props.set,
|
|
|
|
this.props.data,
|
|
|
|
))
|
2018-03-27 18:51:26 +00:00
|
|
|
) {
|
2018-03-27 18:43:02 +00:00
|
|
|
this.handleEmojiSelect(emoji)
|
2019-12-21 16:38:25 +00:00
|
|
|
handled = true
|
2018-03-15 19:36:07 +00:00
|
|
|
}
|
2018-03-27 18:43:02 +00:00
|
|
|
|
2018-03-27 18:51:26 +00:00
|
|
|
break
|
2018-03-15 19:36:07 +00:00
|
|
|
}
|
2018-03-27 18:43:02 +00:00
|
|
|
|
2018-03-15 19:36:07 +00:00
|
|
|
if (handled) {
|
|
|
|
e.preventDefault()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-08 17:56:29 +00:00
|
|
|
updateCategoriesSize() {
|
2017-04-07 21:09:30 +00:00
|
|
|
for (let i = 0, l = this.categories.length; i < l; i++) {
|
2017-09-27 19:26:50 +00:00
|
|
|
let component = this.categoryRefs[`category-${i}`]
|
2016-07-08 17:56:29 +00:00
|
|
|
if (component) component.memoizeSize()
|
|
|
|
}
|
2017-05-27 16:58:46 +00:00
|
|
|
|
2017-09-27 19:26:50 +00:00
|
|
|
if (this.scroll) {
|
|
|
|
let target = this.scroll
|
2017-05-27 16:58:46 +00:00
|
|
|
this.scrollHeight = target.scrollHeight
|
|
|
|
this.clientHeight = target.clientHeight
|
|
|
|
}
|
2016-07-08 17:56:29 +00:00
|
|
|
}
|
|
|
|
|
2016-07-15 16:24:50 +00:00
|
|
|
getCategories() {
|
2017-10-07 04:02:02 +00:00
|
|
|
return this.state.firstRender
|
|
|
|
? this.categories.slice(0, 3)
|
|
|
|
: this.categories
|
2016-07-15 16:24:50 +00:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:26:50 +00:00
|
|
|
setAnchorsRef(c) {
|
|
|
|
this.anchors = c
|
|
|
|
}
|
|
|
|
|
|
|
|
setSearchRef(c) {
|
|
|
|
this.search = c
|
|
|
|
}
|
|
|
|
|
|
|
|
setPreviewRef(c) {
|
|
|
|
this.preview = c
|
|
|
|
}
|
|
|
|
|
|
|
|
setScrollRef(c) {
|
|
|
|
this.scroll = c
|
|
|
|
}
|
|
|
|
|
|
|
|
setCategoryRef(name, c) {
|
|
|
|
if (!this.categoryRefs) {
|
|
|
|
this.categoryRefs = {}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.categoryRefs[name] = c
|
|
|
|
}
|
|
|
|
|
2016-05-31 14:36:52 +00:00
|
|
|
render() {
|
2017-10-07 04:02:02 +00:00
|
|
|
var {
|
|
|
|
perLine,
|
|
|
|
emojiSize,
|
|
|
|
set,
|
|
|
|
sheetSize,
|
2018-08-06 21:31:02 +00:00
|
|
|
sheetColumns,
|
|
|
|
sheetRows,
|
2017-10-07 04:02:02 +00:00
|
|
|
style,
|
|
|
|
title,
|
|
|
|
emoji,
|
|
|
|
color,
|
|
|
|
native,
|
|
|
|
backgroundImageFn,
|
|
|
|
emojisToShowFilter,
|
|
|
|
showPreview,
|
2018-03-02 20:08:52 +00:00
|
|
|
showSkinTones,
|
2017-10-07 04:02:02 +00:00
|
|
|
emojiTooltip,
|
|
|
|
include,
|
|
|
|
exclude,
|
2017-10-07 14:26:09 +00:00
|
|
|
recent,
|
2017-10-07 04:02:02 +00:00
|
|
|
autoFocus,
|
2018-08-10 18:11:28 +00:00
|
|
|
skinEmoji,
|
2018-06-21 15:56:40 +00:00
|
|
|
notFound,
|
2018-07-30 21:06:23 +00:00
|
|
|
notFoundEmoji,
|
2019-12-21 17:25:57 +00:00
|
|
|
darkMode,
|
2017-10-07 04:02:02 +00:00
|
|
|
} = this.props,
|
|
|
|
{ skin } = this.state,
|
|
|
|
width = perLine * (emojiSize + 12) + 12 + 2 + measureScrollbar()
|
|
|
|
|
|
|
|
return (
|
2019-03-12 16:36:28 +00:00
|
|
|
<section
|
2018-03-27 18:51:26 +00:00
|
|
|
style={{ width: width, ...style }}
|
2019-12-21 17:07:17 +00:00
|
|
|
className={`emoji-mart ${darkMode ? 'emoji-mart-dark' : ''}`}
|
2019-03-12 16:36:28 +00:00
|
|
|
aria-label={title}
|
2018-03-27 18:51:26 +00:00
|
|
|
onKeyDown={this.handleKeyDown}
|
|
|
|
>
|
2017-10-07 04:02:02 +00:00
|
|
|
<div className="emoji-mart-bar">
|
|
|
|
<Anchors
|
|
|
|
ref={this.setAnchorsRef}
|
2018-03-28 21:30:47 +00:00
|
|
|
data={this.data}
|
2016-10-27 03:22:59 +00:00
|
|
|
i18n={this.i18n}
|
2017-10-07 04:02:02 +00:00
|
|
|
color={color}
|
|
|
|
categories={this.categories}
|
|
|
|
onAnchorClick={this.handleAnchorClick}
|
2018-06-22 21:23:42 +00:00
|
|
|
icons={this.icons}
|
2016-05-31 14:36:52 +00:00
|
|
|
/>
|
2017-10-07 04:02:02 +00:00
|
|
|
</div>
|
2016-05-31 14:36:52 +00:00
|
|
|
|
2018-04-30 00:55:13 +00:00
|
|
|
<Search
|
2017-10-07 04:02:02 +00:00
|
|
|
ref={this.setSearchRef}
|
|
|
|
onSearch={this.handleSearch}
|
2018-03-28 21:30:47 +00:00
|
|
|
data={this.data}
|
2017-10-07 04:02:02 +00:00
|
|
|
i18n={this.i18n}
|
|
|
|
emojisToShowFilter={emojisToShowFilter}
|
|
|
|
include={include}
|
|
|
|
exclude={exclude}
|
2019-06-27 20:18:16 +00:00
|
|
|
custom={this.CUSTOM}
|
2017-10-07 04:02:02 +00:00
|
|
|
autoFocus={autoFocus}
|
2016-05-31 14:36:52 +00:00
|
|
|
/>
|
2017-10-07 04:02:02 +00:00
|
|
|
|
2019-03-12 16:36:28 +00:00
|
|
|
<div
|
2017-10-07 04:02:02 +00:00
|
|
|
ref={this.setScrollRef}
|
|
|
|
className="emoji-mart-scroll"
|
|
|
|
onScroll={this.handleScroll}
|
|
|
|
>
|
|
|
|
{this.getCategories().map((category, i) => {
|
|
|
|
return (
|
2018-04-30 00:55:13 +00:00
|
|
|
<Category
|
2017-10-07 04:02:02 +00:00
|
|
|
ref={this.setCategoryRef.bind(this, `category-${i}`)}
|
|
|
|
key={category.name}
|
2017-12-08 17:45:31 +00:00
|
|
|
id={category.id}
|
2017-10-07 04:02:02 +00:00
|
|
|
name={category.name}
|
|
|
|
emojis={category.emojis}
|
|
|
|
perLine={perLine}
|
|
|
|
native={native}
|
|
|
|
hasStickyPosition={this.hasStickyPosition}
|
2018-03-28 21:30:47 +00:00
|
|
|
data={this.data}
|
2017-10-07 04:02:02 +00:00
|
|
|
i18n={this.i18n}
|
2018-03-02 20:10:04 +00:00
|
|
|
recent={
|
|
|
|
category.id == this.RECENT_CATEGORY.id ? recent : undefined
|
|
|
|
}
|
2017-10-07 04:02:02 +00:00
|
|
|
custom={
|
2018-03-02 18:25:39 +00:00
|
|
|
category.id == this.RECENT_CATEGORY.id
|
2019-06-27 20:18:16 +00:00
|
|
|
? this.CUSTOM
|
2017-12-15 20:31:49 +00:00
|
|
|
: undefined
|
2017-10-07 04:02:02 +00:00
|
|
|
}
|
|
|
|
emojiProps={{
|
|
|
|
native: native,
|
|
|
|
skin: skin,
|
|
|
|
size: emojiSize,
|
|
|
|
set: set,
|
|
|
|
sheetSize: sheetSize,
|
2018-08-06 21:31:02 +00:00
|
|
|
sheetColumns: sheetColumns,
|
|
|
|
sheetRows: sheetRows,
|
2017-10-07 04:02:02 +00:00
|
|
|
forceSize: native,
|
|
|
|
tooltip: emojiTooltip,
|
|
|
|
backgroundImageFn: backgroundImageFn,
|
|
|
|
onOver: this.handleEmojiOver,
|
|
|
|
onLeave: this.handleEmojiLeave,
|
|
|
|
onClick: this.handleEmojiClick,
|
|
|
|
}}
|
2018-06-21 15:56:40 +00:00
|
|
|
notFound={notFound}
|
2018-07-30 21:06:23 +00:00
|
|
|
notFoundEmoji={notFoundEmoji}
|
2017-10-07 04:02:02 +00:00
|
|
|
/>
|
|
|
|
)
|
|
|
|
})}
|
2019-03-12 16:36:28 +00:00
|
|
|
</div>
|
2017-10-07 04:02:02 +00:00
|
|
|
|
2019-03-08 05:00:50 +00:00
|
|
|
{(showPreview || showSkinTones) && (
|
2017-10-07 04:02:02 +00:00
|
|
|
<div className="emoji-mart-bar">
|
2018-04-30 00:55:13 +00:00
|
|
|
<Preview
|
2017-10-07 04:02:02 +00:00
|
|
|
ref={this.setPreviewRef}
|
2018-03-28 21:30:47 +00:00
|
|
|
data={this.data}
|
2017-10-07 04:02:02 +00:00
|
|
|
title={title}
|
|
|
|
emoji={emoji}
|
2018-03-02 20:08:52 +00:00
|
|
|
showSkinTones={showSkinTones}
|
2019-03-08 05:00:50 +00:00
|
|
|
showPreview={showPreview}
|
2017-10-07 04:02:02 +00:00
|
|
|
emojiProps={{
|
|
|
|
native: native,
|
|
|
|
size: 38,
|
|
|
|
skin: skin,
|
|
|
|
set: set,
|
|
|
|
sheetSize: sheetSize,
|
2018-08-15 05:29:20 +00:00
|
|
|
sheetColumns: sheetColumns,
|
|
|
|
sheetRows: sheetRows,
|
2017-10-07 04:02:02 +00:00
|
|
|
backgroundImageFn: backgroundImageFn,
|
|
|
|
}}
|
|
|
|
skinsProps={{
|
|
|
|
skin: skin,
|
|
|
|
onChange: this.handleSkinChange,
|
2018-08-10 18:11:28 +00:00
|
|
|
skinEmoji: skinEmoji,
|
2017-10-07 04:02:02 +00:00
|
|
|
}}
|
2018-07-05 21:00:57 +00:00
|
|
|
i18n={this.i18n}
|
2017-10-07 04:02:02 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
)}
|
2019-03-12 16:36:28 +00:00
|
|
|
</section>
|
2017-10-07 04:02:02 +00:00
|
|
|
)
|
2016-05-31 14:36:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-18 19:24:52 +00:00
|
|
|
NimblePicker.propTypes /* remove-proptypes */ = {
|
2018-04-26 14:36:54 +00:00
|
|
|
...PickerPropTypes,
|
|
|
|
data: PropTypes.object.isRequired,
|
|
|
|
}
|
2018-03-28 21:30:47 +00:00
|
|
|
NimblePicker.defaultProps = { ...PickerDefaultProps }
|