from __future__ import annotations from dataclasses import dataclass from html import escape import gradio as gr @dataclass(frozen=True) class EmojiPaletteItem: emoji: str label: str description: str EMOJI_PALETTE_CSS = """ .emoji-palette { max-width: 100%; } .emoji-palette-grid { display: flex; gap: 3px; flex-wrap: wrap; align-items: flex-start; max-height: 124px; overflow-y: auto; } .emoji-palette-button { flex: 0 0 28px !important; min-width: 28px !important; max-width: 28px !important; } .emoji-palette-button button { width: 28px !important; min-width: 28px !important; height: 28px !important; min-height: 28px !important; border-radius: 4px; font-size: 17px; line-height: 1; padding: 0 !important; } button.emoji-palette-button { width: 28px; min-width: 28px; height: 28px; min-height: 28px; border-radius: 4px; font-size: 17px; line-height: 1; padding: 0; cursor: pointer; } """ EMOJI_PALETTE_ITEMS: tuple[EmojiPaletteItem, ...] = ( EmojiPaletteItem("๐", "ๅใ", "่ณๅ ใฎ้ณ"), EmojiPaletteItem("๐ฎโ๐จ", "ๅๆฏ", "ๆบๆฏใๅฏๆฏ"), EmojiPaletteItem("โธ๏ธ", "้", "ๆฒ้ป"), EmojiPaletteItem("๐คญ", "็ฌใ", "ใใใใใๅซใฟ็ฌใ"), EmojiPaletteItem("๐ฅต", "ๅใ", "ใใใๅฃฐใๅธใๅฃฐ"), EmojiPaletteItem("๐ข", "ใจใณใผ", "ใชใใผใ"), EmojiPaletteItem("๐", "ใใใใ", "็ใใใใใซ"), EmojiPaletteItem("๐ฅบ", "้ใๅฃฐ", "่ชไฟกใชใใใซ"), EmojiPaletteItem("๐ฌ๏ธ", "ๆฏๅใ", "่ใๆฏ้ฃใใๅผๅธ้ณ"), EmojiPaletteItem("๐ฎ", "ๆฏใใฎใ", "Gasp"), EmojiPaletteItem("๐ ", "่ใใ้ณ", "ๅๅผ้ณใๆฐด้ณ"), EmojiPaletteItem("๐", "ใชใใใใคใบ", "Lip smack"), EmojiPaletteItem("๐ซถ", "ๅชใใ", "Tenderly"), EmojiPaletteItem("๐ญ", "ๆณฃใๅฃฐ", "ๅๅฝใๆฒใใฟ"), EmojiPaletteItem("๐ฑ", "ๆฒ้ณด", "ๅซใณใ็ตถๅซ"), EmojiPaletteItem("๐ช", "็ ใใ", "ๆฐใ ใใใซ"), EmojiPaletteItem("๐ด", "ๅฏ่จ", "ใใณใ"), EmojiPaletteItem("โฉ", "ๆฉๅฃ", "ไธๆฐใซใๆฅใใง"), EmojiPaletteItem("๐", "้ป่ฉฑ่ถใ", "ในใใผใซใผ่ถใ"), EmojiPaletteItem("๐ข", "ใใฃใใ", "Slowly"), EmojiPaletteItem("๐ฅค", "้ฃฒใฟ่พผใ", "ๅพใ้ฃฒใ้ณ"), EmojiPaletteItem("๐คง", "ๅณใป้ผป", "ๅณใ่พผใฟใ้ผปใใใ"), EmojiPaletteItem("๐", "่ๆใก", "Tutting"), EmojiPaletteItem("๐ฐ", "ๆ ใฆใ", "ๅๆบใ็ทๅผตใใฉใใ"), EmojiPaletteItem("๐", "ๅใณ", "ๅฌใใใใซ"), EmojiPaletteItem("๐ฅ", "ๅขใใใ", "ๅๅผทใๅขใ"), EmojiPaletteItem("๐ ", "ๆใ", "ไธๆบใใๆใญใ"), EmojiPaletteItem("๐ฒ", "้ฉใ", "ๆๅ"), EmojiPaletteItem("๐ฅฑ", "ใใใณ", "Yawn"), EmojiPaletteItem("๐", "่ฆใใ", "Agonizingly"), EmojiPaletteItem("๐", "ๅฟ้ ", "ไธๅฎใใใซ"), EmojiPaletteItem("๐ซฃ", "็ งใ", "ๆฅใใใใใใซ"), EmojiPaletteItem("๐", "ๅใ", "Exasperatedly"), EmojiPaletteItem("๐", "ๆฅฝใใ", "ๅฌใใใใซ"), EmojiPaletteItem("๐", "ๅพๆใ", "่ชไฟกใใใใซ"), EmojiPaletteItem("๐", "็ธๆง", "้ ทใ้ณ"), EmojiPaletteItem("๐", "ๆ้ก", "ใ้กใใใใใใซ"), EmojiPaletteItem("๐ฅด", "้ ใ", "Drunkenly"), EmojiPaletteItem("๐ต", "้ผปๆญ", "Humming"), EmojiPaletteItem("๐ค", "ๅฃใๅกใ", "Muffled"), EmojiPaletteItem("๐", "ๅฎๅ ต", "ๆบ่ถณใใซ"), EmojiPaletteItem("๐ค", "็ๅ", "Questioning"), EmojiPaletteItem("๐ช", "ๅๅผทใ", "ๅใ่พผใใฆ"), EmojiPaletteItem("๐", "ๅ ใ้ณ", "ๅใใๅ ใ้ณ"), EmojiPaletteItem("๐", "ๆ่ชญ", "ใใฌใผใทใงใณ"), ) _INSERT_EMOJI_ON_POINTER_DOWN = ( "event.preventDefault();" "const root=this.closest('[data-irodori-emoji-palette]');" "const input=root?document.querySelector(root.dataset.target):null;" "if(!input)return;" "const emoji=this.dataset.emoji;" "const text=input.value||'';" "const focused=document.activeElement===input;" "const start=focused&&typeof input.selectionStart==='number'?input.selectionStart:text.length;" "const end=focused&&typeof input.selectionEnd==='number'?input.selectionEnd:text.length;" "const next=text.slice(0,start)+emoji+text.slice(end);" "const caret=start+emoji.length;" "input.value=next;" "input.focus({preventScroll:true});" "input.setSelectionRange(caret,caret);" "input.dispatchEvent(new Event('input',{bubbles:true}));" "input.dispatchEvent(new Event('change',{bubbles:true}));" ) def _textbox_selector(textbox: gr.Textbox) -> str: elem_id = getattr(textbox, "elem_id", None) root_selector = f"#{elem_id}" if elem_id else f"#component-{textbox._id}" return f"{root_selector} textarea, {root_selector} input:not([type='hidden'])" def _emoji_palette_html(textbox: gr.Textbox) -> str: target = escape(_textbox_selector(textbox), quote=True) handler = escape(_INSERT_EMOJI_ON_POINTER_DOWN, quote=True) buttons = [] for item in EMOJI_PALETTE_ITEMS: emoji = escape(item.emoji, quote=True) title = escape(f"{item.label}: {item.description}", quote=True) buttons.append( '" ) return ( '