import React from 'react'; import { Animated } from 'react-native'; import { Text } from '../Text'; import { Ripple } from '../Ripple'; import useTheme from '../../context/theme/useTheme'; import { getOpacity } from '../../utils'; import type { BadgeProps } from './types'; import { Box } from '../Box'; import { SizeType } from '../../@types/input'; import { SxProps } from '../../lib/styleDictionary'; import { FontSizesProps } from '../../context/theme/types'; import createSxStyle from '../../lib/sx'; export const Badge: React.FC = ({ content, style, isInvisible, enableShadow, children, onPress, borderColor, offset, sx, isPressable = !!onPress, placement = 'top-right', bold = true, size = children ? 'small' : 'middle', bordered = true, background = 'border', variant = 'default', type = 'rounded', color = variant === 'flat' ? background : 'white' }) => { const theme = useTheme(); const { colors, isDark, fontSizes } = useTheme(); const placementStyle = placementStyles[placement]; const fontSize: keyof FontSizesProps = fonts[size]; const isFlat = React.useMemo(() => variant === 'flat', [variant]); const backgroundColor = React.useMemo(() => { if (isFlat) { return getOpacity(colors.get(background), 0.3); } return background; }, [isFlat, colors, background]); const borderInternalColor = React.useMemo(() => { if (!bordered) return 'transparent'; if (borderColor) return borderColor; if (isFlat) return 'transparent'; return 'background'; }, [bordered, isFlat, borderColor]); const Component = React.useMemo(() => { if (isPressable) { return Ripple; } return Box; }, [isPressable]); return ( {!isInvisible && ( {!!content && ( {content} )} )} {children} ); }; const sizesPadding: Record = { small: 0.4, middle: 0.65, large: 1, xLarge: 1.2 }; const fonts: Record = { small: 'xxs', middle: 'xs', large: 'md', xLarge: 'lg' }; const placementStyles: Record = { 'top-right': { alignSelf: 'flex-start', right: 0, top: 0 }, 'top-left': { alignSelf: 'flex-end', left: 0, top: 0 }, 'bottom-right': { alignSelf: 'flex-start', right: 0, bottom: 0 }, 'bottom-left': { alignSelf: 'flex-end', left: 0, bottom: 0 } };