import React, { memo, forwardRef, useRef } from 'react'; import { usePropsResolution } from '../../../hooks/useThemeProps'; import type { ITextProps } from './types'; import { useHover } from '@react-native-aria/interactions'; import { mergeRefs } from '../../../utils/mergeRefs'; import { makeStyledComponent } from '../../../utils/styled'; import { useResolvedFontFamily } from '../../../hooks/useResolvedFontFamily'; import { Platform, Text as NativeText } from 'react-native'; import { useHasResponsiveProps } from '../../../hooks/useHasResponsiveProps'; const StyledText = makeStyledComponent(NativeText); // To have a RN compatible behaviour, we'll inherit parent text styles as base style const TextAncestorContext = React.createContext(false); const Text = ({ children, ...props }: ITextProps, ref: any) => { const hasTextAncestor = React.useContext(TextAncestorContext); const { isTruncated, noOfLines, bold, italic, sub, highlight, underline, strikeThrough, fontFamily: propFontFamily, fontWeight: propFontWeight, fontStyle: propFontStyle, _hover, fontSize, numberOfLines, ...resolvedProps } = usePropsResolution( 'Text', props, {}, { resolveResponsively: ['noOfLines', 'numberOfLines'], // We override the component base theme if text has an ancestor. componentTheme: hasTextAncestor ? {} : undefined, } ); const _ref = useRef(null); // TODO: might have to add this condition const { isHovered } = useHover({}, _hover ? _ref : null); // const { isHovered } = useHover({}, _ref); let fontFamily = propFontFamily; const fontStyle = italic ? 'italic' : propFontStyle; const fontWeight = bold ? 'bold' : propFontWeight; let resolvedFontFamily; resolvedFontFamily = useResolvedFontFamily({ fontFamily, fontWeight: fontWeight ?? (hasTextAncestor ? undefined : 400), fontStyle: fontStyle ?? (hasTextAncestor ? undefined : 'normal'), }); if (resolvedFontFamily) { fontFamily = resolvedFontFamily; } // Need to apply fontWeight & fontStyle on web if (Platform.OS === 'web') { if (resolvedFontFamily) { fontFamily = resolvedFontFamily.fontFamily; } resolvedFontFamily = { fontFamily, fontWeight: fontWeight ?? (hasTextAncestor ? undefined : 400), fontStyle: fontStyle ?? (hasTextAncestor ? undefined : 'normal'), }; } //TODO: refactor for responsive prop if (useHasResponsiveProps(props)) { return null; } const propsToSpread = { ...resolvedProps, numberOfLines: numberOfLines || noOfLines ? numberOfLines || noOfLines : isTruncated ? 1 : undefined, ...resolvedFontFamily, bg: highlight ? 'warning.300' : resolvedProps.bg, textDecorationLine: underline && strikeThrough ? 'underline line-through' : underline ? 'underline' : strikeThrough ? 'line-through' : resolvedProps.textDecorationLine, fontSize: sub ? 10 : fontSize, ref: mergeRefs([ref, _ref]), ...(isHovered && _hover), }; return hasTextAncestor ? ( {children} ) : ( {children} ); }; export default memo(forwardRef(Text)); export type { ITextProps };