emoji-mart
Version:
Customizable Slack-like emoji picker for React
277 lines (240 loc) • 8.89 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
import _inherits from "@babel/runtime/helpers/inherits";
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
import React from 'react';
import PropTypes from 'prop-types';
import frequently from '../utils/frequently';
import { getData } from '../utils';
import NimbleEmoji from './emoji/nimble-emoji';
import NotFound from './not-found';
var Category =
/*#__PURE__*/
function (_React$Component) {
_inherits(Category, _React$Component);
function Category(props) {
var _this;
_classCallCheck(this, Category);
_this = _possibleConstructorReturn(this, _getPrototypeOf(Category).call(this, props));
_this.data = props.data;
_this.setContainerRef = _this.setContainerRef.bind(_assertThisInitialized(_this));
_this.setLabelRef = _this.setLabelRef.bind(_assertThisInitialized(_this));
return _this;
}
_createClass(Category, [{
key: "componentDidMount",
value: function componentDidMount() {
this.margin = 0;
this.minMargin = 0;
this.memoizeSize();
}
}, {
key: "shouldComponentUpdate",
value: function shouldComponentUpdate(nextProps, nextState) {
var _this$props = this.props,
name = _this$props.name,
perLine = _this$props.perLine,
_native = _this$props["native"],
hasStickyPosition = _this$props.hasStickyPosition,
emojis = _this$props.emojis,
emojiProps = _this$props.emojiProps,
skin = emojiProps.skin,
size = emojiProps.size,
set = emojiProps.set,
nextPerLine = nextProps.perLine,
nextNative = nextProps["native"],
nextHasStickyPosition = nextProps.hasStickyPosition,
nextEmojis = nextProps.emojis,
nextEmojiProps = nextProps.emojiProps,
nextSkin = nextEmojiProps.skin,
nextSize = nextEmojiProps.size,
nextSet = nextEmojiProps.set,
shouldUpdate = false;
if (name == 'Recent' && perLine != nextPerLine) {
shouldUpdate = true;
}
if (name == 'Search') {
shouldUpdate = !(emojis == nextEmojis);
}
if (skin != nextSkin || size != nextSize || _native != nextNative || set != nextSet || hasStickyPosition != nextHasStickyPosition) {
shouldUpdate = true;
}
return shouldUpdate;
}
}, {
key: "memoizeSize",
value: function memoizeSize() {
if (!this.container) {
// probably this is a test environment, e.g. jest
this.top = 0;
this.maxMargin = 0;
return;
}
var parent = this.container.parentElement;
var _this$container$getBo = this.container.getBoundingClientRect(),
top = _this$container$getBo.top,
height = _this$container$getBo.height;
var _parent$getBoundingCl = parent.getBoundingClientRect(),
parentTop = _parent$getBoundingCl.top;
var _this$label$getBoundi = this.label.getBoundingClientRect(),
labelHeight = _this$label$getBoundi.height;
this.top = top - parentTop + parent.scrollTop;
if (height == 0) {
this.maxMargin = 0;
} else {
this.maxMargin = height - labelHeight;
}
}
}, {
key: "handleScroll",
value: function 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;
if (!this.props.hasStickyPosition) {
this.label.style.top = "".concat(margin, "px");
}
this.margin = margin;
return true;
}
}, {
key: "getEmojis",
value: function getEmojis() {
var _this2 = this;
var _this$props2 = this.props,
name = _this$props2.name,
emojis = _this$props2.emojis,
recent = _this$props2.recent,
perLine = _this$props2.perLine;
if (name == 'Recent') {
var custom = this.props.custom;
var frequentlyUsed = recent || frequently.get(perLine);
if (frequentlyUsed.length) {
emojis = frequentlyUsed.map(function (id) {
var emoji = custom.filter(function (e) {
return e.id === id;
})[0];
if (emoji) {
return emoji;
}
return id;
}).filter(function (id) {
return !!getData(id, null, null, _this2.data);
});
}
if (emojis.length === 0 && frequentlyUsed.length > 0) {
return null;
}
}
if (emojis) {
emojis = emojis.slice(0);
}
return emojis;
}
}, {
key: "updateDisplay",
value: function updateDisplay(display) {
var emojis = this.getEmojis();
if (!emojis || !this.container) {
return;
}
this.container.style.display = display;
}
}, {
key: "setContainerRef",
value: function setContainerRef(c) {
this.container = c;
}
}, {
key: "setLabelRef",
value: function setLabelRef(c) {
this.label = c;
}
}, {
key: "render",
value: function render() {
var _this3 = this;
var _this$props3 = this.props,
id = _this$props3.id,
name = _this$props3.name,
hasStickyPosition = _this$props3.hasStickyPosition,
emojiProps = _this$props3.emojiProps,
i18n = _this$props3.i18n,
notFound = _this$props3.notFound,
notFoundEmoji = _this$props3.notFoundEmoji,
emojis = this.getEmojis(),
labelStyles = {},
labelSpanStyles = {},
containerStyles = {};
if (!emojis) {
containerStyles = {
display: 'none'
};
}
if (!hasStickyPosition) {
labelStyles = {
height: 28
};
labelSpanStyles = {
position: 'absolute'
};
}
var label = i18n.categories[id] || name;
return React.createElement("section", {
ref: this.setContainerRef,
className: "emoji-mart-category",
"aria-label": label,
style: containerStyles
}, React.createElement("div", {
style: labelStyles,
"data-name": name,
className: "emoji-mart-category-label"
}, React.createElement("span", {
style: labelSpanStyles,
ref: this.setLabelRef,
"aria-hidden": true
/* already labeled by the section aria-label */
}, label)), React.createElement("ul", {
className: "emoji-mart-category-list"
}, emojis && emojis.map(function (emoji) {
return React.createElement("li", {
key: emoji.short_names && emoji.short_names.join('_') || emoji
}, NimbleEmoji(_objectSpread({
emoji: emoji,
data: _this3.data
}, emojiProps)));
})), emojis && !emojis.length && React.createElement(NotFound, {
i18n: i18n,
notFound: notFound,
notFoundEmoji: notFoundEmoji,
data: this.data,
emojiProps: emojiProps
}));
}
}]);
return Category;
}(React.Component);
export { Category as default };
Category.propTypes
/* remove-proptypes */
= {
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,
notFoundEmoji: PropTypes.string.isRequired
};
Category.defaultProps = {
emojis: [],
hasStickyPosition: true
};