improved EmojiBoard
This commit is contained in:
parent
4b5553abef
commit
769fd7b524
3 changed files with 87 additions and 28 deletions
|
@ -30,14 +30,14 @@ const viewEvent = new EventEmitter();
|
||||||
|
|
||||||
function EmojiGroup({ name, emojis }) {
|
function EmojiGroup({ name, emojis }) {
|
||||||
function getEmojiBoard() {
|
function getEmojiBoard() {
|
||||||
|
const emojiBoard = [];
|
||||||
const ROW_EMOJIS_COUNT = 7;
|
const ROW_EMOJIS_COUNT = 7;
|
||||||
const emojiRows = [];
|
|
||||||
const totalEmojis = emojis.length;
|
const totalEmojis = emojis.length;
|
||||||
|
|
||||||
for (let r = 0; r < totalEmojis; r += ROW_EMOJIS_COUNT) {
|
for (let r = 0; r < totalEmojis; r += ROW_EMOJIS_COUNT) {
|
||||||
const emojiRow = [];
|
const emojiRow = [];
|
||||||
for (let c = r; c < r + ROW_EMOJIS_COUNT; c += 1) {
|
for (let c = r; c < r + ROW_EMOJIS_COUNT; c += 1) {
|
||||||
const emojiIndex = r + c;
|
const emojiIndex = c;
|
||||||
if (emojiIndex >= totalEmojis) break;
|
if (emojiIndex >= totalEmojis) break;
|
||||||
const emoji = emojis[emojiIndex];
|
const emoji = emojis[emojiIndex];
|
||||||
emojiRow.push(
|
emojiRow.push(
|
||||||
|
@ -49,6 +49,7 @@ function EmojiGroup({ name, emojis }) {
|
||||||
attributes: () => ({
|
attributes: () => ({
|
||||||
unicode: emoji.unicode,
|
unicode: emoji.unicode,
|
||||||
shortcodes: emoji.shortcodes?.toString(),
|
shortcodes: emoji.shortcodes?.toString(),
|
||||||
|
hexcode: emoji.hexcode,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
@ -56,9 +57,9 @@ function EmojiGroup({ name, emojis }) {
|
||||||
</span>,
|
</span>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
emojiRows.push(<div key={r} className="emoji-row">{emojiRow}</div>);
|
emojiBoard.push(<div key={r} className="emoji-row">{emojiRow}</div>);
|
||||||
}
|
}
|
||||||
return emojiRows;
|
return emojiBoard;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -73,6 +74,7 @@ EmojiGroup.propTypes = {
|
||||||
emojis: PropTypes.arrayOf(PropTypes.shape({
|
emojis: PropTypes.arrayOf(PropTypes.shape({
|
||||||
length: PropTypes.number,
|
length: PropTypes.number,
|
||||||
unicode: PropTypes.string,
|
unicode: PropTypes.string,
|
||||||
|
hexcode: PropTypes.string,
|
||||||
shortcodes: PropTypes.oneOfType([
|
shortcodes: PropTypes.oneOfType([
|
||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
PropTypes.arrayOf(PropTypes.string),
|
PropTypes.arrayOf(PropTypes.string),
|
||||||
|
@ -104,16 +106,18 @@ function SearchedEmoji() {
|
||||||
function EmojiBoard({ onSelect }) {
|
function EmojiBoard({ onSelect }) {
|
||||||
const searchRef = useRef(null);
|
const searchRef = useRef(null);
|
||||||
const scrollEmojisRef = useRef(null);
|
const scrollEmojisRef = useRef(null);
|
||||||
|
const emojiInfo = useRef(null);
|
||||||
|
|
||||||
function isTargetNotEmoji(target) {
|
function isTargetNotEmoji(target) {
|
||||||
return target.classList.contains('emoji') === false;
|
return target.classList.contains('emoji') === false;
|
||||||
}
|
}
|
||||||
function getEmojiDataFromTarget(target) {
|
function getEmojiDataFromTarget(target) {
|
||||||
const unicode = target.getAttribute('unicode');
|
const unicode = target.getAttribute('unicode');
|
||||||
|
const hexcode = target.getAttribute('hexcode');
|
||||||
let shortcodes = target.getAttribute('shortcodes');
|
let shortcodes = target.getAttribute('shortcodes');
|
||||||
if (typeof shortcodes === 'undefined') shortcodes = undefined;
|
if (typeof shortcodes === 'undefined') shortcodes = undefined;
|
||||||
else shortcodes = shortcodes.split(',');
|
else shortcodes = shortcodes.split(',');
|
||||||
return { unicode, shortcodes };
|
return { unicode, hexcode, shortcodes };
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectEmoji(e) {
|
function selectEmoji(e) {
|
||||||
|
@ -123,18 +127,29 @@ function EmojiBoard({ onSelect }) {
|
||||||
onSelect(getEmojiDataFromTarget(emoji));
|
onSelect(getEmojiDataFromTarget(emoji));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setEmojiInfo(emoji) {
|
||||||
|
const infoEmoji = emojiInfo.current.firstElementChild.firstElementChild;
|
||||||
|
const infoShortcode = emojiInfo.current.lastElementChild;
|
||||||
|
|
||||||
|
const emojiSrc = infoEmoji.src;
|
||||||
|
infoEmoji.src = `${emojiSrc.slice(0, emojiSrc.lastIndexOf('/') + 1)}${emoji.hexcode.toLowerCase()}.png`;
|
||||||
|
infoShortcode.textContent = `:${emoji.shortcode}:`;
|
||||||
|
}
|
||||||
|
|
||||||
function hoverEmoji(e) {
|
function hoverEmoji(e) {
|
||||||
if (isTargetNotEmoji(e.target)) return;
|
if (isTargetNotEmoji(e.target)) return;
|
||||||
|
|
||||||
const emoji = e.target;
|
const emoji = e.target;
|
||||||
const { shortcodes } = getEmojiDataFromTarget(emoji);
|
const { shortcodes, hexcode } = getEmojiDataFromTarget(emoji);
|
||||||
|
|
||||||
if (typeof shortcodes === 'undefined') {
|
if (typeof shortcodes === 'undefined') {
|
||||||
searchRef.current.placeholder = 'Search';
|
searchRef.current.placeholder = 'Search';
|
||||||
|
setEmojiInfo({ hexcode: '1f643', shortcode: 'slight_smile' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (searchRef.current.placeholder === shortcodes[0]) return;
|
if (searchRef.current.placeholder === shortcodes[0]) return;
|
||||||
searchRef.current.setAttribute('placeholder', `:${shortcodes[0]}:`);
|
searchRef.current.setAttribute('placeholder', `:${shortcodes[0]}:`);
|
||||||
|
setEmojiInfo({ hexcode, shortcode: shortcodes[0] });
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSearchChange(e) {
|
function handleSearchChange(e) {
|
||||||
|
@ -157,7 +172,11 @@ function EmojiBoard({ onSelect }) {
|
||||||
return (
|
return (
|
||||||
<div id="emoji-board" className="emoji-board">
|
<div id="emoji-board" className="emoji-board">
|
||||||
<div className="emoji-board__content">
|
<div className="emoji-board__content">
|
||||||
<div className="emoji-board__emojis">
|
<div className="emoji-board__content__search">
|
||||||
|
<RawIcon size="small" src={SearchIC} />
|
||||||
|
<Input onChange={handleSearchChange} forwardRef={searchRef} placeholder="Search" />
|
||||||
|
</div>
|
||||||
|
<div className="emoji-board__content__emojis">
|
||||||
<ScrollView ref={scrollEmojisRef} autoHide>
|
<ScrollView ref={scrollEmojisRef} autoHide>
|
||||||
<div onMouseMove={hoverEmoji} onClick={selectEmoji}>
|
<div onMouseMove={hoverEmoji} onClick={selectEmoji}>
|
||||||
<SearchedEmoji />
|
<SearchedEmoji />
|
||||||
|
@ -169,9 +188,9 @@ function EmojiBoard({ onSelect }) {
|
||||||
</div>
|
</div>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</div>
|
</div>
|
||||||
<div className="emoji-board__search">
|
<div ref={emojiInfo} className="emoji-board__content__info">
|
||||||
<RawIcon size="small" src={SearchIC} />
|
<div>{ parse(twemoji.parse('🙂')) }</div>
|
||||||
<Input onChange={handleSearchChange} forwardRef={searchRef} placeholder="Search" />
|
<Text>:slight_smile:</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="emoji-board__nav">
|
<div className="emoji-board__nav">
|
||||||
|
|
|
@ -10,14 +10,15 @@
|
||||||
|
|
||||||
.emoji-board {
|
.emoji-board {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
@extend .emoji-board-flexItem;
|
@extend .emoji-board-flexItem;
|
||||||
@extend .emoji-board-flexBoxV;
|
@extend .emoji-board-flexBoxV;
|
||||||
height: 360px;
|
height: 400px;
|
||||||
|
width: 286px;
|
||||||
}
|
}
|
||||||
&__nav {
|
&__nav {
|
||||||
@extend .emoji-board-flexBoxV;
|
@extend .emoji-board-flexBoxV;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
padding: 4px 6px;
|
padding: 4px 6px;
|
||||||
background-color: var(--bg-surface-low);
|
background-color: var(--bg-surface-low);
|
||||||
|
@ -29,30 +30,62 @@
|
||||||
|
|
||||||
& > .ic-btn-surface {
|
& > .ic-btn-surface {
|
||||||
margin: calc(var(--sp-ultra-tight) / 2) 0;
|
margin: calc(var(--sp-ultra-tight) / 2) 0;
|
||||||
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.emoji-board__content__search {
|
||||||
.emoji-board__emojis {
|
padding: var(--sp-extra-tight);
|
||||||
@extend .emoji-board-flexItem;
|
position: relative;
|
||||||
}
|
|
||||||
.emoji-board__search {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: calc(var(--sp-ultra-tight) / 2) var(--sp-normal);
|
|
||||||
|
|
||||||
|
& .ic-raw {
|
||||||
|
position: absolute;
|
||||||
|
left: var(--sp-normal);
|
||||||
|
top: var(--sp-normal);
|
||||||
|
transform: translateY(1px);
|
||||||
|
[dir=rtl] & {
|
||||||
|
left: unset;
|
||||||
|
right: var(--sp-normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
& .input-container {
|
& .input-container {
|
||||||
@extend .emoji-board-flexItem;
|
|
||||||
& .input {
|
& .input {
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
width: 0;
|
width: 0;
|
||||||
background-color: transparent;
|
padding: var(--sp-extra-tight) 36px;
|
||||||
border: none !important;
|
border-radius: calc(var(--bo-radius) / 2);
|
||||||
box-shadow: none !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.emoji-board__content__emojis {
|
||||||
|
@extend .emoji-board-flexItem;
|
||||||
|
@extend .emoji-board-flexBoxV;
|
||||||
|
}
|
||||||
|
.emoji-board__content__info {
|
||||||
|
margin: 0 var(--sp-extra-tight);
|
||||||
|
padding: var(--sp-tight) var(--sp-extra-tight);
|
||||||
|
border-top: 1px solid var(--bg-surface-border);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
& > div:first-child {
|
||||||
|
line-height: 0;
|
||||||
|
.emoji {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > p:last-child {
|
||||||
|
@extend .emoji-board-flexItem;
|
||||||
|
margin: 0 var(--sp-tight);
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.emoji-group {
|
.emoji-group {
|
||||||
--emoji-padding: 6px;
|
--emoji-padding: 6px;
|
||||||
|
@ -65,12 +98,19 @@
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
background-color: var(--bg-surface);
|
background-color: var(--bg-surface);
|
||||||
|
|
||||||
padding: var(--sp-tight) var(--sp-normal);
|
margin-left: var(--sp-extra-tight);
|
||||||
|
padding: var(--sp-extra-tight) var(--sp-ultra-tight);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
box-shadow: 0 -4px 0 0 var(--bg-surface);
|
||||||
|
border-bottom: 1px solid var(--bg-surface-border);
|
||||||
|
[dir=rtl] & {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: var(--sp-extra-tight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
& .emoji-set {
|
& .emoji-set {
|
||||||
margin: 0 calc(var(--sp-normal) - var(--emoji-padding));
|
margin: var(--sp-extra-tight) calc(var(--sp-normal) - var(--emoji-padding));
|
||||||
margin-right: calc(var(--sp-extra-tight) - var(--emoji-padding));
|
margin-right: calc(var(--sp-extra-tight) - var(--emoji-padding));
|
||||||
[dir=rtl] & {
|
[dir=rtl] & {
|
||||||
margin-right: calc(var(--sp-normal) - var(--emoji-padding));
|
margin-right: calc(var(--sp-normal) - var(--emoji-padding));
|
||||||
|
@ -79,6 +119,7 @@
|
||||||
}
|
}
|
||||||
& .emoji {
|
& .emoji {
|
||||||
width: 38px;
|
width: 38px;
|
||||||
|
height: 38px;
|
||||||
padding: var(--emoji-padding);
|
padding: var(--emoji-padding);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
@ -47,7 +47,7 @@ function addToGroup(emoji) {
|
||||||
else if (emoji.group === 6) addEmoji(emoji, 3);
|
else if (emoji.group === 6) addEmoji(emoji, 3);
|
||||||
else if (emoji.group === 5) addEmoji(emoji, 4);
|
else if (emoji.group === 5) addEmoji(emoji, 4);
|
||||||
else if (emoji.group === 7) addEmoji(emoji, 5);
|
else if (emoji.group === 7) addEmoji(emoji, 5);
|
||||||
else if (emoji.group === 8) addEmoji(emoji, 6);
|
else if (emoji.group === 8 || typeof emoji.group === 'undefined') addEmoji(emoji, 6);
|
||||||
else if (emoji.group === 9) addEmoji(emoji, 7);
|
else if (emoji.group === 9) addEmoji(emoji, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,6 @@ function searchEmoji(term) {
|
||||||
if (result.length > 20) result = result.slice(0, 20);
|
if (result.length > 20) result = result.slice(0, 20);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
emojis, emojiGroups, searchEmoji,
|
emojis, emojiGroups, searchEmoji,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue