2022-04-04 14:04:01 +00:00
|
|
|
import * as React from 'react';
|
2022-04-04 23:56:21 +00:00
|
|
|
import {useRef, useState} from 'react';
|
2022-04-04 14:04:01 +00:00
|
|
|
import Popover from '@mui/material/Popover';
|
|
|
|
import Typography from '@mui/material/Typography';
|
|
|
|
import {rawEmojis} from '../app/emojis';
|
|
|
|
import Box from "@mui/material/Box";
|
2022-04-04 23:56:21 +00:00
|
|
|
import TextField from "@mui/material/TextField";
|
|
|
|
import {InputAdornment} from "@mui/material";
|
|
|
|
import IconButton from "@mui/material/IconButton";
|
|
|
|
import {Close} from "@mui/icons-material";
|
2022-04-04 14:04:01 +00:00
|
|
|
|
|
|
|
const emojisByCategory = {};
|
|
|
|
rawEmojis.forEach(emoji => {
|
|
|
|
if (!emojisByCategory[emoji.category]) {
|
|
|
|
emojisByCategory[emoji.category] = [];
|
|
|
|
}
|
|
|
|
emojisByCategory[emoji.category].push(emoji);
|
|
|
|
});
|
|
|
|
|
|
|
|
const EmojiPicker = (props) => {
|
|
|
|
const open = Boolean(props.anchorEl);
|
2022-04-04 23:56:21 +00:00
|
|
|
const [search, setSearch] = useState("");
|
|
|
|
const searchRef = useRef(null);
|
|
|
|
|
|
|
|
/*
|
|
|
|
FIXME Search is inefficient, somehow make it faster
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
const matching = rawEmojis.filter(e => {
|
|
|
|
const searchLower = search.toLowerCase();
|
|
|
|
return e.description.toLowerCase().indexOf(searchLower) !== -1
|
|
|
|
|| matchInArray(e.aliases, searchLower)
|
|
|
|
|| matchInArray(e.tags, searchLower);
|
|
|
|
});
|
|
|
|
console.log("matching", matching.length);
|
|
|
|
}, [search]);
|
|
|
|
*/
|
|
|
|
const handleSearchClear = () => {
|
|
|
|
setSearch("");
|
|
|
|
searchRef.current?.focus();
|
|
|
|
};
|
2022-04-04 14:04:01 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Popover
|
|
|
|
open={open}
|
2022-04-04 23:56:21 +00:00
|
|
|
elevation={3}
|
2022-04-04 14:04:01 +00:00
|
|
|
onClose={props.onClose}
|
2022-04-04 23:56:21 +00:00
|
|
|
anchorEl={props.anchorEl}
|
2022-04-04 14:04:01 +00:00
|
|
|
anchorOrigin={{
|
|
|
|
vertical: 'bottom',
|
|
|
|
horizontal: 'left',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<Box sx={{ padding: 2, paddingRight: 0, width: "370px", maxHeight: "300px" }}>
|
2022-04-04 23:56:21 +00:00
|
|
|
<TextField
|
|
|
|
inputRef={searchRef}
|
|
|
|
margin="dense"
|
|
|
|
size="small"
|
|
|
|
placeholder="Search emoji"
|
|
|
|
value={search}
|
|
|
|
onChange={ev => setSearch(ev.target.value)}
|
|
|
|
type="text"
|
|
|
|
variant="standard"
|
|
|
|
fullWidth
|
|
|
|
sx={{ marginTop: 0, paddingRight: 2 }}
|
|
|
|
InputProps={{
|
|
|
|
endAdornment:
|
|
|
|
<InputAdornment position="end" sx={{ display: (search) ? '' : 'none' }}>
|
|
|
|
<IconButton size="small" onClick={handleSearchClear} edge="end"><Close/></IconButton>
|
|
|
|
</InputAdornment>
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
<Box sx={{ display: "flex", flexWrap: "wrap", paddingRight: 0, marginTop: 1 }}>
|
|
|
|
{Object.keys(emojisByCategory).map(category =>
|
|
|
|
<Category
|
|
|
|
key={category}
|
|
|
|
title={category}
|
|
|
|
emojis={emojisByCategory[category]}
|
|
|
|
search={search.toLowerCase()}
|
|
|
|
onPick={props.onEmojiPick}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</Box>
|
2022-04-04 14:04:01 +00:00
|
|
|
</Box>
|
|
|
|
</Popover>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const Category = (props) => {
|
2022-04-04 23:56:21 +00:00
|
|
|
const showTitle = !props.search;
|
2022-04-04 14:04:01 +00:00
|
|
|
return (
|
|
|
|
<>
|
2022-04-04 23:56:21 +00:00
|
|
|
{showTitle &&
|
|
|
|
<Typography variant="body1" sx={{ width: "100%", marginTop: 1, marginBottom: 1 }}>
|
|
|
|
{props.title}
|
|
|
|
</Typography>
|
|
|
|
}
|
|
|
|
{props.emojis.map(emoji =>
|
|
|
|
<Emoji
|
|
|
|
key={emoji.aliases[0]}
|
|
|
|
emoji={emoji}
|
|
|
|
search={props.search}
|
|
|
|
onClick={() => props.onPick(emoji.aliases[0])}
|
|
|
|
/>
|
|
|
|
)}
|
2022-04-04 14:04:01 +00:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const Emoji = (props) => {
|
|
|
|
const emoji = props.emoji;
|
2022-04-04 23:56:21 +00:00
|
|
|
const search = props.search;
|
|
|
|
const matches = search === ""
|
|
|
|
|| emoji.description.toLowerCase().indexOf(search) !== -1
|
|
|
|
|| matchInArray(emoji.aliases, search)
|
|
|
|
|| matchInArray(emoji.tags, search);
|
|
|
|
if (!matches) {
|
|
|
|
return null;
|
|
|
|
}
|
2022-04-04 14:04:01 +00:00
|
|
|
return (
|
|
|
|
<div
|
|
|
|
onClick={props.onClick}
|
|
|
|
title={`${emoji.description} (${emoji.aliases[0]})`}
|
|
|
|
style={{
|
|
|
|
fontSize: "30px",
|
|
|
|
width: "30px",
|
|
|
|
height: "30px",
|
|
|
|
marginTop: "8px",
|
|
|
|
marginBottom: "8px",
|
|
|
|
marginRight: "8px",
|
|
|
|
lineHeight: "30px",
|
|
|
|
cursor: "pointer"
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{props.emoji.emoji}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2022-04-04 23:56:21 +00:00
|
|
|
const matchInArray = (arr, search) => {
|
|
|
|
if (!arr || !search) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return arr.filter(s => s.indexOf(search) !== -1).length > 0;
|
|
|
|
}
|
|
|
|
|
2022-04-04 14:04:01 +00:00
|
|
|
export default EmojiPicker;
|