multimodalart's picture
multimodalart HF Staff
Upload folder using huggingface_hub
fdcef0f verified
Raw
History Blame Contribute Delete
6.01 kB
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(
'<button type="button" '
'class="emoji-palette-button" '
f'data-emoji="{emoji}" '
f'title="{title}" '
f'aria-label="{title}" '
f'onpointerdown="{handler}">'
f"{emoji}</button>"
)
return (
'<div class="emoji-palette-grid" '
'data-irodori-emoji-palette="true" '
f'data-target="{target}">'
f"{''.join(buttons)}</div>"
)
def build_emoji_palette(textbox: gr.Textbox, *, open: bool = True) -> None:
with gr.Accordion("Emoji Palette", open=open, elem_classes=["emoji-palette"]):
gr.HTML(_emoji_palette_html(textbox))