mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-21 12:46:42 +02:00
Applied formatting to 1487+ files using pnpm format:write - TypeScript/JavaScript files - Svelte components - Astro pages - JSON configs - Markdown docs 13 files still need manual review (Astro JSX comments)
163 lines
3.2 KiB
TypeScript
163 lines
3.2 KiB
TypeScript
import { forwardRef } from 'react';
|
|
import { Text as RNText, TextProps as RNTextProps, TextStyle } from 'react-native';
|
|
import { useTheme } from '~/contexts/ThemeContext';
|
|
|
|
type TextVariant =
|
|
| 'h1'
|
|
| 'h2'
|
|
| 'h3'
|
|
| 'h4'
|
|
| 'title'
|
|
| 'body'
|
|
| 'bodyLarge'
|
|
| 'bodySmall'
|
|
| 'caption'
|
|
| 'label'
|
|
| 'button';
|
|
|
|
type TextColor = 'primary' | 'secondary' | 'tertiary' | 'inverse' | 'error' | 'success' | 'warning';
|
|
|
|
type TextWeight = 'regular' | 'medium' | 'semibold' | 'bold';
|
|
|
|
type TextProps = {
|
|
variant?: TextVariant;
|
|
color?: TextColor;
|
|
weight?: TextWeight;
|
|
align?: 'left' | 'center' | 'right';
|
|
children?: React.ReactNode;
|
|
} & RNTextProps;
|
|
|
|
export const Text = forwardRef<RNText, TextProps>(
|
|
(
|
|
{ variant = 'body', color = 'primary', weight, align = 'left', style, children, ...props },
|
|
ref
|
|
) => {
|
|
const { theme } = useTheme();
|
|
|
|
// Variant styles
|
|
const getVariantStyle = (): TextStyle => {
|
|
switch (variant) {
|
|
case 'h1':
|
|
return {
|
|
fontSize: 32,
|
|
fontWeight: '700',
|
|
lineHeight: 40,
|
|
};
|
|
case 'h2':
|
|
return {
|
|
fontSize: 28,
|
|
fontWeight: '700',
|
|
lineHeight: 36,
|
|
};
|
|
case 'h3':
|
|
return {
|
|
fontSize: 24,
|
|
fontWeight: '600',
|
|
lineHeight: 32,
|
|
};
|
|
case 'h4':
|
|
return {
|
|
fontSize: 20,
|
|
fontWeight: '600',
|
|
lineHeight: 28,
|
|
};
|
|
case 'title':
|
|
return {
|
|
fontSize: 44,
|
|
fontWeight: '800',
|
|
lineHeight: 52,
|
|
};
|
|
case 'bodyLarge':
|
|
return {
|
|
fontSize: 18,
|
|
fontWeight: '400',
|
|
lineHeight: 28,
|
|
};
|
|
case 'body':
|
|
return {
|
|
fontSize: 16,
|
|
fontWeight: '400',
|
|
lineHeight: 24,
|
|
};
|
|
case 'bodySmall':
|
|
return {
|
|
fontSize: 14,
|
|
fontWeight: '400',
|
|
lineHeight: 20,
|
|
};
|
|
case 'caption':
|
|
return {
|
|
fontSize: 12,
|
|
fontWeight: '400',
|
|
lineHeight: 16,
|
|
};
|
|
case 'label':
|
|
return {
|
|
fontSize: 14,
|
|
fontWeight: '500',
|
|
lineHeight: 20,
|
|
};
|
|
case 'button':
|
|
return {
|
|
fontSize: 16,
|
|
fontWeight: '600',
|
|
lineHeight: 24,
|
|
};
|
|
default:
|
|
return {};
|
|
}
|
|
};
|
|
|
|
// Color mapping
|
|
const getTextColor = (): string => {
|
|
switch (color) {
|
|
case 'primary':
|
|
return theme.colors.text.primary;
|
|
case 'secondary':
|
|
return theme.colors.text.secondary;
|
|
case 'tertiary':
|
|
return theme.colors.text.tertiary;
|
|
case 'inverse':
|
|
return theme.colors.text.inverse;
|
|
case 'error':
|
|
return theme.colors.error;
|
|
case 'success':
|
|
return theme.colors.success;
|
|
case 'warning':
|
|
return theme.colors.warning;
|
|
default:
|
|
return theme.colors.text.primary;
|
|
}
|
|
};
|
|
|
|
// Weight mapping
|
|
const getFontWeight = (): TextStyle['fontWeight'] => {
|
|
if (weight) {
|
|
const weightMap: Record<TextWeight, TextStyle['fontWeight']> = {
|
|
regular: '400',
|
|
medium: '500',
|
|
semibold: '600',
|
|
bold: '700',
|
|
};
|
|
return weightMap[weight];
|
|
}
|
|
return undefined;
|
|
};
|
|
|
|
const textStyle: TextStyle = {
|
|
...getVariantStyle(),
|
|
color: getTextColor(),
|
|
textAlign: align,
|
|
...(weight && { fontWeight: getFontWeight() }),
|
|
...(style as TextStyle),
|
|
};
|
|
|
|
return (
|
|
<RNText ref={ref} style={textStyle} {...props}>
|
|
{children}
|
|
</RNText>
|
|
);
|
|
}
|
|
);
|
|
|
|
Text.displayName = 'Text';
|