import { ComponentProps } from 'react' import { MessageFormatOptions, MessageFormatPart } from './chatUtils' import './MessageFormatted.css' export const MessagePart = ({ part, formatOptions, ...props }: { part: MessageFormatPart, formatOptions?: MessageFormatOptions } & Pick, 'style' | 'className' | 'children'>) => { const { color: _color, italic, bold, underlined, strikethrough, text, clickEvent, hoverEvent, obfuscated } = part const color = _color ?? 'white' const applyStyles = [ colorF(color.toLowerCase()) + ((formatOptions?.doShadow ?? true) ? `; text-shadow: 1px 1px 0px ${getColorShadow(colorF(color.toLowerCase()).replace('color:', ''))}` : ''), italic && messageFormatStylesMap.italic, bold && messageFormatStylesMap.bold, italic && messageFormatStylesMap.italic, underlined && messageFormatStylesMap.underlined, strikethrough && messageFormatStylesMap.strikethrough, obfuscated && messageFormatStylesMap.obfuscated ].filter(a => a !== false && a !== undefined).filter(Boolean) return {text} } export default ({ parts, className, formatOptions }: { parts: readonly MessageFormatPart[], className?: string, formatOptions?: MessageFormatOptions }) => { return ( {parts.map((part, i) => )} ) } const colorF = (color) => { return color.trim().startsWith('#') ? `color:${color}` : messageFormatStylesMap[color] ?? undefined } export function getColorShadow (hex, dim = 0.25) { const color = parseInt(hex.replace('#', ''), 16) const r = Math.trunc((color >> 16 & 0xFF) * dim) const g = Math.trunc((color >> 8 & 0xFF) * dim) const b = Math.trunc((color & 0xFF) * dim) const f = (c) => ('00' + c.toString(16)).slice(-2) return `#${f(r)}${f(g)}${f(b)}` } export function parseInlineStyle (style: string): Record { const obj: Record = {} for (const rule of style.split(';')) { const [prop, value] = rule.split(':') const cssInJsProp = prop.trim().replaceAll(/-./g, (x) => x.toUpperCase()[1]) obj[cssInJsProp] = value.trim() } return obj } export const messageFormatStylesMap = { black: 'color:color(display-p3 0 0 0)', dark_blue: 'color:color(display-p3 0 0 0.6667)', dark_green: 'color:color(display-p3 0 0.6667 0)', dark_aqua: 'color:color(display-p3 0 0.6667 0.6667)', dark_red: 'color:color(display-p3 0.6667 0 0)', dark_purple: 'color:color(display-p3 0.6667 0 0.6667)', gold: 'color:color(display-p3 1 0.6667 0)', gray: 'color:color(display-p3 0.6667 0.6667 0.6667)', dark_gray: 'color:color(display-p3 0.3333 0.3333 0.3333)', blue: 'color:color(display-p3 0.3333 0.3333 1)', green: 'color:color(display-p3 0.3333 1 0.3333)', aqua: 'color:color(display-p3 0.3333 1 1)', red: 'color:color(display-p3 1 0.3333 0.3333)', light_purple: 'color:color(display-p3 1 0.3333 1)', yellow: 'color:color(display-p3 1 1 0.3333)', white: 'color:color(display-p3 1 1 1)', bold: 'font-weight:900', strikethrough: 'text-decoration:line-through', underlined: 'text-decoration:underline', italic: 'font-style:italic', obfuscated: 'filter:blur(2px)', clickEvent: 'cursor:pointer', }