Skip to content

Commit

Permalink
TextShadow: Add support for AnimatedText
Browse files Browse the repository at this point in the history
  • Loading branch information
christianbaroni committed Nov 24, 2024
1 parent fda58dc commit 082ac3c
Showing 1 changed file with 34 additions and 15 deletions.
49 changes: 34 additions & 15 deletions src/design-system/components/TextShadow/TextShadow.tsx
Original file line number Diff line number Diff line change
@@ -1,62 +1,81 @@
import React, { ReactElement, useMemo } from 'react';
import { StyleProp, TextStyle, View, ViewStyle } from 'react-native';
import { View } from 'react-native';
import { IS_IOS } from '@/env';
import { opacity } from '@/__swaps__/utils/swaps';
import { useColorMode } from '../../color/ColorMode';
import { useForegroundColor } from '../../color/useForegroundColor';
import { AnimatedText, AnimatedTextProps } from '../Text/AnimatedText';
import { Text, TextProps } from '../Text/Text';

export interface TextShadowProps {
blur?: number;
children: ReactElement<TextProps>;
children: ReactElement<TextProps | AnimatedTextProps>;
color?: string;
containerStyle?: StyleProp<ViewStyle>;
disabled?: boolean;
enableInLightMode?: boolean;
enableOnAndroid?: boolean;
shadowOpacity?: number;
textStyle?: StyleProp<TextStyle>;
x?: number;
y?: number;
}

const isAnimatedTextChild = (child: ReactElement<TextProps | AnimatedTextProps>): child is ReactElement<AnimatedTextProps> => {
return child.type === AnimatedText;
};

export const TextShadow = ({
blur = 16,
children,
color,
containerStyle,
disabled,
enableInLightMode,
enableOnAndroid,
shadowOpacity = 0.6,
textStyle,
x = 0,
y = 0,
}: TextShadowProps) => {
const { isDarkMode } = useColorMode();

const inferredTextColor = useForegroundColor(children.props.color ?? 'label');
const inferredTextSize = children.props.size || '17pt';
const isAnimatedText = isAnimatedTextChild(children);

const [internalContainerStyle, internalTextStyle] = useMemo(() => {
const [containerStyle, internalTextStyle] = useMemo(() => {
const extraSpaceForShadow = blur + Math.max(Math.abs(x), Math.abs(y));
return [
// Container style
{ margin: -extraSpaceForShadow },

// Text style
{
...(isAnimatedText
? {
marginBottom: -extraSpaceForShadow,
marginLeft: -extraSpaceForShadow,
marginRight: -extraSpaceForShadow,
marginTop: -extraSpaceForShadow,
}
: {}),
padding: extraSpaceForShadow,
textShadowColor: opacity(color || inferredTextColor, shadowOpacity),
textShadowOffset: { width: x, height: y },
textShadowRadius: blur,
padding: extraSpaceForShadow,
},
];
}, [blur, color, inferredTextColor, shadowOpacity, x, y]);
}, [blur, color, inferredTextColor, isAnimatedText, shadowOpacity, x, y]);

return !disabled && (IS_IOS || enableOnAndroid) && (isDarkMode || enableInLightMode) ? (
<View style={[containerStyle, internalContainerStyle]}>
<Text color={{ custom: 'transparent' }} size={inferredTextSize} style={[textStyle, internalTextStyle]} weight="bold">
{children}
</Text>
</View>
<>
{isAnimatedText ? (
// eslint-disable-next-line react/jsx-props-no-spreading
<AnimatedText {...children.props} style={[children.props.style, internalTextStyle]} />
) : (
<View style={containerStyle}>
<Text color={{ custom: 'transparent' }} size={children.props.size} style={internalTextStyle} weight={children.props.weight}>
{children}
</Text>
</View>
)}
</>
) : (
<>{children}</>
);
Expand Down

0 comments on commit 082ac3c

Please sign in to comment.