mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-15 08:48:53 +00:00
[Glitch] Emoji Component
Port c12b8f51c1 to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
108
app/javascript/flavours/glitch/components/emoji/context.tsx
Normal file
108
app/javascript/flavours/glitch/components/emoji/context.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
import type { MouseEventHandler, PropsWithChildren } from 'react';
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { cleanExtraEmojis } from '@/flavours/glitch/features/emoji/normalize';
|
||||
import { autoPlayGif } from '@/flavours/glitch/initial_state';
|
||||
import { polymorphicForwardRef } from '@/types/polymorphic';
|
||||
import type {
|
||||
CustomEmojiMapArg,
|
||||
ExtraCustomEmojiMap,
|
||||
} from 'flavours/glitch/features/emoji/types';
|
||||
|
||||
// Animation context
|
||||
export const AnimateEmojiContext = createContext<boolean | null>(null);
|
||||
|
||||
// Polymorphic provider component
|
||||
type AnimateEmojiProviderProps = Required<PropsWithChildren> & {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const AnimateEmojiProvider = polymorphicForwardRef<
|
||||
'div',
|
||||
AnimateEmojiProviderProps
|
||||
>(
|
||||
(
|
||||
{
|
||||
children,
|
||||
as: Wrapper = 'div',
|
||||
className,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const [animate, setAnimate] = useState(autoPlayGif ?? false);
|
||||
|
||||
const handleEnter: MouseEventHandler<HTMLDivElement> = useCallback(
|
||||
(event) => {
|
||||
onMouseEnter?.(event);
|
||||
if (!autoPlayGif) {
|
||||
setAnimate(true);
|
||||
}
|
||||
},
|
||||
[onMouseEnter],
|
||||
);
|
||||
const handleLeave: MouseEventHandler<HTMLDivElement> = useCallback(
|
||||
(event) => {
|
||||
onMouseLeave?.(event);
|
||||
if (!autoPlayGif) {
|
||||
setAnimate(false);
|
||||
}
|
||||
},
|
||||
[onMouseLeave],
|
||||
);
|
||||
|
||||
// If there's a parent context or GIFs autoplay, we don't need handlers.
|
||||
const parentContext = useContext(AnimateEmojiContext);
|
||||
if (parentContext !== null || autoPlayGif === true) {
|
||||
return (
|
||||
<Wrapper
|
||||
{...props}
|
||||
className={classNames(className, 'animate-parent')}
|
||||
ref={ref}
|
||||
>
|
||||
{children}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Wrapper
|
||||
{...props}
|
||||
className={classNames(className, 'animate-parent')}
|
||||
onMouseEnter={handleEnter}
|
||||
onMouseLeave={handleLeave}
|
||||
ref={ref}
|
||||
>
|
||||
<AnimateEmojiContext.Provider value={animate}>
|
||||
{children}
|
||||
</AnimateEmojiContext.Provider>
|
||||
</Wrapper>
|
||||
);
|
||||
},
|
||||
);
|
||||
AnimateEmojiProvider.displayName = 'AnimateEmojiProvider';
|
||||
|
||||
// Handle custom emoji
|
||||
export const CustomEmojiContext = createContext<ExtraCustomEmojiMap>({});
|
||||
|
||||
export const CustomEmojiProvider = ({
|
||||
children,
|
||||
emojis: rawEmojis,
|
||||
}: PropsWithChildren<{ emojis?: CustomEmojiMapArg }>) => {
|
||||
const emojis = useMemo(() => cleanExtraEmojis(rawEmojis) ?? {}, [rawEmojis]);
|
||||
return (
|
||||
<CustomEmojiContext.Provider value={emojis}>
|
||||
{children}
|
||||
</CustomEmojiContext.Provider>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user