template_0205
This commit is contained in:
118
RN_TEMPLATE/app/components/Text.tsx
Normal file
118
RN_TEMPLATE/app/components/Text.tsx
Normal file
@@ -0,0 +1,118 @@
|
||||
import { ReactNode, forwardRef, ForwardedRef } from "react"
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { StyleProp, Text as RNText, TextProps as RNTextProps, TextStyle } from "react-native"
|
||||
import { TOptions } from "i18next"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { isRTL, TxKeyPath } from "@/i18n"
|
||||
import { useAppTheme } from "@/theme/context"
|
||||
import type { ThemedStyle, ThemedStyleArray } from "@/theme/types"
|
||||
import { typography } from "@/theme/typography"
|
||||
import { fs } from "@/utils/responsive"
|
||||
|
||||
type Sizes = keyof typeof $sizeStyles
|
||||
type Weights = keyof typeof typography.primary
|
||||
type Presets = "default" | "bold" | "heading" | "subheading" | "formLabel" | "formHelper"
|
||||
|
||||
export interface TextProps extends RNTextProps {
|
||||
/**
|
||||
* Text which is looked up via i18n.
|
||||
*/
|
||||
tx?: TxKeyPath
|
||||
/**
|
||||
* The text to display if not using `tx` or nested components.
|
||||
*/
|
||||
text?: string
|
||||
/**
|
||||
* Optional options to pass to i18n. Useful for interpolation
|
||||
* as well as explicitly setting locale or translation fallbacks.
|
||||
*/
|
||||
txOptions?: TOptions
|
||||
/**
|
||||
* An optional style override useful for padding & margin.
|
||||
*/
|
||||
style?: StyleProp<TextStyle>
|
||||
/**
|
||||
* One of the different types of text presets.
|
||||
*/
|
||||
preset?: Presets
|
||||
/**
|
||||
* Text weight modifier.
|
||||
*/
|
||||
weight?: Weights
|
||||
/**
|
||||
* Text size modifier.
|
||||
*/
|
||||
size?: Sizes
|
||||
/**
|
||||
* Children components.
|
||||
*/
|
||||
children?: ReactNode
|
||||
}
|
||||
|
||||
/**
|
||||
* For your text displaying needs.
|
||||
* This component is a HOC over the built-in React Native one.
|
||||
* @see [Documentation and Examples]{@link https://docs.infinite.red/ignite-cli/boilerplate/app/components/Text/}
|
||||
* @param {TextProps} props - The props for the `Text` component.
|
||||
* @returns {JSX.Element} The rendered `Text` component.
|
||||
*/
|
||||
export const Text = forwardRef(function Text(props: TextProps, ref: ForwardedRef<RNText>) {
|
||||
const { weight, size, tx, txOptions, text, children, style: $styleOverride, ...rest } = props
|
||||
const { themed } = useAppTheme()
|
||||
const { t } = useTranslation()
|
||||
|
||||
const i18nText = tx && t(tx, txOptions)
|
||||
const content = i18nText || text || children
|
||||
|
||||
const preset: Presets = props.preset ?? "default"
|
||||
const $styles: StyleProp<TextStyle> = [
|
||||
$rtlStyle,
|
||||
themed($presets[preset]),
|
||||
weight && $fontWeightStyles[weight],
|
||||
size && $sizeStyles[size],
|
||||
$styleOverride,
|
||||
]
|
||||
|
||||
return (
|
||||
<RNText {...rest} style={$styles} ref={ref}>
|
||||
{content}
|
||||
</RNText>
|
||||
)
|
||||
})
|
||||
|
||||
const $sizeStyles = {
|
||||
xxl: { fontSize: fs(36), lineHeight: fs(44) } satisfies TextStyle,
|
||||
xl: { fontSize: fs(24), lineHeight: fs(34) } satisfies TextStyle,
|
||||
lg: { fontSize: fs(20), lineHeight: fs(32) } satisfies TextStyle,
|
||||
md: { fontSize: fs(18), lineHeight: fs(26) } satisfies TextStyle,
|
||||
sm: { fontSize: fs(16), lineHeight: fs(24) } satisfies TextStyle,
|
||||
xs: { fontSize: fs(14), lineHeight: fs(21) } satisfies TextStyle,
|
||||
xxs: { fontSize: fs(12), lineHeight: fs(18) } satisfies TextStyle,
|
||||
}
|
||||
|
||||
const $fontWeightStyles = Object.entries(typography.primary).reduce((acc, [weight, fontFamily]) => {
|
||||
return { ...acc, [weight]: { fontFamily } }
|
||||
}, {}) as Record<Weights, TextStyle>
|
||||
|
||||
const $baseStyle: ThemedStyle<TextStyle> = (theme) => ({
|
||||
...$sizeStyles.sm,
|
||||
...$fontWeightStyles.normal,
|
||||
color: theme.colors.text,
|
||||
})
|
||||
|
||||
const $presets: Record<Presets, ThemedStyleArray<TextStyle>> = {
|
||||
default: [$baseStyle],
|
||||
bold: [$baseStyle, { ...$fontWeightStyles.bold }],
|
||||
heading: [
|
||||
$baseStyle,
|
||||
{
|
||||
...$sizeStyles.xxl,
|
||||
...$fontWeightStyles.bold,
|
||||
},
|
||||
],
|
||||
subheading: [$baseStyle, { ...$sizeStyles.lg, ...$fontWeightStyles.medium }],
|
||||
formLabel: [$baseStyle, { ...$fontWeightStyles.medium }],
|
||||
formHelper: [$baseStyle, { ...$sizeStyles.sm, ...$fontWeightStyles.normal }],
|
||||
}
|
||||
const $rtlStyle: TextStyle = isRTL ? { writingDirection: "rtl" } : {}
|
||||
Reference in New Issue
Block a user