2025-07-31 19:30:14 +02:00
|
|
|
import type { ComponentPropsWithoutRef, ElementType } from 'react';
|
2025-07-22 16:43:15 +02:00
|
|
|
|
2025-09-23 10:53:14 +02:00
|
|
|
import classNames from 'classnames';
|
|
|
|
|
|
2025-09-08 14:08:07 +02:00
|
|
|
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
|
|
|
|
|
2025-07-31 19:30:14 +02:00
|
|
|
import { useEmojify } from './hooks';
|
|
|
|
|
import type { CustomEmojiMapArg } from './types';
|
2025-07-22 16:43:15 +02:00
|
|
|
|
2025-07-31 19:30:14 +02:00
|
|
|
type EmojiHTMLProps<Element extends ElementType = 'div'> = Omit<
|
|
|
|
|
ComponentPropsWithoutRef<Element>,
|
2025-09-23 10:53:14 +02:00
|
|
|
'dangerouslySetInnerHTML' | 'className'
|
2025-07-22 16:43:15 +02:00
|
|
|
> & {
|
|
|
|
|
htmlString: string;
|
2025-07-31 19:30:14 +02:00
|
|
|
extraEmojis?: CustomEmojiMapArg;
|
|
|
|
|
as?: Element;
|
2025-09-04 12:09:27 +02:00
|
|
|
shallow?: boolean;
|
2025-09-23 10:53:14 +02:00
|
|
|
className?: string;
|
2025-07-22 16:43:15 +02:00
|
|
|
};
|
|
|
|
|
|
2025-09-08 14:08:07 +02:00
|
|
|
export const ModernEmojiHTML = ({
|
2025-07-22 16:43:15 +02:00
|
|
|
extraEmojis,
|
2025-07-31 19:30:14 +02:00
|
|
|
htmlString,
|
2025-09-04 12:09:27 +02:00
|
|
|
as: Wrapper = 'div', // Rename for syntax highlighting
|
|
|
|
|
shallow,
|
2025-09-23 10:53:14 +02:00
|
|
|
className = '',
|
2025-07-22 16:43:15 +02:00
|
|
|
...props
|
2025-09-04 12:09:27 +02:00
|
|
|
}: EmojiHTMLProps<ElementType>) => {
|
|
|
|
|
const emojifiedHtml = useEmojify({
|
|
|
|
|
text: htmlString,
|
|
|
|
|
extraEmojis,
|
|
|
|
|
deep: !shallow,
|
|
|
|
|
});
|
2025-07-22 16:43:15 +02:00
|
|
|
|
2025-07-31 19:30:14 +02:00
|
|
|
if (emojifiedHtml === null) {
|
2025-07-22 16:43:15 +02:00
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-31 19:30:14 +02:00
|
|
|
return (
|
2025-09-23 10:53:14 +02:00
|
|
|
<Wrapper
|
|
|
|
|
{...props}
|
|
|
|
|
className={classNames(className, 'animate-parent')}
|
|
|
|
|
dangerouslySetInnerHTML={{ __html: emojifiedHtml }}
|
|
|
|
|
/>
|
2025-07-31 19:30:14 +02:00
|
|
|
);
|
2025-07-22 16:43:15 +02:00
|
|
|
};
|
2025-09-08 14:08:07 +02:00
|
|
|
|
|
|
|
|
export const EmojiHTML = <Element extends ElementType>(
|
|
|
|
|
props: EmojiHTMLProps<Element>,
|
|
|
|
|
) => {
|
|
|
|
|
if (isModernEmojiEnabled()) {
|
|
|
|
|
return <ModernEmojiHTML {...props} />;
|
|
|
|
|
}
|
2025-09-29 05:10:27 -04:00
|
|
|
const {
|
|
|
|
|
as: asElement,
|
|
|
|
|
htmlString,
|
|
|
|
|
extraEmojis,
|
|
|
|
|
className,
|
|
|
|
|
shallow: _,
|
|
|
|
|
...rest
|
|
|
|
|
} = props;
|
2025-09-08 14:08:07 +02:00
|
|
|
const Wrapper = asElement ?? 'div';
|
2025-09-23 10:53:14 +02:00
|
|
|
return (
|
|
|
|
|
<Wrapper
|
|
|
|
|
{...rest}
|
|
|
|
|
dangerouslySetInnerHTML={{ __html: htmlString }}
|
|
|
|
|
className={classNames(className, 'animate-parent')}
|
|
|
|
|
/>
|
|
|
|
|
);
|
2025-09-08 14:08:07 +02:00
|
|
|
};
|