Adds DisplayName component (#35985)

This commit is contained in:
Echo 2025-09-04 12:09:27 +02:00 committed by GitHub
commit 42be0ca0eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 259 additions and 33 deletions

View file

@ -1,7 +1,5 @@
import type { ComponentPropsWithoutRef, ElementType } from 'react';
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
import { useEmojify } from './hooks';
import type { CustomEmojiMapArg } from './types';
@ -12,16 +10,21 @@ type EmojiHTMLProps<Element extends ElementType = 'div'> = Omit<
htmlString: string;
extraEmojis?: CustomEmojiMapArg;
as?: Element;
shallow?: boolean;
};
export const ModernEmojiHTML = <Element extends ElementType>({
export const EmojiHTML = ({
extraEmojis,
htmlString,
as: asElement, // Rename for syntax highlighting
as: Wrapper = 'div', // Rename for syntax highlighting
shallow,
...props
}: EmojiHTMLProps<Element>) => {
const Wrapper = asElement ?? 'div';
const emojifiedHtml = useEmojify(htmlString, extraEmojis);
}: EmojiHTMLProps<ElementType>) => {
const emojifiedHtml = useEmojify({
text: htmlString,
extraEmojis,
deep: !shallow,
});
if (emojifiedHtml === null) {
return null;
@ -31,14 +34,3 @@ export const ModernEmojiHTML = <Element extends ElementType>({
<Wrapper {...props} dangerouslySetInnerHTML={{ __html: emojifiedHtml }} />
);
};
export const EmojiHTML = <Element extends ElementType>(
props: EmojiHTMLProps<Element>,
) => {
if (isModernEmojiEnabled()) {
return <ModernEmojiHTML {...props} />;
}
const { as: asElement, htmlString, extraEmojis, ...rest } = props;
const Wrapper = asElement ?? 'div';
return <Wrapper {...rest} dangerouslySetInnerHTML={{ __html: htmlString }} />;
};

View file

@ -8,6 +8,7 @@ import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
import { toSupportedLocale } from './locale';
import { determineEmojiMode } from './mode';
import { emojifyElement, emojifyText } from './render';
import type {
CustomEmojiMapArg,
EmojiAppState,
@ -15,7 +16,17 @@ import type {
} from './types';
import { stringHasAnyEmoji } from './utils';
export function useEmojify(text: string, extraEmojis?: CustomEmojiMapArg) {
interface UseEmojifyOptions {
text: string;
extraEmojis?: CustomEmojiMapArg;
deep?: boolean;
}
export function useEmojify({
text,
extraEmojis,
deep = true,
}: UseEmojifyOptions) {
const [emojifiedText, setEmojifiedText] = useState<string | null>(null);
const appState = useEmojiAppState();
@ -36,17 +47,23 @@ export function useEmojify(text: string, extraEmojis?: CustomEmojiMapArg) {
const emojify = useCallback(
async (input: string) => {
const wrapper = document.createElement('div');
wrapper.innerHTML = input;
const { emojifyElement } = await import('./render');
const result = await emojifyElement(wrapper, appState, extra);
let result: string | null = null;
if (deep) {
const wrapper = document.createElement('div');
wrapper.innerHTML = input;
if (await emojifyElement(wrapper, appState, extra)) {
result = wrapper.innerHTML;
}
} else {
result = await emojifyText(text, appState, extra);
}
if (result) {
setEmojifiedText(result.innerHTML);
setEmojifiedText(result);
} else {
setEmojifiedText(input);
}
},
[appState, extra],
[appState, deep, extra, text],
);
useLayoutEffect(() => {
if (isModernEmojiEnabled() && !!text.trim() && stringHasAnyEmoji(text)) {