emoji-mart-lazyload/src/components/category.js

240 lines
5.2 KiB
JavaScript
Raw Normal View History

2016-05-31 14:36:52 +00:00
import React from 'react'
import PropTypes from 'prop-types'
2016-07-07 18:22:02 +00:00
2018-04-30 00:55:13 +00:00
import frequently from '../utils/frequently'
import { getData } from '../utils'
2018-11-13 10:21:37 +00:00
import NimbleEmoji from './emoji/nimble-emoji'
import NotFound from './not-found'
2018-04-26 15:47:30 +00:00
2018-04-30 00:55:13 +00:00
export default class Category extends React.Component {
constructor(props) {
super(props)
this.data = props.data
this.setContainerRef = this.setContainerRef.bind(this)
this.setLabelRef = this.setLabelRef.bind(this)
}
2016-05-31 16:35:08 +00:00
componentDidMount() {
this.margin = 0
this.minMargin = 0
this.memoizeSize()
}
2016-05-31 14:36:52 +00:00
2016-07-08 17:56:29 +00:00
shouldComponentUpdate(nextProps, nextState) {
2017-10-07 04:02:02 +00:00
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
2016-07-08 17:56:29 +00:00
if (name == 'Recent' && perLine != nextPerLine) {
shouldUpdate = true
}
if (name == 'Search') {
shouldUpdate = !(emojis == nextEmojis)
}
2017-10-07 04:02:02 +00:00
if (
skin != nextSkin ||
size != nextSize ||
native != nextNative ||
set != nextSet ||
hasStickyPosition != nextHasStickyPosition
) {
2016-07-08 17:56:29 +00:00
shouldUpdate = true
}
return shouldUpdate
2016-05-31 16:35:08 +00:00
}
memoizeSize() {
2019-03-14 01:31:13 +00:00
if (!this.container) {
// probably this is a test environment, e.g. jest
this.top = 0
this.maxMargin = 0
return
}
var parent = this.container.parentElement
2016-05-31 16:35:08 +00:00
var { top, height } = this.container.getBoundingClientRect()
var { top: parentTop } = parent.getBoundingClientRect()
2016-05-31 16:35:08 +00:00
var { height: labelHeight } = this.label.getBoundingClientRect()
this.top = top - parentTop + parent.scrollTop
if (height == 0) {
this.maxMargin = 0
2016-06-02 15:26:48 +00:00
} else {
this.maxMargin = height - labelHeight
2016-06-02 15:26:48 +00:00
}
2016-05-31 16:35:08 +00:00
}
handleScroll(scrollTop) {
var margin = scrollTop - this.top
margin = margin < this.minMargin ? this.minMargin : margin
margin = margin > this.maxMargin ? this.maxMargin : margin
if (margin == this.margin) return
2016-06-02 15:26:48 +00:00
if (!this.props.hasStickyPosition) {
this.label.style.top = `${margin}px`
}
2016-05-31 16:35:08 +00:00
this.margin = margin
2016-06-02 15:26:48 +00:00
return true
2016-05-31 14:36:52 +00:00
}
getEmojis() {
var { name, emojis, recent, perLine } = this.props
2016-05-31 14:36:52 +00:00
2016-07-07 18:22:02 +00:00
if (name == 'Recent') {
let { custom } = this.props
let frequentlyUsed = recent || frequently.get(perLine)
2016-05-31 16:35:08 +00:00
2016-07-07 18:22:02 +00:00
if (frequentlyUsed.length) {
2017-11-08 03:09:40 +00:00
emojis = frequentlyUsed
2018-03-27 18:51:26 +00:00
.map((id) => {
const emoji = custom.filter((e) => e.id === id)[0]
2017-11-08 03:09:40 +00:00
if (emoji) {
return emoji
}
return id
})
.filter((id) => !!getData(id, null, null, this.data))
}
if (emojis.length === 0 && frequentlyUsed.length > 0) {
2017-11-08 03:09:40 +00:00
return null
2016-05-31 16:35:08 +00:00
}
}
2016-07-07 18:22:02 +00:00
if (emojis) {
emojis = emojis.slice(0)
}
return emojis
}
updateDisplay(display) {
var emojis = this.getEmojis()
if (!emojis) {
return
}
this.container.style.display = display
}
setContainerRef(c) {
this.container = c
}
setLabelRef(c) {
this.label = c
}
render() {
var {
id,
name,
hasStickyPosition,
emojiProps,
i18n,
notFound,
2018-07-30 21:06:23 +00:00
notFoundEmoji,
} = this.props,
2017-10-07 04:02:02 +00:00
emojis = this.getEmojis(),
labelStyles = {},
labelSpanStyles = {},
containerStyles = {}
if (!emojis) {
2016-06-02 15:26:48 +00:00
containerStyles = {
display: 'none',
2016-06-02 15:26:48 +00:00
}
}
2016-07-07 18:22:02 +00:00
if (!hasStickyPosition) {
labelStyles = {
height: 28,
}
labelSpanStyles = {
position: 'absolute',
}
}
2017-10-07 04:02:02 +00:00
return (
<section
2017-10-07 04:02:02 +00:00
ref={this.setContainerRef}
className="emoji-mart-category"
aria-label={i18n.categories[id]}
2017-10-07 04:02:02 +00:00
style={containerStyles}
>
<div
style={labelStyles}
data-name={name}
className="emoji-mart-category-label"
>
<span
style={labelSpanStyles}
ref={this.setLabelRef}
aria-hidden={true /* already labeled by the section aria-label */}
>
{i18n.categories[id]}
2017-10-07 04:02:02 +00:00
</span>
</div>
2017-10-07 04:02:02 +00:00
2018-03-27 18:51:26 +00:00
{emojis &&
2018-04-26 14:36:54 +00:00
emojis.map((emoji) =>
NimbleEmoji({ emoji: emoji, data: this.data, ...emojiProps }),
)}
2017-10-07 04:02:02 +00:00
{emojis &&
!emojis.length && (
<NotFound
i18n={i18n}
notFound={notFound}
2018-07-30 21:06:23 +00:00
notFoundEmoji={notFoundEmoji}
data={this.data}
emojiProps={emojiProps}
/>
2017-10-07 04:02:02 +00:00
)}
</section>
2017-10-07 04:02:02 +00:00
)
2016-05-31 14:36:52 +00:00
}
}
Category.propTypes /* remove-proptypes */ = {
2018-04-30 00:55:13 +00:00
emojis: PropTypes.array,
hasStickyPosition: PropTypes.bool,
name: PropTypes.string.isRequired,
native: PropTypes.bool.isRequired,
perLine: PropTypes.number.isRequired,
emojiProps: PropTypes.object.isRequired,
recent: PropTypes.arrayOf(PropTypes.string),
notFound: PropTypes.func,
2018-07-30 21:06:23 +00:00
notFoundEmoji: PropTypes.string.isRequired,
2018-04-30 00:55:13 +00:00
}
Category.defaultProps = {
emojis: [],
hasStickyPosition: true,
2018-04-26 14:36:54 +00:00
}