Twemoji
ncdai/twemojiUnverifiedComponent
Render Unicode emoji as Twemoji SVG images inline with text.
Install it
npx shadcn@latest add https://raw.githubusercontent.com/exekartik/exeKartik/main/twemoji.jsonSource
1import type { ReactNode } from "react"23import { cn } from "@/lib/utils"4import emojiRegex from "@/registry/components/twemoji/lib/twemoji-regex"56const VARIATION_SELECTOR_16 = /\uFE0F/g7const ZERO_WIDTH_JOINER = String.fromCharCode(0x200d)89export const TWEMOJI_CDN_URL = "https://abs-0.twimg.com/emoji/v2/svg"1011export type TwemojiProps = {12 children: string13 className?: string14 /**15 * Resolve an emoji code point to an image URL.16 *17 * @param codePoint - The Unicode code point of the emoji (e.g. `1f44d`)18 * @returns The URL string pointing to the emoji image asset19 *20 * @example21 * ```tsx22 * source={(codePoint) => `https://cdn.example.com/emoji/${codePoint}.svg`}23 * ```24 * */25 source?: (codePoint: string) => string26}2728export function Twemoji({29 children,30 className,31 source = defaultSource,32}: TwemojiProps) {33 const parts: ReactNode[] = []34 let lastIndex = 035 const globalRegex = new RegExp(emojiRegex.source, "g")36 let match3738 while ((match = globalRegex.exec(children)) !== null) {39 if (match.index > lastIndex) {40 parts.push(children.substring(lastIndex, match.index))41 }4243 const rawText = match[0]44 const codePoint = getEmojiCodePoint(rawText)4546 if (codePoint) {47 parts.push(48 <img49 key={match.index}50 className={cn("twemoji", className)}51 draggable={false}52 alt={rawText}53 src={source(codePoint)}54 />55 )56 } else {57 parts.push(rawText)58 }5960 lastIndex = globalRegex.lastIndex61 }6263 if (lastIndex < children.length) {64 parts.push(children.substring(lastIndex))65 }6667 return <>{parts}</>68}6970function getEmojiCodePoint(rawText: string) {71 return toCodePoint(72 rawText.indexOf(ZERO_WIDTH_JOINER) < 073 ? rawText.replace(VARIATION_SELECTOR_16, "")74 : rawText75 )76}7778function toCodePoint(unicodeSurrogates: string, sep = "-") {79 const result: string[] = []80 let code = 081 let previous = 082 let i = 08384 while (i < unicodeSurrogates.length) {85 code = unicodeSurrogates.charCodeAt(i++)86 if (previous) {87 result.push(88 (0x10000 + ((previous - 0xd800) << 10) + (code - 0xdc00)).toString(16)89 )90 previous = 091 } else if (0xd800 <= code && code <= 0xdbff) {92 previous = code93 } else {94 result.push(code.toString(16))95 }96 }9798 return result.join(sep)99}100101function defaultSource(codePoint: string) {102 return `${TWEMOJI_CDN_URL}/${codePoint}.svg`103}
Files it writes
More from ncdai
All 17 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Apple Hello Effectapple-hello-effect | ncdai | Components | Unverified | 1 dep | |
| Apple Hello Effect - Hindiapple-hello-effect-hindi | ncdai | Components | Unverified | 1 dep | |
| Apple Hello Effect - Spanishapple-hello-effect-spanish | ncdai | Components | Unverified | 1 dep | |
| Apple Hello Effect - Vietnameseapple-hello-effect-vietnamese | ncdai | Components | Unverified | 1 dep | |
| Brand Assets Menubrand-assets-menu | ncdai | Components | Unverified | 1 dep | |
| chevrons-up-down-iconchevrons-up-down-icon | ncdai | Components | Unverified | 1 dep | |
| Code Block Commandcode-block-command | ncdai | Components | Unverified | 4 deps · 3 files | |
| Consent Managerconsent-manager | ncdai | Components | Unverified | 1 dep · 2 files |
