-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathIOText.tsx
154 lines (141 loc) · 4.51 KB
/
IOText.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import React, { ComponentProps, forwardRef, useMemo } from "react";
import {
ColorValue,
GestureResponderEvent,
Text,
TextStyle,
View
} from "react-native";
import { IOColors, useIOTheme } from "../../core";
import { useBoldTextEnabled } from "../../utils/accessibility";
import {
IOFontFamily,
IOFontWeight,
IOMaxFontSizeMultiplier,
makeFontStyleObject
} from "../../utils/fonts";
/**
* We exclude all of the following props when we define a new
* typographic style in which all of these visual attributes
* are already defined.
*/
export type IOTextStyle = Omit<
TextStyle,
"fontFamily" | "fontSize" | "fontWeight" | "lineHeight" | "fontStyle"
>;
export type TypographicStyleProps = Omit<
IOTextProps,
"style" | "font" | "size" | "weight" | "color" | "lineHeight" | "fontStyle"
> & { textStyle?: IOTextStyle; style?: IOTextStyle } & {
color?: IOTextBaseProps["color"];
};
/**
* The specific properties needed to calculate the font style using {@link makeFontStyleObject} (these information
* cannot be included in the default StyleProp<TextStyle>
*/
type IOTextBaseProps = {
size?: number;
weight?: IOFontWeight;
color?: IOColors;
font?: IOFontFamily;
lineHeight?: TextStyle["lineHeight"];
fontStyle?: TextStyle["fontStyle"];
textStyle?: IOTextStyle;
style?: IOTextStyle;
};
type IOTextExcludedProps = Omit<ComponentProps<typeof Text>, "style">;
export type IOTextProps = IOTextBaseProps & IOTextExcludedProps;
/**
* Extend `TypographicStyleProps` with extra props for styles that
* can be used as links
*/
export type TypographicStyleAsLinkProps =
| {
color?: never;
asLink: true;
onPress: (event: GestureResponderEvent) => void;
}
| { color?: IOColors; asLink?: false };
/**
* Decorate the function {@link makeFontStyleObject} with the additional color calculation.
* @param color A value key from {@link IOColors}, transformed here in {@link ColorValue}
* @param args the args of the function {@link makeFontStyleObject}
*/
const calculateTextStyle = (
color: IOColors,
...args: Parameters<typeof makeFontStyleObject>
) => ({
...makeFontStyleObject(...args),
color: IOColors[color]
});
/**
* `IOText` is the core Typography component used to render a text.
* It accepts all the default text style `StyleProp<TextStyle>` (excluding the ones already applied) in addition with {@link IOTextBaseProps}
* used to calculate at runtime the platform-dependent styles.
* @param props
* @constructor
*/
export const IOText = forwardRef<View, IOTextProps>(
(
{
color,
size,
font,
lineHeight,
weight,
fontStyle,
textStyle,
style,
children,
allowFontScaling = true,
maxFontSizeMultiplier,
...props
},
ref
) => {
const theme = useIOTheme();
const boldEnabled = useBoldTextEnabled();
const computedStyleObj = useMemo(
() =>
calculateTextStyle(
color ?? theme["textBody-default"],
size,
font,
lineHeight,
weight,
fontStyle,
boldEnabled
),
[color, theme, size, font, lineHeight, weight, fontStyle, boldEnabled]
);
/* In some cases, for example when we use color transitions with
`reanimated` we need to manage chromatic values as `ColorValue`
or `string` (not `IOColors`). So we keep a way to override
the the `color' attribute without giving the ability to
override all other all other typographic attributes
through the `style' prop. */
const fontStyleObj = style?.color
? [{ ...computedStyleObj, color: style?.color }]
: computedStyleObj;
/* Some typographic styles like `H5` have certain `TextStyle` properties
like `textTransform` or `letterSpacing` that we want to apply to the text.
We use the `textStyle` prop to pass these properties to the `IOText`
component and preserve the ability to define the `style` prop as well.
The `style` prop is the last one to be applied, so we can properly
override the `color` attribute.
*/
const styleObj = style
? [textStyle ?? {}, fontStyleObj ?? {}, style]
: [textStyle ?? {}, fontStyleObj ?? {}];
/* Accessible typography based on the `fontScale` parameter */
const accessibleFontSizeProps: ComponentProps<typeof Text> = {
allowFontScaling,
maxFontSizeMultiplier: maxFontSizeMultiplier ?? IOMaxFontSizeMultiplier
};
return (
<Text ref={ref} style={styleObj} {...props} {...accessibleFontSizeProps}>
{children}
</Text>
);
}
);