import React, { Fragment, useCallback, useEffect, useState } from 'react'; import { SilkeBox } from '../silke-box'; import { SilkeButton } from '../silke-button'; import ButtonContext from '../silke-button/context'; import { SilkeSearchField } from '../silke-search-field'; import { SilkeText } from '../silke-text'; import { SilkeToolbar } from '../silke-toolbar'; import { SilkeVirtualGrid } from '../silke-virtual'; import { TabProps } from './utils'; import styles from './styles.scss'; type EmojiCategory = { id: string; name: string; emojis: string[]; }; type Emoji = { a: string; b: string; j?: string[]; k: number[]; m?: string; o: number; }; function toEmoji(unified: string): string { const unicodes = unified.split('-'), codePoints = unicodes.map((u) => Number(`0x${u}`)); return String.fromCodePoint(...codePoints); } type EmojiData = { compressed: true; categories: EmojiCategory[]; emojis: Record; aliases: Record; }; let emojiPromise: Promise; async function fetchEmojis(): Promise { if (!emojiPromise) { emojiPromise = fetch('https://cdn.vev.design/icons/emojis.json').then((r) => r.json()); } return emojiPromise; } export default function EmojiTab({ onSelect }: TabProps) { const [emojis, setEmojis] = useState(null); const [query, setQuery] = useState(''); useEffect(() => { fetchEmojis().then(setEmojis); }, []); const filtered = React.useMemo(() => { if (!emojis) return []; if (query.length === 0) return emojis.categories; const lowercaseQuery = query.toLocaleLowerCase(); const result = emojis.categories .map((category) => { return { ...category, emojis: category.emojis.filter((id) => { if (id.includes(lowercaseQuery)) { return true; } const emoji = emojis.emojis[id]; if (emoji.a.includes(lowercaseQuery)) { return true; } return emoji.j && emoji.j.find((keyword) => keyword.includes(lowercaseQuery)); }), }; }) .filter((category) => category.emojis.length > 0); return result; }, [query, emojis]); const handleRandom = useCallback(() => { if (emojis) { const randomCategoryIndex = Math.floor(Math.random() * filtered.length); const randomEmojiIndex = Math.floor( Math.random() * filtered[randomCategoryIndex].emojis.length, ); const emoji = emojis.emojis[filtered[randomCategoryIndex].emojis[randomEmojiIndex]]; onSelect({ type: 0, value: toEmoji(emoji.b) }); } }, [emojis, filtered, onSelect]); return ( setQuery('')} /> {!emojis && ( )} {filtered.map((category) => ( {category.name} {(emoji) => { const value = emojis?.emojis[emoji]?.b; if (!value) return false; return ( onSelect({ type: 0, value: toEmoji(value) })} /> ); }} ))} ); }