-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathDataTableTitle.tsx
208 lines (185 loc) · 4.61 KB
/
DataTableTitle.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
import * as React from 'react';
import {
Animated,
GestureResponderEvent,
I18nManager,
PixelRatio,
Pressable,
StyleProp,
StyleSheet,
TextStyle,
ViewStyle,
} from 'react-native';
import color from 'color';
import { useInternalTheme } from '../../core/theming';
import type { ThemeProp } from '../../types';
import MaterialCommunityIcon from '../MaterialCommunityIcon';
import Text from '../Typography/Text';
export type Props = React.ComponentPropsWithRef<typeof Pressable> & {
/**
* Text content of the `DataTableTitle`.
*/
children: React.ReactNode;
/**
* Align the text to the right. Generally monetary or number fields are aligned to right.
*/
numeric?: boolean;
/**
* Direction of sorting. An arrow indicating the direction is displayed when this is given.
*/
sortDirection?: 'ascending' | 'descending';
/**
* The number of lines to show.
*/
numberOfLines?: number;
/**
* Function to execute on press.
*/
onPress?: (e: GestureResponderEvent) => void;
style?: StyleProp<ViewStyle>;
/**
* Text content style of the `DataTableTitle`.
*/
textStyle?: StyleProp<TextStyle>;
/**
* Specifies the largest possible scale a text font can reach.
*/
maxFontSizeMultiplier?: number;
/**
* @optional
*/
theme?: ThemeProp;
};
/**
* A component to display title in table header.
*
* ## Usage
* ```js
* import * as React from 'react';
* import { DataTable } from 'react-native-paper';
*
* const MyComponent = () => (
* <DataTable>
* <DataTable.Header>
* <DataTable.Title
* sortDirection='descending'
* >
* Dessert
* </DataTable.Title>
* <DataTable.Title numeric>Calories</DataTable.Title>
* <DataTable.Title numeric>Fat (g)</DataTable.Title>
* </DataTable.Header>
* </DataTable>
* );
*
* export default MyComponent;
* ```
*/
const DataTableTitle = ({
numeric,
children,
onPress,
sortDirection,
textStyle,
style,
theme: themeOverrides,
numberOfLines = 1,
maxFontSizeMultiplier,
...rest
}: Props) => {
const theme = useInternalTheme(themeOverrides);
const { current: spinAnim } = React.useRef<Animated.Value>(
new Animated.Value(sortDirection === 'ascending' ? 0 : 1)
);
React.useEffect(() => {
Animated.timing(spinAnim, {
toValue: sortDirection === 'ascending' ? 0 : 1,
duration: 150,
useNativeDriver: true,
}).start();
}, [sortDirection, spinAnim]);
const textColor = theme.isV3 ? theme.colors.onSurface : theme?.colors?.text;
const alphaTextColor = color(textColor).alpha(0.6).rgb().string();
const spin = spinAnim.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '180deg'],
});
const icon = sortDirection ? (
<Animated.View style={[styles.icon, { transform: [{ rotate: spin }] }]}>
<MaterialCommunityIcon
name="arrow-up"
size={16}
color={textColor}
direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'}
/>
</Animated.View>
) : null;
return (
<Pressable
disabled={!onPress}
onPress={onPress}
{...rest}
style={[styles.container, numeric && styles.right, style]}
>
{icon}
<Text
style={[
styles.cell,
// height must scale with numberOfLines
{ maxHeight: 24 * PixelRatio.getFontScale() * numberOfLines },
// if numberOfLines causes wrap, center is lost. Align directly, sensitive to numeric and RTL
numberOfLines > 1
? numeric
? I18nManager.getConstants().isRTL
? styles.leftText
: styles.rightText
: styles.centerText
: {},
sortDirection ? styles.sorted : { color: alphaTextColor },
textStyle,
]}
numberOfLines={numberOfLines}
maxFontSizeMultiplier={maxFontSizeMultiplier}
>
{children}
</Text>
</Pressable>
);
};
DataTableTitle.displayName = 'DataTable.Title';
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
alignContent: 'center',
paddingVertical: 12,
},
rightText: {
textAlign: 'right',
},
leftText: {
textAlign: 'left',
},
centerText: {
textAlign: 'center',
},
right: {
justifyContent: 'flex-end',
},
cell: {
lineHeight: 24,
fontSize: 12,
fontWeight: '500',
alignItems: 'center',
},
sorted: {
marginLeft: 8,
},
icon: {
height: 24,
justifyContent: 'center',
},
});
export default DataTableTitle;
// @component-docs ignore-next-line
export { DataTableTitle };