@hero-design/rn 7.1.1 → 7.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/.eslintrc.json +4 -3
  2. package/es/index.js +283 -113
  3. package/lib/index.js +282 -111
  4. package/package.json +4 -3
  5. package/playground/components/BottomNavigation.tsx +69 -0
  6. package/playground/components/Card.tsx +149 -70
  7. package/playground/index.tsx +3 -0
  8. package/rollup.config.js +1 -1
  9. package/src/components/BottomNavigation/StyledBottomNavigation.tsx +58 -0
  10. package/src/components/BottomNavigation/__tests__/BottomNavigation.spec.tsx +95 -0
  11. package/src/components/BottomNavigation/__tests__/__snapshots__/BottomNavigation.spec.tsx.snap +315 -0
  12. package/src/components/BottomNavigation/index.tsx +169 -0
  13. package/src/components/Icon/utils.ts +6 -0
  14. package/src/components/Typography/Text/StyledText.tsx +5 -1
  15. package/src/components/Typography/Text/index.tsx +1 -1
  16. package/src/index.ts +2 -0
  17. package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +16 -0
  18. package/src/theme/components/bottomNavigation.ts +23 -0
  19. package/src/theme/components/typography.ts +1 -0
  20. package/src/theme/index.ts +3 -0
  21. package/src/utils/helpers.ts +4 -0
  22. package/types/playground/components/BottomNavigation.d.ts +2 -0
  23. package/types/src/components/BottomNavigation/StyledBottomNavigation.d.ts +17 -0
  24. package/types/src/components/BottomNavigation/__tests__/BottomNavigation.spec.d.ts +1 -0
  25. package/types/src/components/BottomNavigation/index.d.ts +40 -0
  26. package/types/src/components/Icon/utils.d.ts +2 -0
  27. package/types/src/components/Typography/Text/StyledText.d.ts +1 -1
  28. package/types/src/components/Typography/Text/index.d.ts +1 -1
  29. package/types/src/index.d.ts +2 -1
  30. package/types/src/theme/components/bottomNavigation.d.ts +17 -0
  31. package/types/src/theme/components/typography.d.ts +1 -0
  32. package/types/src/theme/index.d.ts +2 -0
  33. package/types/src/utils/helpers.d.ts +2 -0
  34. package/.expo/README.md +0 -15
  35. package/.expo/packager-info.json +0 -10
  36. package/.expo/settings.json +0 -10
@@ -0,0 +1,315 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`BottomNavigation renders correctly 1`] = `
4
+ <RNCSafeAreaProvider
5
+ onInsetsChange={[Function]}
6
+ style={
7
+ Array [
8
+ Object {
9
+ "flex": 1,
10
+ },
11
+ undefined,
12
+ ]
13
+ }
14
+ >
15
+ <View
16
+ style={
17
+ Object {
18
+ "flexBasis": 0,
19
+ "flexGrow": 1,
20
+ "flexShrink": 1,
21
+ "overflow": "hidden",
22
+ }
23
+ }
24
+ >
25
+ <View
26
+ style={
27
+ Object {
28
+ "flexBasis": 0,
29
+ "flexGrow": 1,
30
+ "flexShrink": 1,
31
+ }
32
+ }
33
+ >
34
+ <View
35
+ accessibilityElementsHidden={false}
36
+ collapsable={false}
37
+ importantForAccessibility="auto"
38
+ pointerEvents="auto"
39
+ removeClippedSubviews={false}
40
+ style={
41
+ Object {
42
+ "display": "flex",
43
+ "flexBasis": 0,
44
+ "flexGrow": 1,
45
+ "flexShrink": 1,
46
+ }
47
+ }
48
+ testID="route-screen-home"
49
+ themeVisibility={true}
50
+ >
51
+ <Text>
52
+ Home Screen
53
+ </Text>
54
+ </View>
55
+ </View>
56
+ <View
57
+ style={
58
+ Object {
59
+ "backgroundColor": "#ffffff",
60
+ "elevation": 10,
61
+ "height": 72,
62
+ "paddingBottom": 0,
63
+ "paddingLeft": 0,
64
+ "paddingRight": 0,
65
+ "shadowColor": "#292a2b",
66
+ "shadowOffset": Object {
67
+ "height": 3,
68
+ "width": 0,
69
+ },
70
+ "shadowOpacity": 0.27,
71
+ "shadowRadius": 4.65,
72
+ }
73
+ }
74
+ themeInsets={
75
+ Object {
76
+ "bottom": 0,
77
+ "left": 0,
78
+ "right": 0,
79
+ "top": 0,
80
+ }
81
+ }
82
+ >
83
+ <View
84
+ style={
85
+ Object {
86
+ "alignItems": "center",
87
+ "flexBasis": 0,
88
+ "flexDirection": "row",
89
+ "flexGrow": 1,
90
+ "flexShrink": 1,
91
+ "overflow": "hidden",
92
+ }
93
+ }
94
+ >
95
+ <View
96
+ accessible={true}
97
+ focusable={true}
98
+ onClick={[Function]}
99
+ onResponderGrant={[Function]}
100
+ onResponderMove={[Function]}
101
+ onResponderRelease={[Function]}
102
+ onResponderTerminate={[Function]}
103
+ onResponderTerminationRequest={[Function]}
104
+ onStartShouldSetResponder={[Function]}
105
+ style={
106
+ Object {
107
+ "alignItems": "center",
108
+ "flexBasis": 0,
109
+ "flexGrow": 1,
110
+ "flexShrink": 1,
111
+ }
112
+ }
113
+ >
114
+ <HeroIcon
115
+ name="home"
116
+ style={
117
+ Object {
118
+ "color": "#7622d7",
119
+ "fontSize": 24,
120
+ }
121
+ }
122
+ testID="hero-icon-home"
123
+ themeIntent="primary"
124
+ themeSize="medium"
125
+ />
126
+ <Text
127
+ numberOfLines={1}
128
+ style={
129
+ Array [
130
+ Object {
131
+ "color": "#7622d7",
132
+ "fontSize": 12,
133
+ "fontWeight": "600",
134
+ "letterSpacing": 0.36,
135
+ "lineHeight": 20,
136
+ },
137
+ Object {
138
+ "marginTop": 4,
139
+ },
140
+ ]
141
+ }
142
+ themeFontSize="small"
143
+ themeFontWeight="semi-bold"
144
+ themeIntent="primary"
145
+ >
146
+ Home
147
+ </Text>
148
+ </View>
149
+ <View
150
+ accessible={true}
151
+ focusable={true}
152
+ onClick={[Function]}
153
+ onResponderGrant={[Function]}
154
+ onResponderMove={[Function]}
155
+ onResponderRelease={[Function]}
156
+ onResponderTerminate={[Function]}
157
+ onResponderTerminationRequest={[Function]}
158
+ onStartShouldSetResponder={[Function]}
159
+ style={
160
+ Object {
161
+ "alignItems": "center",
162
+ "flexBasis": 0,
163
+ "flexGrow": 1,
164
+ "flexShrink": 1,
165
+ }
166
+ }
167
+ >
168
+ <HeroIcon
169
+ name="speaker-outlined"
170
+ style={
171
+ Object {
172
+ "color": "#292a2b",
173
+ "fontSize": 24,
174
+ }
175
+ }
176
+ testID="hero-icon-speaker-outlined"
177
+ themeIntent="text"
178
+ themeSize="medium"
179
+ />
180
+ <Text
181
+ numberOfLines={1}
182
+ style={
183
+ Array [
184
+ Object {
185
+ "color": "#292a2b",
186
+ "fontSize": 12,
187
+ "fontWeight": "600",
188
+ "letterSpacing": 0.36,
189
+ "lineHeight": 20,
190
+ },
191
+ Object {
192
+ "marginTop": 4,
193
+ },
194
+ ]
195
+ }
196
+ themeFontSize="small"
197
+ themeFontWeight="semi-bold"
198
+ themeIntent="body"
199
+ >
200
+ Feed
201
+ </Text>
202
+ </View>
203
+ <View
204
+ accessible={true}
205
+ focusable={true}
206
+ onClick={[Function]}
207
+ onResponderGrant={[Function]}
208
+ onResponderMove={[Function]}
209
+ onResponderRelease={[Function]}
210
+ onResponderTerminate={[Function]}
211
+ onResponderTerminationRequest={[Function]}
212
+ onStartShouldSetResponder={[Function]}
213
+ style={
214
+ Object {
215
+ "alignItems": "center",
216
+ "flexBasis": 0,
217
+ "flexGrow": 1,
218
+ "flexShrink": 1,
219
+ }
220
+ }
221
+ >
222
+ <HeroIcon
223
+ name="bell-outlined"
224
+ style={
225
+ Object {
226
+ "color": "#292a2b",
227
+ "fontSize": 24,
228
+ }
229
+ }
230
+ testID="hero-icon-bell-outlined"
231
+ themeIntent="text"
232
+ themeSize="medium"
233
+ />
234
+ <Text
235
+ numberOfLines={1}
236
+ style={
237
+ Array [
238
+ Object {
239
+ "color": "#292a2b",
240
+ "fontSize": 12,
241
+ "fontWeight": "600",
242
+ "letterSpacing": 0.36,
243
+ "lineHeight": 20,
244
+ },
245
+ Object {
246
+ "marginTop": 4,
247
+ },
248
+ ]
249
+ }
250
+ themeFontSize="small"
251
+ themeFontWeight="semi-bold"
252
+ themeIntent="body"
253
+ >
254
+ Alerts
255
+ </Text>
256
+ </View>
257
+ <View
258
+ accessible={true}
259
+ focusable={true}
260
+ onClick={[Function]}
261
+ onResponderGrant={[Function]}
262
+ onResponderMove={[Function]}
263
+ onResponderRelease={[Function]}
264
+ onResponderTerminate={[Function]}
265
+ onResponderTerminationRequest={[Function]}
266
+ onStartShouldSetResponder={[Function]}
267
+ style={
268
+ Object {
269
+ "alignItems": "center",
270
+ "flexBasis": 0,
271
+ "flexGrow": 1,
272
+ "flexShrink": 1,
273
+ }
274
+ }
275
+ >
276
+ <HeroIcon
277
+ name="user-outlined"
278
+ style={
279
+ Object {
280
+ "color": "#292a2b",
281
+ "fontSize": 24,
282
+ }
283
+ }
284
+ testID="hero-icon-user-outlined"
285
+ themeIntent="text"
286
+ themeSize="medium"
287
+ />
288
+ <Text
289
+ numberOfLines={1}
290
+ style={
291
+ Array [
292
+ Object {
293
+ "color": "#292a2b",
294
+ "fontSize": 12,
295
+ "fontWeight": "600",
296
+ "letterSpacing": 0.36,
297
+ "lineHeight": 20,
298
+ },
299
+ Object {
300
+ "marginTop": 4,
301
+ },
302
+ ]
303
+ }
304
+ themeFontSize="small"
305
+ themeFontWeight="semi-bold"
306
+ themeIntent="body"
307
+ >
308
+ Profile
309
+ </Text>
310
+ </View>
311
+ </View>
312
+ </View>
313
+ </View>
314
+ </RNCSafeAreaProvider>
315
+ `;
@@ -0,0 +1,169 @@
1
+ import React, { ComponentProps, ReactNode } from 'react';
2
+ import {
3
+ TouchableWithoutFeedback,
4
+ StyleProp,
5
+ ViewStyle,
6
+ ViewProps,
7
+ } from 'react-native';
8
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
9
+ import { useTheme } from 'styled-components-native';
10
+ import Icon from '../Icon';
11
+ import { isHeroIcon } from '../Icon/utils';
12
+ import Typography from '../Typography';
13
+ import {
14
+ BottomBar,
15
+ BottomBarItem,
16
+ BottomBarWrapper,
17
+ BottomNavigationContainer,
18
+ BottomNavigationTab,
19
+ ContentWrapper,
20
+ } from './StyledBottomNavigation';
21
+ import { isIOS } from '../../utils/helpers';
22
+
23
+ type IconType = ComponentProps<typeof Icon>['icon'];
24
+
25
+ export type Tab<V> = {
26
+ key: V;
27
+ title?: string;
28
+ icon: IconType;
29
+ component: ReactNode;
30
+ testID?: string;
31
+ };
32
+
33
+ interface BottomNavigationType<V extends string | number, T extends Tab<V>>
34
+ extends ViewProps {
35
+ /**
36
+ * Callback which is called on tab change, receiving id of upcoming active Tab.
37
+ */
38
+ onChange: (key: V) => void;
39
+ /**
40
+ * Whether inactive tabs should be removed and unmounted in React.
41
+ * Defaults to `false`.
42
+ */
43
+ renderActiveTabOnly?: boolean;
44
+ /**
45
+ * Current selected tab key.
46
+ */
47
+ selectedTabKey: V;
48
+ /**
49
+ * List of Tab to be rendered. Each Tab must have an unique id.
50
+ */
51
+ tabs: T[];
52
+ /**
53
+ * Addditional style.
54
+ */
55
+ style?: StyleProp<ViewStyle>;
56
+ /**
57
+ * Testing id of the component.
58
+ */
59
+ testID?: string;
60
+ }
61
+
62
+ const getInactiveIcon = (icon: IconType): IconType => {
63
+ const inactiveIcon = `${icon}-outlined`;
64
+ return isHeroIcon(inactiveIcon) ? inactiveIcon : icon;
65
+ };
66
+
67
+ const BottomNavigation = <V extends string | number, T extends Tab<V>>({
68
+ onChange,
69
+ renderActiveTabOnly = false,
70
+ selectedTabKey,
71
+ tabs,
72
+ ...nativeProps
73
+ }: BottomNavigationType<V, T>): JSX.Element => {
74
+ const theme = useTheme();
75
+ const insets = useSafeAreaInsets();
76
+
77
+ /**
78
+ * List of loaded tabs, tabs will be loaded when navigated to.
79
+ */
80
+ const [loaded, setLoaded] = React.useState([selectedTabKey]);
81
+
82
+ if (!loaded.includes(selectedTabKey)) {
83
+ // Set the current tab to be loaded if it was not loaded before
84
+ setLoaded(loadedState => [...loadedState, selectedTabKey]);
85
+ }
86
+
87
+ return (
88
+ <BottomNavigationContainer {...nativeProps}>
89
+ <ContentWrapper>
90
+ {tabs.map(tab => {
91
+ const { key, component } = tab;
92
+ const active = selectedTabKey === key;
93
+
94
+ if (renderActiveTabOnly && !active) {
95
+ return null;
96
+ }
97
+
98
+ if (!loaded.includes(key)) {
99
+ // Don't render a screen if we've never navigated to it
100
+ return null;
101
+ }
102
+
103
+ return (
104
+ <BottomNavigationTab
105
+ key={key}
106
+ testID={`route-screen-${selectedTabKey}`}
107
+ pointerEvents={active ? 'auto' : 'none'}
108
+ accessibilityElementsHidden={!active}
109
+ importantForAccessibility={
110
+ active ? 'auto' : 'no-hide-descendants'
111
+ }
112
+ collapsable={false}
113
+ removeClippedSubviews={
114
+ // On iOS, set removeClippedSubviews to true only when not focused
115
+ // This is an workaround for a bug where the clipped view never re-appears.
116
+ isIOS ? selectedTabKey !== key : true
117
+ }
118
+ themeVisibility={active}
119
+ >
120
+ {component}
121
+ </BottomNavigationTab>
122
+ );
123
+ })}
124
+ </ContentWrapper>
125
+ <BottomBarWrapper themeInsets={insets}>
126
+ <BottomBar>
127
+ {tabs.map(tab => {
128
+ const { key, icon, title, testID } = tab;
129
+ const active = selectedTabKey === key;
130
+ const inactiveIcon = getInactiveIcon(icon);
131
+
132
+ return (
133
+ <TouchableWithoutFeedback
134
+ key={key}
135
+ onPress={() => {
136
+ if (key !== selectedTabKey) {
137
+ onChange(key);
138
+ }
139
+ }}
140
+ testID={testID}
141
+ >
142
+ <BottomBarItem>
143
+ <Icon
144
+ icon={active ? icon : inactiveIcon}
145
+ intent={active ? 'primary' : 'text'}
146
+ testID={`hero-icon-${icon}`}
147
+ />
148
+ {title && (
149
+ <Typography.Text
150
+ fontSize="small"
151
+ fontWeight="semi-bold"
152
+ intent={active ? 'primary' : 'body'}
153
+ style={{ marginTop: theme.space.xsmall }}
154
+ numberOfLines={1}
155
+ >
156
+ {title}
157
+ </Typography.Text>
158
+ )}
159
+ </BottomBarItem>
160
+ </TouchableWithoutFeedback>
161
+ );
162
+ })}
163
+ </BottomBar>
164
+ </BottomBarWrapper>
165
+ </BottomNavigationContainer>
166
+ );
167
+ };
168
+
169
+ export default BottomNavigation;
@@ -0,0 +1,6 @@
1
+ import IconList from './IconList';
2
+
3
+ const isHeroIcon = (x: any): x is typeof IconList[number] =>
4
+ IconList.includes(x);
5
+
6
+ export { isHeroIcon };
@@ -4,7 +4,7 @@ import styled, { css } from '../../../styled-components';
4
4
  const StyledText = styled(Text)<{
5
5
  themeFontSize: 'small' | 'medium' | 'large' | 'xlarge';
6
6
  themeFontWeight: 'light' | 'regular' | 'semi-bold';
7
- themeIntent: 'body' | 'subdued';
7
+ themeIntent: 'body' | 'subdued' | 'primary';
8
8
  }>`
9
9
  ${({ themeFontSize, theme }) => {
10
10
  switch (themeFontSize) {
@@ -62,6 +62,10 @@ const StyledText = styled(Text)<{
62
62
  return css`
63
63
  color: ${theme.__hd__.typography.colors.subdued};
64
64
  `;
65
+ case 'primary':
66
+ return css`
67
+ color: ${theme.__hd__.typography.colors.primary};
68
+ `;
65
69
  }
66
70
  }}
67
71
  `;
@@ -22,7 +22,7 @@ interface TextProps extends NativeTextProps {
22
22
  /**
23
23
  * Visual intent color to apply to the text.
24
24
  */
25
- intent?: 'body' | 'subdued';
25
+ intent?: 'body' | 'subdued' | 'primary';
26
26
  /**
27
27
  * Addditional style.
28
28
  */
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ import theme, { getTheme } from './theme';
3
3
  import { scale } from './utils/scale';
4
4
 
5
5
  import Badge from './components/Badge';
6
+ import BottomNavigation from './components/BottomNavigation';
6
7
  import Card from './components/Card';
7
8
  import Divider from './components/Divider';
8
9
  import Icon from './components/Icon';
@@ -16,6 +17,7 @@ export {
16
17
  scale,
17
18
  ThemeProvider,
18
19
  Badge,
20
+ BottomNavigation,
19
21
  Card,
20
22
  Divider,
21
23
  Icon,
@@ -30,6 +30,21 @@ Object {
30
30
  "default": "4px",
31
31
  },
32
32
  },
33
+ "bottomNavigation": Object {
34
+ "colors": Object {
35
+ "background": "#ffffff",
36
+ "shadow": "#292a2b",
37
+ },
38
+ "shadows": Object {
39
+ "elevation": 10,
40
+ "offset": "0px 3px",
41
+ "opacity": 0.27,
42
+ "radius": "4.65px",
43
+ },
44
+ "sizes": Object {
45
+ "height": 72,
46
+ },
47
+ },
33
48
  "card": Object {
34
49
  "padding": Object {
35
50
  "default": "8px",
@@ -86,6 +101,7 @@ Object {
86
101
  "typography": Object {
87
102
  "colors": Object {
88
103
  "body": "#292a2b",
104
+ "primary": "#7622d7",
89
105
  "subdued": "#8b8d92",
90
106
  },
91
107
  "fontSizes": Object {
@@ -0,0 +1,23 @@
1
+ import { GlobalTheme } from '../global';
2
+
3
+ const getBottomNavigationTheme = (theme: GlobalTheme) => {
4
+ const colors = {
5
+ shadow: theme.colors.backgroundDark,
6
+ background: theme.colors.platformBackground,
7
+ };
8
+
9
+ const sizes = {
10
+ height: 72,
11
+ };
12
+
13
+ const shadows = {
14
+ offset: `0px 3px`,
15
+ opacity: 0.27,
16
+ radius: `4.65px`,
17
+ elevation: 10,
18
+ };
19
+
20
+ return { colors, shadows, sizes };
21
+ };
22
+
23
+ export default getBottomNavigationTheme;
@@ -4,6 +4,7 @@ const getTypographyTheme = (theme: GlobalTheme) => {
4
4
  const colors = {
5
5
  body: theme.colors.text,
6
6
  subdued: theme.colors.disabledText,
7
+ primary: theme.colors.primary,
7
8
  };
8
9
 
9
10
  const fontSizes = {
@@ -1,6 +1,7 @@
1
1
  import globalTheme, { GlobalTheme } from './global';
2
2
 
3
3
  import getBadgeTheme from './components/badge';
4
+ import getBottomNavigationTheme from './components/bottomNavigation';
4
5
  import getCardTheme from './components/card';
5
6
  import getDividerTheme from './components/divider';
6
7
  import getIconTheme from './components/icon';
@@ -10,6 +11,7 @@ import getFABTheme from './components/fab';
10
11
  type Theme = GlobalTheme & {
11
12
  __hd__: {
12
13
  badge: ReturnType<typeof getBadgeTheme>;
14
+ bottomNavigation: ReturnType<typeof getBottomNavigationTheme>;
13
15
  card: ReturnType<typeof getCardTheme>;
14
16
  divider: ReturnType<typeof getDividerTheme>;
15
17
  icon: ReturnType<typeof getIconTheme>;
@@ -22,6 +24,7 @@ const getTheme = (theme: GlobalTheme = globalTheme): Theme => ({
22
24
  ...theme,
23
25
  __hd__: {
24
26
  badge: getBadgeTheme(theme),
27
+ bottomNavigation: getBottomNavigationTheme(theme),
25
28
  card: getCardTheme(theme),
26
29
  divider: getDividerTheme(theme),
27
30
  icon: getIconTheme(theme),
@@ -0,0 +1,4 @@
1
+ import { Platform } from 'react-native';
2
+
3
+ export const isIOS = Platform.OS === 'ios';
4
+ export const isAndroid = Platform.OS === 'android';
@@ -0,0 +1,2 @@
1
+ declare const MyComponent: () => JSX.Element;
2
+ export default MyComponent;
@@ -0,0 +1,17 @@
1
+ import { View } from 'react-native';
2
+ declare const BottomNavigationTab: import("styled-components").StyledComponent<typeof View, import("../../theme").Theme, {
3
+ themeVisibility?: boolean | undefined;
4
+ }, never>;
5
+ declare const BottomNavigationContainer: import("styled-components").StyledComponent<typeof View, import("../../theme").Theme, {}, never>;
6
+ declare const ContentWrapper: import("styled-components").StyledComponent<typeof View, import("../../theme").Theme, {}, never>;
7
+ declare const BottomBarWrapper: import("styled-components").StyledComponent<typeof View, import("../../theme").Theme, {
8
+ themeInsets: {
9
+ top: number;
10
+ right: number;
11
+ bottom: number;
12
+ left: number;
13
+ };
14
+ }, never>;
15
+ declare const BottomBar: import("styled-components").StyledComponent<typeof View, import("../../theme").Theme, {}, never>;
16
+ declare const BottomBarItem: import("styled-components").StyledComponent<typeof View, import("../../theme").Theme, {}, never>;
17
+ export { BottomBar, BottomBarItem, BottomNavigationTab, BottomNavigationContainer, BottomBarWrapper, ContentWrapper, };
@@ -0,0 +1,40 @@
1
+ import { ComponentProps, ReactNode } from 'react';
2
+ import { StyleProp, ViewStyle, ViewProps } from 'react-native';
3
+ import Icon from '../Icon';
4
+ declare type IconType = ComponentProps<typeof Icon>['icon'];
5
+ export declare type Tab<V> = {
6
+ key: V;
7
+ title?: string;
8
+ icon: IconType;
9
+ component: ReactNode;
10
+ testID?: string;
11
+ };
12
+ interface BottomNavigationType<V extends string | number, T extends Tab<V>> extends ViewProps {
13
+ /**
14
+ * Callback which is called on tab change, receiving id of upcoming active Tab.
15
+ */
16
+ onChange: (key: V) => void;
17
+ /**
18
+ * Whether inactive tabs should be removed and unmounted in React.
19
+ * Defaults to `false`.
20
+ */
21
+ renderActiveTabOnly?: boolean;
22
+ /**
23
+ * Current selected tab key.
24
+ */
25
+ selectedTabKey: V;
26
+ /**
27
+ * List of Tab to be rendered. Each Tab must have an unique id.
28
+ */
29
+ tabs: T[];
30
+ /**
31
+ * Addditional style.
32
+ */
33
+ style?: StyleProp<ViewStyle>;
34
+ /**
35
+ * Testing id of the component.
36
+ */
37
+ testID?: string;
38
+ }
39
+ declare const BottomNavigation: <V extends string | number, T extends Tab<V>>({ onChange, renderActiveTabOnly, selectedTabKey, tabs, ...nativeProps }: BottomNavigationType<V, T>) => JSX.Element;
40
+ export default BottomNavigation;