@hero-design/rn 7.2.2 → 7.3.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 (243) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/es/index.js +2389 -449
  3. package/jest.config.js +1 -1
  4. package/lib/index.js +2410 -465
  5. package/package.json +4 -2
  6. package/playground/components/Avatar.tsx +102 -0
  7. package/playground/components/Badge.tsx +146 -9
  8. package/playground/components/Button.tsx +138 -35
  9. package/playground/components/Card.tsx +36 -1
  10. package/playground/components/Collapse.tsx +99 -0
  11. package/playground/components/Drawer.tsx +32 -0
  12. package/playground/components/FAB.tsx +15 -0
  13. package/playground/components/IconButton.tsx +67 -0
  14. package/playground/components/Progress.tsx +95 -0
  15. package/playground/components/Tabs.tsx +106 -14
  16. package/playground/components/Tag.tsx +45 -0
  17. package/playground/index.tsx +18 -0
  18. package/src/components/Avatar/StyledAvatar.tsx +61 -0
  19. package/src/components/Avatar/__tests__/StyledAvatar.spec.tsx +48 -0
  20. package/src/components/Avatar/__tests__/__snapshots__/StyledAvatar.spec.tsx.snap +87 -0
  21. package/src/components/Avatar/__tests__/__snapshots__/index.spec.tsx.snap +88 -0
  22. package/src/components/Avatar/__tests__/index.spec.tsx +26 -0
  23. package/src/components/Avatar/index.tsx +71 -0
  24. package/src/components/Badge/Status.tsx +77 -0
  25. package/src/components/Badge/StyledBadge.tsx +38 -26
  26. package/src/components/Badge/__tests__/Badge.spec.tsx +16 -0
  27. package/src/components/Badge/__tests__/Status.spec.tsx +27 -0
  28. package/src/components/Badge/__tests__/__snapshots__/Badge.spec.tsx.snap +133 -52
  29. package/src/components/Badge/__tests__/__snapshots__/Status.spec.tsx.snap +89 -0
  30. package/src/components/Badge/index.tsx +77 -19
  31. package/src/components/Button/Button.tsx +163 -0
  32. package/src/components/Button/LoadingIndicator/StyledLoadingIndicator.tsx +58 -0
  33. package/src/components/Button/LoadingIndicator/__tests__/StyledLoadingIndicator.spec.tsx +20 -0
  34. package/src/components/Button/LoadingIndicator/__tests__/__snapshots__/StyledLoadingIndicator.spec.tsx.snap +101 -0
  35. package/src/components/Button/LoadingIndicator/__tests__/__snapshots__/index.spec.tsx.snap +606 -0
  36. package/src/components/Button/LoadingIndicator/__tests__/index.spec.tsx +24 -0
  37. package/src/components/Button/LoadingIndicator/index.tsx +140 -0
  38. package/src/components/Button/StyledButton.tsx +254 -0
  39. package/src/components/Button/__tests__/Button.spec.tsx +86 -0
  40. package/src/components/Button/__tests__/{index.spec.tsx → IconButton.spec.tsx} +0 -0
  41. package/src/components/Button/__tests__/StyledButton.spec.tsx +154 -0
  42. package/src/components/Button/__tests__/__snapshots__/{index.spec.tsx.snap → IconButton.spec.tsx.snap} +0 -0
  43. package/src/components/Button/__tests__/__snapshots__/StyledButton.spec.tsx.snap +895 -0
  44. package/src/components/Button/index.tsx +10 -2
  45. package/src/components/Card/StyledCard.tsx +27 -4
  46. package/src/components/Card/__tests__/StyledCard.spec.tsx +15 -3
  47. package/src/components/Card/__tests__/__snapshots__/StyledCard.spec.tsx.snap +34 -1
  48. package/src/components/Card/__tests__/index.spec.tsx +16 -21
  49. package/src/components/Card/index.tsx +15 -2
  50. package/src/components/Collapse/StyledCollapse.tsx +15 -0
  51. package/src/components/Collapse/__tests__/StyledCollapse.spec.tsx +26 -0
  52. package/src/components/Collapse/__tests__/__snapshots__/StyledCollapse.spec.tsx.snap +37 -0
  53. package/src/components/Collapse/__tests__/__snapshots__/index.spec.tsx.snap +84 -0
  54. package/src/components/Collapse/__tests__/index.spec.tsx +42 -0
  55. package/src/components/Collapse/index.tsx +109 -0
  56. package/src/components/Divider/index.tsx +1 -1
  57. package/src/components/Drawer/StyledDrawer.tsx +39 -0
  58. package/src/components/Drawer/__tests__/__snapshots__/index.spec.tsx.snap +244 -0
  59. package/src/components/Drawer/__tests__/index.spec.tsx +37 -0
  60. package/src/components/Drawer/index.tsx +93 -0
  61. package/src/components/FAB/ActionGroup/__tests__/__snapshots__/index.spec.tsx.snap +78 -62
  62. package/src/components/FAB/ActionGroup/__tests__/index.spec.tsx +2 -0
  63. package/src/components/FAB/ActionGroup/index.tsx +13 -0
  64. package/src/components/FAB/FAB.tsx +63 -13
  65. package/src/components/FAB/StyledFAB.tsx +25 -6
  66. package/src/components/FAB/__tests__/__snapshots__/AnimatedFABIcon.spec.tsx.snap +6 -2
  67. package/src/components/FAB/__tests__/__snapshots__/StyledFAB.spec.tsx.snap +7 -3
  68. package/src/components/FAB/__tests__/__snapshots__/index.spec.tsx.snap +88 -6
  69. package/src/components/FAB/__tests__/index.spec.tsx +16 -0
  70. package/src/components/Progress/ProgressBar.tsx +73 -0
  71. package/src/components/Progress/ProgressCircle.tsx +165 -0
  72. package/src/components/Progress/StyledProgressBar.tsx +21 -0
  73. package/src/components/Progress/StyledProgressCircle.tsx +66 -0
  74. package/src/components/Progress/__tests__/__snapshots__/index.spec.js.snap +641 -0
  75. package/src/components/Progress/__tests__/index.spec.js +46 -0
  76. package/src/components/Progress/index.tsx +6 -0
  77. package/src/components/Progress/types.ts +1 -0
  78. package/src/components/Tabs/ActiveTabIndicator.tsx +37 -0
  79. package/src/components/Tabs/ScrollableTabs.tsx +216 -0
  80. package/src/components/Tabs/StyledScrollableTabs.tsx +60 -0
  81. package/src/components/Tabs/StyledTabs.tsx +30 -44
  82. package/src/components/Tabs/__tests__/ScrollableTabs.spec.tsx +84 -0
  83. package/src/components/Tabs/__tests__/__snapshots__/ScrollableTabs.spec.tsx.snap +591 -0
  84. package/src/components/Tabs/__tests__/__snapshots__/index.spec.tsx.snap +317 -224
  85. package/src/components/Tabs/__tests__/index.spec.tsx +22 -21
  86. package/src/components/Tabs/index.tsx +155 -114
  87. package/src/components/Tabs/utils.ts +13 -0
  88. package/src/components/Tag/StyledTag.tsx +35 -0
  89. package/src/components/Tag/__tests__/Tag.spec.tsx +41 -0
  90. package/src/components/Tag/__tests__/__snapshots__/Tag.spec.tsx.snap +153 -0
  91. package/src/components/Tag/index.tsx +41 -0
  92. package/src/components/Typography/Text/index.tsx +1 -1
  93. package/src/index.ts +10 -0
  94. package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +182 -20
  95. package/src/theme/components/avatar.ts +40 -0
  96. package/src/theme/components/badge.ts +14 -16
  97. package/src/theme/components/button.ts +57 -0
  98. package/src/theme/components/card.ts +8 -2
  99. package/src/theme/components/drawer.ts +24 -0
  100. package/src/theme/components/fab.ts +9 -2
  101. package/src/theme/components/progress.ts +27 -0
  102. package/src/theme/components/tabs.ts +22 -7
  103. package/src/theme/components/tag.ts +39 -0
  104. package/src/theme/global/borders.ts +13 -1
  105. package/src/theme/global/colors.ts +6 -1
  106. package/src/theme/global/index.ts +3 -1
  107. package/src/theme/global/scale.ts +3 -0
  108. package/src/theme/index.ts +16 -1
  109. package/src/utils/hooks.ts +10 -0
  110. package/testUtils/setup.tsx +43 -0
  111. package/types/playground/components/Avatar.d.ts +2 -0
  112. package/types/playground/components/Badge.d.ts +0 -0
  113. package/types/playground/components/BottomNavigation.d.ts +0 -0
  114. package/types/playground/components/Button.d.ts +0 -0
  115. package/types/playground/components/Card.d.ts +0 -0
  116. package/types/playground/components/Collapse.d.ts +2 -0
  117. package/types/playground/components/Divider.d.ts +0 -0
  118. package/types/playground/components/Drawer.d.ts +2 -0
  119. package/types/playground/components/FAB.d.ts +0 -0
  120. package/types/playground/components/Icon.d.ts +0 -0
  121. package/types/playground/components/IconButton.d.ts +2 -0
  122. package/types/playground/components/Progress.d.ts +2 -0
  123. package/types/playground/components/Tabs.d.ts +0 -0
  124. package/types/playground/components/Tag.d.ts +2 -0
  125. package/types/playground/components/Typography.d.ts +0 -0
  126. package/types/playground/index.d.ts +0 -0
  127. package/types/src/components/Avatar/StyledAvatar.d.ts +46 -0
  128. package/types/src/components/{BottomNavigation/__tests__/BottomNavigation.spec.d.ts → Avatar/__tests__/StyledAvatar.spec.d.ts} +0 -0
  129. package/types/src/components/{Card/__tests__/Card.spec.d.ts → Avatar/__tests__/index.spec.d.ts} +0 -0
  130. package/types/src/components/Avatar/index.d.ts +25 -0
  131. package/types/src/components/Badge/Status.d.ts +24 -0
  132. package/types/src/components/Badge/StyledBadge.d.ts +17 -9
  133. package/types/src/components/Badge/__tests__/Badge.spec.d.ts +0 -0
  134. package/types/src/components/{FAB/__tests__/StyledFABContainer.spec.d.ts → Badge/__tests__/Status.spec.d.ts} +0 -0
  135. package/types/src/components/Badge/index.d.ts +17 -7
  136. package/types/src/components/BottomNavigation/StyledBottomNavigation.d.ts +0 -0
  137. package/types/src/components/BottomNavigation/__tests__/index.spec.d.ts +0 -0
  138. package/types/src/components/BottomNavigation/index.d.ts +0 -0
  139. package/types/src/components/Button/Button.d.ts +57 -0
  140. package/types/src/components/Button/IconButton.d.ts +0 -0
  141. package/types/src/components/Button/LoadingIndicator/StyledLoadingIndicator.d.ts +20 -0
  142. package/types/src/components/{FAB/__tests__/StyledFABIcon.spec.d.ts → Button/LoadingIndicator/__tests__/StyledLoadingIndicator.spec.d.ts} +0 -0
  143. package/types/src/components/{Icon/__tests__/Icon.spec.d.ts → Button/LoadingIndicator/__tests__/index.spec.d.ts} +0 -0
  144. package/types/src/components/Button/LoadingIndicator/index.d.ts +26 -0
  145. package/types/src/components/Button/StyledButton.d.ts +40 -0
  146. package/types/src/components/{Tabs/__tests__/Tabs.spec.d.ts → Button/__tests__/Button.spec.d.ts} +0 -0
  147. package/types/src/components/Button/__tests__/IconButton.spec.d.ts +1 -0
  148. package/types/src/components/Button/__tests__/StyledButton.spec.d.ts +1 -0
  149. package/types/src/components/Button/__tests__/index.spec.d.ts +0 -0
  150. package/types/src/components/Button/index.d.ts +8 -4
  151. package/types/src/components/Card/StyledCard.d.ts +9 -1
  152. package/types/src/components/Card/__tests__/StyledCard.spec.d.ts +0 -0
  153. package/types/src/components/Card/__tests__/index.spec.d.ts +0 -0
  154. package/types/src/components/Card/index.d.ts +5 -1
  155. package/types/src/components/Collapse/StyledCollapse.d.ts +15 -0
  156. package/types/src/components/Collapse/__tests__/StyledCollapse.spec.d.ts +1 -0
  157. package/types/src/components/Collapse/__tests__/index.spec.d.ts +1 -0
  158. package/types/src/components/Collapse/index.d.ts +23 -0
  159. package/types/src/components/Divider/StyledDivider.d.ts +0 -0
  160. package/types/src/components/Divider/__tests__/StyledDivider.spec.d.ts +0 -0
  161. package/types/src/components/Divider/index.d.ts +0 -0
  162. package/types/src/components/Drawer/StyledDrawer.d.ts +25 -0
  163. package/types/src/components/Drawer/__tests__/index.spec.d.ts +1 -0
  164. package/types/src/components/Drawer/index.d.ts +25 -0
  165. package/types/src/components/FAB/ActionGroup/ActionItem.d.ts +0 -0
  166. package/types/src/components/FAB/ActionGroup/StyledActionGroup.d.ts +0 -0
  167. package/types/src/components/FAB/ActionGroup/StyledActionItem.d.ts +0 -0
  168. package/types/src/components/FAB/ActionGroup/__tests__/index.spec.d.ts +0 -0
  169. package/types/src/components/FAB/ActionGroup/index.d.ts +5 -1
  170. package/types/src/components/FAB/AnimatedFABIcon.d.ts +0 -0
  171. package/types/src/components/FAB/FAB.d.ts +5 -1
  172. package/types/src/components/FAB/StyledFAB.d.ts +8 -2
  173. package/types/src/components/FAB/__tests__/AnimatedFABIcon.spec.d.ts +0 -0
  174. package/types/src/components/FAB/__tests__/StyledFAB.spec.d.ts +0 -0
  175. package/types/src/components/FAB/__tests__/index.spec.d.ts +0 -0
  176. package/types/src/components/FAB/index.d.ts +2 -2
  177. package/types/src/components/Icon/HeroIcon/index.d.ts +0 -0
  178. package/types/src/components/Icon/IconList.d.ts +0 -0
  179. package/types/src/components/Icon/__tests__/index.spec.d.ts +0 -0
  180. package/types/src/components/Icon/index.d.ts +0 -0
  181. package/types/src/components/Icon/utils.d.ts +1 -1
  182. package/types/src/components/Progress/ProgressBar.d.ts +18 -0
  183. package/types/src/components/Progress/ProgressCircle.d.ts +18 -0
  184. package/types/src/components/Progress/StyledProgressBar.d.ts +18 -0
  185. package/types/src/components/Progress/StyledProgressCircle.d.ts +38 -0
  186. package/types/src/components/Progress/__tests__/index.spec.d.ts +1 -0
  187. package/types/src/components/Progress/index.d.ts +5 -0
  188. package/types/src/components/Progress/types.d.ts +1 -0
  189. package/types/src/components/Tabs/ActiveTabIndicator.d.ts +8 -0
  190. package/types/src/components/Tabs/ScrollableTab.d.ts +3 -0
  191. package/types/src/components/Tabs/ScrollableTabs.d.ts +3 -0
  192. package/types/src/components/Tabs/StyledScrollableTab.d.ts +61 -0
  193. package/types/src/components/Tabs/StyledScrollableTabs.d.ts +61 -0
  194. package/types/src/components/Tabs/StyledTabs.d.ts +22 -22
  195. package/types/src/components/Tabs/__tests__/ScrollableTab.spec.d.ts +1 -0
  196. package/types/src/components/Tabs/__tests__/ScrollableTabs.spec.d.ts +1 -0
  197. package/types/src/components/Tabs/__tests__/index.spec.d.ts +0 -0
  198. package/types/src/components/Tabs/index.d.ts +28 -19
  199. package/types/src/components/Tabs/utils.d.ts +2 -0
  200. package/types/src/components/Tag/StyledTag.d.ts +20 -0
  201. package/types/src/components/Tag/__tests__/Tag.spec.d.ts +1 -0
  202. package/types/src/components/Tag/index.d.ts +21 -0
  203. package/types/src/components/Typography/Text/StyledText.d.ts +0 -0
  204. package/types/src/components/Typography/Text/__tests__/StyledText.spec.d.ts +0 -0
  205. package/types/src/components/Typography/Text/__tests__/index.spec.d.ts +0 -0
  206. package/types/src/components/Typography/Text/index.d.ts +0 -0
  207. package/types/src/components/Typography/index.d.ts +0 -0
  208. package/types/src/index.d.ts +6 -1
  209. package/types/src/testHelpers/renderWithTheme.d.ts +0 -0
  210. package/types/src/theme/__tests__/index.spec.d.ts +0 -0
  211. package/types/src/theme/components/avatar.d.ts +32 -0
  212. package/types/src/theme/components/badge.d.ts +12 -13
  213. package/types/src/theme/components/bottomNavigation.d.ts +0 -0
  214. package/types/src/theme/components/button.d.ts +37 -0
  215. package/types/src/theme/components/card.d.ts +5 -1
  216. package/types/src/theme/components/divider.d.ts +0 -0
  217. package/types/src/theme/components/drawer.d.ts +21 -0
  218. package/types/src/theme/components/fab.d.ts +8 -1
  219. package/types/src/theme/components/icon.d.ts +0 -0
  220. package/types/src/theme/components/progress.d.ts +21 -0
  221. package/types/src/theme/components/tabs.d.ts +14 -2
  222. package/types/src/theme/components/tag.d.ts +30 -0
  223. package/types/src/theme/components/typography.d.ts +0 -0
  224. package/types/src/theme/global/borders.d.ts +7 -1
  225. package/types/src/theme/global/colors.d.ts +6 -1
  226. package/types/src/theme/global/index.d.ts +7 -1
  227. package/types/src/theme/global/scale.d.ts +1 -0
  228. package/types/src/theme/global/space.d.ts +0 -0
  229. package/types/src/theme/global/typography.d.ts +0 -0
  230. package/types/src/theme/index.d.ts +10 -0
  231. package/types/src/types.d.ts +0 -0
  232. package/types/src/utils/__tests__/scale.spec.d.ts +0 -0
  233. package/types/src/utils/helpers.d.ts +0 -0
  234. package/types/src/utils/hooks.d.ts +1 -0
  235. package/types/src/utils/scale.d.ts +0 -0
  236. package/.expo/README.md +0 -15
  237. package/.expo/packager-info.json +0 -10
  238. package/.expo/settings.json +0 -10
  239. package/src/components/Card/__tests__/__snapshots__/index.spec.tsx.snap +0 -33
  240. package/testUtils/setup.ts +0 -18
  241. package/types/src/components/FAB/StyledFABContainer.d.ts +0 -3
  242. package/types/src/components/FAB/StyledFABIcon.d.ts +0 -3
  243. package/types/src/styled-components.d.ts +0 -6
@@ -1,43 +1,50 @@
1
1
  import React, { ReactNode } from 'react';
2
2
  import {
3
- TouchableOpacity,
3
+ Animated,
4
+ TouchableWithoutFeedback,
5
+ View,
4
6
  StyleProp,
5
7
  ViewStyle,
6
8
  ViewProps,
7
- FlatList,
8
9
  } from 'react-native';
9
10
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
11
+ import { useTheme } from '@emotion/react';
12
+ import PagerView, {
13
+ PagerViewOnPageScrollEventData,
14
+ } from 'react-native-pager-view';
15
+ import Typography from '../Typography';
10
16
  import {
11
- HeaderTabItem,
17
+ ContentWrapper,
12
18
  HeaderTabWrapper,
13
- StyledHeaderTabText,
14
- StyledHeaderTabIcon,
19
+ HeaderTabItem,
15
20
  TabContainer,
16
21
  TabScreen,
17
- ContentWrapper,
18
- StyledFlatList,
22
+ HeaderTab,
19
23
  } from './StyledTabs';
20
- import { isIOS } from '../../utils/helpers';
24
+ import Badge from '../Badge';
21
25
  import { IconName } from '../Icon';
26
+ import ActiveTabIndicator from './ActiveTabIndicator';
27
+ import ScrollableTabs from './ScrollableTabs';
28
+
29
+ export type ItemType =
30
+ | string
31
+ | IconName
32
+ | ((props: { color: string }) => ReactNode);
22
33
 
23
34
  export type TabType = {
24
35
  key: string;
25
- title: string;
26
- icon: IconName;
36
+ activeItem: ItemType;
37
+ inactiveItem?: ItemType;
27
38
  component: ReactNode;
28
39
  testID?: string;
40
+ showBadge?: boolean;
29
41
  };
30
42
 
31
- interface TabsProps extends ViewProps {
43
+ export interface TabsProps extends ViewProps {
32
44
  /**
33
45
  * Callback which is called on tab press, receiving key of upcoming active Tab.
34
46
  */
35
47
  onTabPress: (key: string) => void;
36
- /**
37
- * Whether inactive tabs should be removed and unmounted in React.
38
- * Defaults to `false`.
39
- */
40
- renderActiveTabOnly?: boolean;
41
48
  /**
42
49
  * Current selected tab key.
43
50
  */
@@ -45,116 +52,154 @@ interface TabsProps extends ViewProps {
45
52
  /**
46
53
  * List of Tabs to be rendered. Each Tab must have an unique key.
47
54
  */
48
- tabs: {
49
- key: string;
50
- title: string;
51
- icon: IconName;
52
- component: ReactNode;
53
- testID?: string;
54
- }[];
55
+ tabs: TabType[];
56
+ /**
57
+ * Style for the container of Tab.
58
+ */
59
+ containerStyle?: StyleProp<ViewStyle>;
55
60
  /**
56
- * Addditional style.
61
+ * Style for the tab navigation bar.
57
62
  */
58
- style?: StyleProp<ViewStyle>;
63
+ barStyle?: StyleProp<ViewStyle>;
64
+ /**
65
+ * Whether inactive screen should be removed and unmounted in React.
66
+ * Defaults value is `false`.
67
+ */
68
+ lazy?: boolean;
69
+ /**
70
+ * Only work when lazy is `true`. You can specify how many adjacent screens should be preloaded.
71
+ * Defaults value is `1`.
72
+ */
73
+ lazyPreloadDistance?: number;
59
74
  /**
60
75
  * Testing id of the component.
61
76
  */
62
77
  testID?: string;
63
78
  }
64
79
 
80
+ const getTabItem = ({
81
+ item,
82
+ color,
83
+ active,
84
+ }: {
85
+ item: ItemType;
86
+ color: string;
87
+ active: boolean;
88
+ }) => {
89
+ if (typeof item === 'string') {
90
+ return (
91
+ <Typography.Text
92
+ fontWeight={active ? 'semi-bold' : 'regular'}
93
+ numberOfLines={1}
94
+ style={{ color }}
95
+ >
96
+ {item}
97
+ </Typography.Text>
98
+ );
99
+ }
100
+
101
+ return item({ color });
102
+ };
103
+
65
104
  const Tabs = ({
66
105
  onTabPress,
67
- renderActiveTabOnly = false,
68
106
  selectedTabKey,
69
107
  tabs,
70
- ...nativeProps
108
+ containerStyle,
109
+ barStyle,
110
+ lazy = false,
111
+ lazyPreloadDistance = 1,
71
112
  }: TabsProps): JSX.Element => {
72
- const flatListRef = React.useRef<FlatList>(null);
113
+ const theme = useTheme();
73
114
  const insets = useSafeAreaInsets();
74
-
75
- /**
76
- * List of loaded tabs, tabs will be loaded when navigated to.
77
- */
78
- const [loaded, setLoaded] = React.useState([selectedTabKey]);
79
-
80
- React.useEffect(() => {
81
- const selectedTabIndex = tabs.findIndex(
82
- item => item.key === selectedTabKey
83
- );
84
- if (selectedTabIndex !== -1) {
85
- flatListRef.current?.scrollToIndex({
86
- index: selectedTabIndex,
87
- viewPosition: 0.5,
88
- });
89
- }
90
- }, [selectedTabKey, tabs]);
91
-
92
- if (!loaded.includes(selectedTabKey)) {
93
- // Set the current tab to be loaded if it was not loaded before
94
- setLoaded(loadedState => [...loadedState, selectedTabKey]);
95
- }
115
+ const pagerViewRef = React.useRef<PagerView>(null);
116
+ const selectedTabIndex = tabs.findIndex(item => item.key === selectedTabKey);
117
+ const scrollOffsetAnimatedValue = React.useRef(new Animated.Value(0)).current;
118
+ const positionAnimatedValue = React.useRef(new Animated.Value(0)).current;
119
+ const [tabsWidth, setTabsWidth] = React.useState<number>(0);
96
120
 
97
121
  return (
98
- <TabContainer {...nativeProps}>
99
- <HeaderTabWrapper themeInsets={insets}>
100
- <StyledFlatList<TabType>
101
- ref={flatListRef}
102
- horizontal
103
- data={tabs}
104
- keyExtractor={tab => String(tab.key)}
105
- showsHorizontalScrollIndicator={false}
106
- onScrollToIndexFailed={({ index }) => {
107
- setTimeout(
108
- () =>
109
- flatListRef.current?.scrollToIndex({
110
- index,
111
- viewPosition: 0.5,
112
- }),
113
- 100
114
- );
115
- }}
116
- renderItem={({ item: tab }) => {
117
- const { key, icon, title, testID } = tab;
118
- const active = selectedTabKey === key;
122
+ <TabContainer style={containerStyle}>
123
+ <HeaderTabWrapper themeInsets={insets} style={barStyle}>
124
+ <View>
125
+ <HeaderTab
126
+ onLayout={e => {
127
+ const { width } = e.nativeEvent.layout;
128
+ if (tabsWidth !== width) {
129
+ setTabsWidth(width);
130
+ }
131
+ }}
132
+ >
133
+ {tabs.map((tab, index) => {
134
+ const {
135
+ key,
136
+ testID,
137
+ activeItem,
138
+ inactiveItem: originalInactiveItem,
139
+ showBadge = false,
140
+ } = tab;
119
141
 
120
- return (
121
- <TouchableOpacity
122
- key={key}
123
- onPress={() => onTabPress(key)}
124
- testID={testID}
125
- >
126
- <HeaderTabItem>
127
- <StyledHeaderTabIcon
128
- icon={icon}
129
- testID={`hero-icon-${icon}`}
130
- themeActive={active}
131
- />
132
- <StyledHeaderTabText
133
- fontWeight="semi-bold"
134
- numberOfLines={1}
135
- themeActive={active}
136
- >
137
- {title}
138
- </StyledHeaderTabText>
139
- </HeaderTabItem>
140
- </TouchableOpacity>
141
- );
142
- }}
143
- />
144
- </HeaderTabWrapper>
145
- <ContentWrapper>
146
- {tabs.map(tab => {
147
- const { key, component, testID } = tab;
148
- const active = selectedTabKey === key;
142
+ const active = selectedTabKey === key;
143
+ const inactiveItem = originalInactiveItem ?? activeItem;
144
+ const tabItem = getTabItem({
145
+ item: active ? activeItem : inactiveItem,
146
+ color: theme.__hd__.tabs.colors.text,
147
+ active,
148
+ });
149
149
 
150
- if (renderActiveTabOnly && !active) {
151
- return null;
150
+ return (
151
+ <TouchableWithoutFeedback
152
+ key={key}
153
+ onPress={() => {
154
+ onTabPress(key);
155
+ pagerViewRef.current?.setPage(index);
156
+ }}
157
+ testID={testID}
158
+ >
159
+ <HeaderTabItem>
160
+ <Badge.Status visible={showBadge}>{tabItem}</Badge.Status>
161
+ </HeaderTabItem>
162
+ </TouchableWithoutFeedback>
163
+ );
164
+ })}
165
+ </HeaderTab>
166
+ <ActiveTabIndicator
167
+ positionAnimatedValue={positionAnimatedValue}
168
+ scrollOffsetAnimatedValue={scrollOffsetAnimatedValue}
169
+ tabsLength={tabs.length}
170
+ tabsWidth={tabsWidth}
171
+ />
172
+ </View>
173
+ </HeaderTabWrapper>
174
+ <ContentWrapper
175
+ initialPage={selectedTabIndex}
176
+ ref={pagerViewRef}
177
+ onPageSelected={e => {
178
+ const index = e.nativeEvent.position;
179
+ const selectedItem = tabs[index];
180
+ if (selectedItem) {
181
+ onTabPress(selectedItem.key);
152
182
  }
153
-
154
- if (!loaded.includes(key)) {
155
- // Don't render a screen if we've never navigated to it
156
- return null;
183
+ }}
184
+ onPageScroll={Animated.event<PagerViewOnPageScrollEventData>(
185
+ [
186
+ {
187
+ nativeEvent: {
188
+ offset: scrollOffsetAnimatedValue,
189
+ position: positionAnimatedValue,
190
+ },
191
+ },
192
+ ],
193
+ {
194
+ useNativeDriver: true,
157
195
  }
196
+ )}
197
+ >
198
+ {tabs.map((tab, index) => {
199
+ const { key, component, testID } = tab;
200
+ const active = selectedTabKey === key;
201
+ const isLazyScreen =
202
+ lazy && Math.abs(selectedTabIndex - index) > lazyPreloadDistance;
158
203
 
159
204
  return (
160
205
  <TabScreen
@@ -166,14 +211,8 @@ const Tabs = ({
166
211
  active ? 'auto' : 'no-hide-descendants'
167
212
  }
168
213
  collapsable={false}
169
- removeClippedSubviews={
170
- // On iOS, set removeClippedSubviews to true only when not focused
171
- // This is an workaround for a bug where the clipped view never re-appears.
172
- isIOS ? selectedTabKey !== key : true
173
- }
174
- themeVisibility={active}
175
214
  >
176
- {component}
215
+ {isLazyScreen ? null : component}
177
216
  </TabScreen>
178
217
  );
179
218
  })}
@@ -182,4 +221,6 @@ const Tabs = ({
182
221
  );
183
222
  };
184
223
 
185
- export default Tabs;
224
+ export default Object.assign(Tabs, {
225
+ Scroll: ScrollableTabs,
226
+ });
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { Animated } from 'react-native';
3
+
4
+ export const useAnimatedValueArray = (initialValues: number[]) => {
5
+ const refs = React.useRef<Animated.Value[]>([]);
6
+
7
+ refs.current.length = initialValues.length;
8
+ initialValues.forEach((initialValue, i) => {
9
+ refs.current[i] = refs.current[i] ?? new Animated.Value(initialValue);
10
+ });
11
+
12
+ return refs.current;
13
+ };
@@ -0,0 +1,35 @@
1
+ import { View, Text } from 'react-native';
2
+ import styled from '@emotion/native';
3
+
4
+ const BACKGROUND_INTENTS = {
5
+ success: 'successBackground',
6
+ warning: 'warningBackground',
7
+ danger: 'dangerBackground',
8
+ info: 'infoBackground',
9
+ } as const;
10
+
11
+ type ThemeIntent = 'success' | 'warning' | 'danger' | 'info';
12
+
13
+ const StyledView = styled(View)<{ themeIntent: ThemeIntent }>(
14
+ ({ themeIntent, theme }) => ({
15
+ borderWidth: theme.__hd__.tag.borderWidths.default,
16
+ borderRadius: theme.__hd__.tag.radii.default,
17
+ paddingVertical: theme.__hd__.tag.space.verticalPadding,
18
+ paddingHorizontal: theme.__hd__.tag.space.horizontalPadding,
19
+ borderColor: theme.__hd__.tag.colors[themeIntent],
20
+ backgroundColor: theme.__hd__.tag.colors[BACKGROUND_INTENTS[themeIntent]],
21
+ })
22
+ );
23
+
24
+ const StyledText = styled(Text)<{ themeIntent: ThemeIntent }>(
25
+ ({ themeIntent, theme }) => ({
26
+ fontFamily: theme.__hd__.tag.fonts.default,
27
+ fontSize: theme.__hd__.tag.fontSizes.default,
28
+ color: theme.__hd__.tag.colors[themeIntent],
29
+ includeFontPadding: false,
30
+ textAlignVertical: 'center',
31
+ textAlign: 'center',
32
+ })
33
+ );
34
+
35
+ export { StyledView, StyledText };
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import renderWithTheme from '../../../testHelpers/renderWithTheme';
3
+ import Tag from '..';
4
+
5
+ describe('Tag', () => {
6
+ it('has success style when intent is success', () => {
7
+ const { getByText, toJSON } = renderWithTheme(
8
+ <Tag content="APPROVED" intent="success" />
9
+ );
10
+
11
+ expect(toJSON()).toMatchSnapshot();
12
+ expect(getByText('APPROVED')).toBeDefined();
13
+ });
14
+
15
+ it('has warning style when intent is warning', () => {
16
+ const { getByText, toJSON } = renderWithTheme(
17
+ <Tag content="PENDING" intent="warning" />
18
+ );
19
+
20
+ expect(toJSON()).toMatchSnapshot();
21
+ expect(getByText('PENDING')).toBeDefined();
22
+ });
23
+
24
+ it('has danger style when intent is danger', () => {
25
+ const { getByText, toJSON } = renderWithTheme(
26
+ <Tag content="DECLINED" intent="danger" />
27
+ );
28
+
29
+ expect(toJSON()).toMatchSnapshot();
30
+ expect(getByText('DECLINED')).toBeDefined();
31
+ });
32
+
33
+ it('has info style when intent is info', () => {
34
+ const { getByText, toJSON } = renderWithTheme(
35
+ <Tag content="SUBMITTED" intent="info" />
36
+ );
37
+
38
+ expect(toJSON()).toMatchSnapshot();
39
+ expect(getByText('SUBMITTED')).toBeDefined();
40
+ });
41
+ });
@@ -0,0 +1,153 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Tag has danger style when intent is danger 1`] = `
4
+ <View
5
+ style={
6
+ Array [
7
+ Object {
8
+ "backgroundColor": "#fcebe7",
9
+ "borderColor": "#de350b",
10
+ "borderRadius": 4,
11
+ "borderWidth": 1,
12
+ "paddingHorizontal": 8,
13
+ "paddingVertical": 2,
14
+ },
15
+ undefined,
16
+ ]
17
+ }
18
+ themeIntent="danger"
19
+ >
20
+ <Text
21
+ style={
22
+ Array [
23
+ Object {
24
+ "color": "#de350b",
25
+ "fontFamily": "BeVietnamPro-SemiBold",
26
+ "fontSize": 12,
27
+ "includeFontPadding": false,
28
+ "textAlign": "center",
29
+ "textAlignVertical": "center",
30
+ },
31
+ undefined,
32
+ ]
33
+ }
34
+ themeIntent="danger"
35
+ >
36
+ DECLINED
37
+ </Text>
38
+ </View>
39
+ `;
40
+
41
+ exports[`Tag has info style when intent is info 1`] = `
42
+ <View
43
+ style={
44
+ Array [
45
+ Object {
46
+ "backgroundColor": "#ecf0ff",
47
+ "borderColor": "#4568fb",
48
+ "borderRadius": 4,
49
+ "borderWidth": 1,
50
+ "paddingHorizontal": 8,
51
+ "paddingVertical": 2,
52
+ },
53
+ undefined,
54
+ ]
55
+ }
56
+ themeIntent="info"
57
+ >
58
+ <Text
59
+ style={
60
+ Array [
61
+ Object {
62
+ "color": "#4568fb",
63
+ "fontFamily": "BeVietnamPro-SemiBold",
64
+ "fontSize": 12,
65
+ "includeFontPadding": false,
66
+ "textAlign": "center",
67
+ "textAlignVertical": "center",
68
+ },
69
+ undefined,
70
+ ]
71
+ }
72
+ themeIntent="info"
73
+ >
74
+ SUBMITTED
75
+ </Text>
76
+ </View>
77
+ `;
78
+
79
+ exports[`Tag has success style when intent is success 1`] = `
80
+ <View
81
+ style={
82
+ Array [
83
+ Object {
84
+ "backgroundColor": "#f0fef4",
85
+ "borderColor": "#017d6d",
86
+ "borderRadius": 4,
87
+ "borderWidth": 1,
88
+ "paddingHorizontal": 8,
89
+ "paddingVertical": 2,
90
+ },
91
+ undefined,
92
+ ]
93
+ }
94
+ themeIntent="success"
95
+ >
96
+ <Text
97
+ style={
98
+ Array [
99
+ Object {
100
+ "color": "#017d6d",
101
+ "fontFamily": "BeVietnamPro-SemiBold",
102
+ "fontSize": 12,
103
+ "includeFontPadding": false,
104
+ "textAlign": "center",
105
+ "textAlignVertical": "center",
106
+ },
107
+ undefined,
108
+ ]
109
+ }
110
+ themeIntent="success"
111
+ >
112
+ APPROVED
113
+ </Text>
114
+ </View>
115
+ `;
116
+
117
+ exports[`Tag has warning style when intent is warning 1`] = `
118
+ <View
119
+ style={
120
+ Array [
121
+ Object {
122
+ "backgroundColor": "#fff6eb",
123
+ "borderColor": "#d98a2c",
124
+ "borderRadius": 4,
125
+ "borderWidth": 1,
126
+ "paddingHorizontal": 8,
127
+ "paddingVertical": 2,
128
+ },
129
+ undefined,
130
+ ]
131
+ }
132
+ themeIntent="warning"
133
+ >
134
+ <Text
135
+ style={
136
+ Array [
137
+ Object {
138
+ "color": "#d98a2c",
139
+ "fontFamily": "BeVietnamPro-SemiBold",
140
+ "fontSize": 12,
141
+ "includeFontPadding": false,
142
+ "textAlign": "center",
143
+ "textAlignVertical": "center",
144
+ },
145
+ undefined,
146
+ ]
147
+ }
148
+ themeIntent="warning"
149
+ >
150
+ PENDING
151
+ </Text>
152
+ </View>
153
+ `;
@@ -0,0 +1,41 @@
1
+ import { StyleProp, ViewStyle, ViewProps } from 'react-native';
2
+ import React from 'react';
3
+ import { StyledView, StyledText } from './StyledTag';
4
+
5
+ interface TagProps extends ViewProps {
6
+ /**
7
+ * Content of the Tag.
8
+ */
9
+ content: string;
10
+ /**
11
+ * Visual intent color to apply to Tag.
12
+ */
13
+ intent?: 'success' | 'warning' | 'danger' | 'info';
14
+ /**
15
+ * Additional style.
16
+ */
17
+ style?: StyleProp<ViewStyle>;
18
+ /**
19
+ * Testing id of the component.
20
+ */
21
+ testID?: string;
22
+ }
23
+
24
+ const Tag = ({
25
+ content,
26
+ intent = 'info',
27
+ style,
28
+ testID,
29
+ ...nativeProps
30
+ }: TagProps): JSX.Element => (
31
+ <StyledView
32
+ {...nativeProps}
33
+ themeIntent={intent}
34
+ style={style}
35
+ testID={testID}
36
+ >
37
+ <StyledText themeIntent={intent}>{content}</StyledText>
38
+ </StyledView>
39
+ );
40
+
41
+ export default Tag;
@@ -41,10 +41,10 @@ const Text = ({
41
41
  ...nativeProps
42
42
  }: TextProps) => (
43
43
  <StyledText
44
+ {...nativeProps}
44
45
  themeFontSize={fontSize}
45
46
  themeFontWeight={fontWeight}
46
47
  themeIntent={intent}
47
- {...nativeProps}
48
48
  >
49
49
  {children}
50
50
  </StyledText>
package/src/index.ts CHANGED
@@ -2,14 +2,19 @@ import { ThemeProvider, useTheme } from '@emotion/react';
2
2
  import theme, { getTheme } from './theme';
3
3
  import { scale } from './utils/scale';
4
4
 
5
+ import Avatar from './components/Avatar';
5
6
  import Badge from './components/Badge';
6
7
  import BottomNavigation from './components/BottomNavigation';
7
8
  import Button from './components/Button';
8
9
  import Card from './components/Card';
10
+ import Collapse from './components/Collapse';
9
11
  import Divider from './components/Divider';
12
+ import Drawer from './components/Drawer';
10
13
  import FAB from './components/FAB';
11
14
  import Icon from './components/Icon';
15
+ import Progress from './components/Progress';
12
16
  import Tabs from './components/Tabs';
17
+ import Tag from './components/Tag';
13
18
  import Typography from './components/Typography';
14
19
 
15
20
  export {
@@ -18,14 +23,19 @@ export {
18
23
  useTheme,
19
24
  scale,
20
25
  ThemeProvider,
26
+ Avatar,
21
27
  Badge,
22
28
  BottomNavigation,
23
29
  Button,
24
30
  Card,
31
+ Collapse,
25
32
  Divider,
33
+ Drawer,
26
34
  FAB,
27
35
  Icon,
36
+ Progress,
28
37
  Tabs,
38
+ Tag,
29
39
  Typography,
30
40
  };
31
41