110 lines
9.5 KiB
TypeScript
110 lines
9.5 KiB
TypeScript
/** A generous, categorized emoji set with shortcodes + search keywords.
|
|
* Powers the picker, composer autocomplete, reactions, and `:shortcode:` parsing. */
|
|
|
|
export interface Emoji {
|
|
e: string; // the emoji
|
|
n: string; // canonical shortcode name (no colons)
|
|
k?: string; // extra search keywords
|
|
c: EmojiCategory;
|
|
}
|
|
|
|
export type EmojiCategory =
|
|
| "Frequent" | "Smileys" | "Gestures" | "People" | "Animals"
|
|
| "Food" | "Activity" | "Travel" | "Objects" | "Symbols" | "Flags";
|
|
|
|
export const EMOJI_CATEGORIES: EmojiCategory[] = [
|
|
"Frequent", "Smileys", "Gestures", "People", "Animals", "Food", "Activity", "Travel", "Objects", "Symbols", "Flags",
|
|
];
|
|
|
|
export const EMOJIS: Emoji[] = [
|
|
// Smileys
|
|
{ e: "😀", n: "grinning", c: "Smileys" }, { e: "😃", n: "smiley", c: "Smileys" }, { e: "😄", n: "smile", c: "Smileys" },
|
|
{ e: "😁", n: "grin", c: "Smileys" }, { e: "😆", n: "laughing", k: "haha", c: "Smileys" }, { e: "😅", n: "sweat_smile", c: "Smileys" },
|
|
{ e: "🤣", n: "rofl", k: "lol laugh", c: "Smileys" }, { e: "😂", n: "joy", k: "lol cry laugh", c: "Smileys" }, { e: "🙂", n: "slightly_smiling", c: "Smileys" },
|
|
{ e: "🙃", n: "upside_down", c: "Smileys" }, { e: "😉", n: "wink", c: "Smileys" }, { e: "😊", n: "blush", c: "Smileys" },
|
|
{ e: "😇", n: "innocent", k: "angel", c: "Smileys" }, { e: "🥰", n: "smiling_hearts", k: "love", c: "Smileys" }, { e: "😍", n: "heart_eyes", k: "love", c: "Smileys" },
|
|
{ e: "😘", n: "kissing_heart", c: "Smileys" }, { e: "😜", n: "stuck_out_tongue_wink", c: "Smileys" }, { e: "🤪", n: "zany", c: "Smileys" },
|
|
{ e: "🤨", n: "raised_eyebrow", k: "skeptic", c: "Smileys" }, { e: "🧐", n: "monocle", c: "Smileys" }, { e: "🤓", n: "nerd", c: "Smileys" },
|
|
{ e: "😎", n: "sunglasses", k: "cool", c: "Smileys" }, { e: "🥳", n: "partying", k: "celebrate party", c: "Smileys" }, { e: "😏", n: "smirk", c: "Smileys" },
|
|
{ e: "😒", n: "unamused", c: "Smileys" }, { e: "😞", n: "disappointed", c: "Smileys" }, { e: "😔", n: "pensive", c: "Smileys" },
|
|
{ e: "😟", n: "worried", c: "Smileys" }, { e: "😢", n: "cry", k: "sad tear", c: "Smileys" }, { e: "😭", n: "sob", k: "cry sad", c: "Smileys" },
|
|
{ e: "😤", n: "huff", c: "Smileys" }, { e: "😠", n: "angry", c: "Smileys" }, { e: "😡", n: "rage", k: "mad angry", c: "Smileys" },
|
|
{ e: "🤬", n: "cursing", c: "Smileys" }, { e: "🤯", n: "mind_blown", k: "explode", c: "Smileys" }, { e: "😳", n: "flushed", c: "Smileys" },
|
|
{ e: "🥵", n: "hot", c: "Smileys" }, { e: "🥶", n: "cold", c: "Smileys" }, { e: "😱", n: "scream", k: "shock", c: "Smileys" },
|
|
{ e: "😨", n: "fearful", c: "Smileys" }, { e: "😰", n: "anxious", c: "Smileys" }, { e: "🤔", n: "thinking", k: "hmm", c: "Smileys" },
|
|
{ e: "🤫", n: "shush", c: "Smileys" }, { e: "🤐", n: "zipper_mouth", c: "Smileys" }, { e: "😴", n: "sleeping", k: "zzz tired", c: "Smileys" },
|
|
{ e: "🥱", n: "yawn", k: "tired bored", c: "Smileys" }, { e: "🤒", n: "sick", k: "ill", c: "Smileys" }, { e: "🤕", n: "hurt", c: "Smileys" },
|
|
{ e: "🤮", n: "vomit", c: "Smileys" }, { e: "😷", n: "mask", c: "Smileys" }, { e: "🤗", n: "hug", c: "Smileys" },
|
|
{ e: "🤭", n: "hand_over_mouth", c: "Smileys" }, { e: "😬", n: "grimace", c: "Smileys" }, { e: "🙄", n: "eye_roll", c: "Smileys" },
|
|
// Gestures
|
|
{ e: "👍", n: "+1", k: "thumbsup like yes", c: "Gestures" }, { e: "👎", n: "-1", k: "thumbsdown no", c: "Gestures" }, { e: "👏", n: "clap", k: "applause", c: "Gestures" },
|
|
{ e: "🙌", n: "raised_hands", k: "hooray celebrate", c: "Gestures" }, { e: "👋", n: "wave", k: "hi hello bye", c: "Gestures" }, { e: "🤝", n: "handshake", k: "deal", c: "Gestures" },
|
|
{ e: "🙏", n: "pray", k: "please thanks", c: "Gestures" }, { e: "✌️", n: "victory", k: "peace", c: "Gestures" }, { e: "🤞", n: "crossed_fingers", k: "luck", c: "Gestures" },
|
|
{ e: "👌", n: "ok_hand", c: "Gestures" }, { e: "🤙", n: "call_me", c: "Gestures" }, { e: "💪", n: "muscle", k: "strong flex", c: "Gestures" },
|
|
{ e: "👊", n: "fist_bump", c: "Gestures" }, { e: "✊", n: "raised_fist", c: "Gestures" }, { e: "🤟", n: "love_you", c: "Gestures" },
|
|
{ e: "👉", n: "point_right", c: "Gestures" }, { e: "👈", n: "point_left", c: "Gestures" }, { e: "👆", n: "point_up", c: "Gestures" },
|
|
{ e: "🫡", n: "salute", c: "Gestures" }, { e: "🫶", n: "heart_hands", c: "Gestures" }, { e: "🤌", n: "pinched", c: "Gestures" },
|
|
// People / Activity
|
|
{ e: "🎉", n: "tada", k: "party celebrate hooray", c: "Activity" }, { e: "🎊", n: "confetti", c: "Activity" }, { e: "🥳", n: "party", c: "Activity" },
|
|
{ e: "🏆", n: "trophy", k: "win", c: "Activity" }, { e: "🥇", n: "1st_place", c: "Activity" }, { e: "⚽", n: "soccer", c: "Activity" },
|
|
{ e: "🏀", n: "basketball", c: "Activity" }, { e: "🎯", n: "dart", k: "target bullseye", c: "Activity" }, { e: "🎮", n: "video_game", c: "Activity" },
|
|
{ e: "🎸", n: "guitar", c: "Activity" }, { e: "🎧", n: "headphones", k: "music", c: "Activity" }, { e: "🚀", n: "rocket", k: "ship launch fast", c: "Travel" },
|
|
// Animals
|
|
{ e: "🐶", n: "dog", c: "Animals" }, { e: "🐱", n: "cat", c: "Animals" }, { e: "🦄", n: "unicorn", c: "Animals" },
|
|
{ e: "🐝", n: "bee", c: "Animals" }, { e: "🦋", n: "butterfly", c: "Animals" }, { e: "🐢", n: "turtle", c: "Animals" },
|
|
{ e: "🐼", n: "panda", c: "Animals" }, { e: "🦁", n: "lion", c: "Animals" }, { e: "🐧", n: "penguin", c: "Animals" },
|
|
// Food
|
|
{ e: "🍕", n: "pizza", c: "Food" }, { e: "🍔", n: "burger", c: "Food" }, { e: "🌮", n: "taco", c: "Food" },
|
|
{ e: "🍣", n: "sushi", c: "Food" }, { e: "🍜", n: "ramen", k: "noodles", c: "Food" }, { e: "☕", n: "coffee", c: "Food" },
|
|
{ e: "🍺", n: "beer", c: "Food" }, { e: "🥂", n: "clink", k: "cheers", c: "Food" }, { e: "🎂", n: "cake", k: "birthday", c: "Food" },
|
|
{ e: "🍩", n: "donut", c: "Food" }, { e: "🍎", n: "apple", c: "Food" }, { e: "🥑", n: "avocado", c: "Food" },
|
|
// Travel / weather
|
|
{ e: "🌍", n: "earth", c: "Travel" }, { e: "✈️", n: "airplane", c: "Travel" }, { e: "🚗", n: "car", c: "Travel" },
|
|
{ e: "🏠", n: "house", k: "home", c: "Travel" }, { e: "🏗️", n: "construction", k: "site build", c: "Travel" }, { e: "🌩️", n: "storm", k: "thunder weather", c: "Travel" },
|
|
{ e: "☀️", n: "sun", c: "Travel" }, { e: "🌈", n: "rainbow", c: "Travel" }, { e: "🔥", n: "fire", k: "lit hot flame", c: "Objects" },
|
|
// Objects
|
|
{ e: "💡", n: "bulb", k: "idea", c: "Objects" }, { e: "📌", n: "pin", c: "Objects" }, { e: "📎", n: "paperclip", c: "Objects" },
|
|
{ e: "📈", n: "chart_up", k: "growth", c: "Objects" }, { e: "📉", n: "chart_down", c: "Objects" }, { e: "📅", n: "calendar", c: "Objects" },
|
|
{ e: "📐", n: "ruler", c: "Objects" }, { e: "🛠️", n: "tools", c: "Objects" }, { e: "🔧", n: "wrench", c: "Objects" },
|
|
{ e: "💰", n: "money", c: "Objects" }, { e: "📱", n: "phone", c: "Objects" }, { e: "💻", n: "laptop", c: "Objects" },
|
|
{ e: "⚙️", n: "gear", k: "settings", c: "Objects" }, { e: "🔒", n: "lock", c: "Objects" }, { e: "🔑", n: "key", c: "Objects" },
|
|
{ e: "🎁", n: "gift", c: "Objects" }, { e: "🤖", n: "robot", k: "bot ai", c: "Objects" }, { e: "⚡", n: "zap", k: "fast bolt", c: "Objects" },
|
|
// Symbols
|
|
{ e: "❤️", n: "heart", k: "love red", c: "Symbols" }, { e: "🧡", n: "orange_heart", c: "Symbols" }, { e: "💛", n: "yellow_heart", c: "Symbols" },
|
|
{ e: "💚", n: "green_heart", c: "Symbols" }, { e: "💙", n: "blue_heart", c: "Symbols" }, { e: "💜", n: "purple_heart", c: "Symbols" },
|
|
{ e: "🖤", n: "black_heart", c: "Symbols" }, { e: "💯", n: "100", k: "hundred perfect", c: "Symbols" }, { e: "✅", n: "white_check_mark", k: "tick done yes check", c: "Symbols" },
|
|
{ e: "☑️", n: "check", k: "tick done", c: "Symbols" }, { e: "✔️", n: "heavy_check", k: "tick", c: "Symbols" }, { e: "❌", n: "x", k: "cross no wrong", c: "Symbols" },
|
|
{ e: "⭐", n: "star", c: "Symbols" }, { e: "🌟", n: "glowing_star", c: "Symbols" }, { e: "✨", n: "sparkles", c: "Symbols" },
|
|
{ e: "❗", n: "exclamation", c: "Symbols" }, { e: "❓", n: "question", c: "Symbols" }, { e: "⚠️", n: "warning", c: "Symbols" },
|
|
{ e: "👀", n: "eyes", k: "look watch", c: "Symbols" }, { e: "🎈", n: "balloon", c: "Symbols" }, { e: "💥", n: "boom", c: "Symbols" },
|
|
];
|
|
|
|
// name → emoji map for :shortcode: parsing
|
|
const NAME_MAP: Record<string, string> = (() => {
|
|
const m: Record<string, string> = {};
|
|
for (const em of EMOJIS) m[em.n] = em.e;
|
|
// common aliases
|
|
m["thumbsup"] = "👍"; m["thumbsdown"] = "👎"; m["heart"] = "❤️"; m["fire"] = "🔥";
|
|
m["check"] = "✅"; m["tick"] = "✅"; m["done"] = "✅"; m["rocket"] = "🚀"; m["party"] = "🎉";
|
|
m["smile"] = "😄"; m["laugh"] = "😂"; m["ok"] = "👌"; m["eyes"] = "👀"; m["100"] = "💯";
|
|
return m;
|
|
})();
|
|
|
|
/** Replace :shortcode: tokens in a string with their emoji. */
|
|
export function replaceShortcodes(text: string): string {
|
|
return text.replace(/:([a-z0-9_+-]{1,30}):/gi, (whole, name) => NAME_MAP[name.toLowerCase()] ?? whole);
|
|
}
|
|
|
|
export function shortcodeToEmoji(name: string): string | undefined {
|
|
return NAME_MAP[name.toLowerCase()];
|
|
}
|
|
|
|
/** Fuzzy search across name + keywords. */
|
|
export function searchEmojis(query: string, limit = 40): Emoji[] {
|
|
const q = query.toLowerCase().trim();
|
|
if (!q) return EMOJIS.slice(0, limit);
|
|
return EMOJIS.filter((e) => e.n.includes(q) || (e.k && e.k.includes(q))).slice(0, limit);
|
|
}
|
|
|
|
export const FREQUENT: string[] = ["👍", "🎉", "🔥", "❤️", "😂", "🙌", "👀", "✅", "🚀", "💯", "🙏", "👏"];
|