@hero-design/rn 7.7.0 → 7.9.0

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 (221) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/es/index.js +1775 -333
  3. package/lib/index.js +1780 -336
  4. package/package.json +4 -8
  5. package/src/components/Alert/__tests__/__snapshots__/index.spec.tsx.snap +2 -2
  6. package/src/components/Avatar/index.tsx +1 -1
  7. package/src/components/Button/Button.tsx +4 -2
  8. package/src/components/Button/LoadingIndicator/StyledLoadingIndicator.tsx +7 -2
  9. package/src/components/Button/LoadingIndicator/__tests__/StyledLoadingIndicator.spec.tsx +2 -0
  10. package/src/components/Button/LoadingIndicator/__tests__/__snapshots__/StyledLoadingIndicator.spec.tsx.snap +40 -0
  11. package/src/components/Button/LoadingIndicator/__tests__/__snapshots__/index.spec.tsx.snap +242 -0
  12. package/src/components/Button/LoadingIndicator/__tests__/index.spec.tsx +2 -0
  13. package/src/components/Button/LoadingIndicator/index.tsx +3 -1
  14. package/src/components/Button/StyledButton.tsx +15 -2
  15. package/src/components/Button/__tests__/Button.spec.tsx +2 -0
  16. package/src/components/Button/__tests__/StyledButton.spec.tsx +12 -0
  17. package/src/components/Button/__tests__/__snapshots__/StyledButton.spec.tsx.snap +314 -0
  18. package/src/components/Card/DataCard/StyledDataCard.tsx +18 -0
  19. package/src/components/Card/DataCard/__tests__/StyledDataCard.spec.tsx +24 -0
  20. package/src/components/Card/DataCard/__tests__/__snapshots__/StyledDataCard.spec.tsx.snap +96 -0
  21. package/src/components/Card/DataCard/__tests__/__snapshots__/index.spec.tsx.snap +151 -0
  22. package/src/components/Card/DataCard/__tests__/index.spec.tsx +30 -0
  23. package/src/components/Card/DataCard/index.tsx +35 -0
  24. package/src/components/Card/StyledCard.tsx +1 -3
  25. package/src/components/Card/__tests__/__snapshots__/StyledCard.spec.tsx.snap +0 -1
  26. package/src/components/Card/index.tsx +7 -2
  27. package/src/components/Checkbox/index.tsx +1 -1
  28. package/src/components/Collapse/index.tsx +1 -1
  29. package/src/components/Icon/HeroIcon/index.tsx +3 -1
  30. package/src/components/Icon/index.tsx +3 -2
  31. package/src/components/List/BasicListItem.tsx +98 -0
  32. package/src/components/List/ListItem.tsx +142 -0
  33. package/src/components/List/StyledBasicListItem.tsx +34 -0
  34. package/src/components/List/StyledListItem.tsx +82 -0
  35. package/src/components/List/__tests__/BasicListItem.spec.tsx +37 -0
  36. package/src/components/List/__tests__/ListItem.spec.tsx +110 -0
  37. package/src/components/List/__tests__/StyledBasicListItem.spec.tsx +24 -0
  38. package/src/components/List/__tests__/StyledListItem.spec.tsx +48 -0
  39. package/src/components/List/__tests__/__snapshots__/BasicListItem.spec.tsx.snap +103 -0
  40. package/src/components/List/__tests__/__snapshots__/ListItem.spec.tsx.snap +760 -0
  41. package/src/components/List/__tests__/__snapshots__/StyledBasicListItem.spec.tsx.snap +105 -0
  42. package/src/components/List/__tests__/__snapshots__/StyledListItem.spec.tsx.snap +200 -0
  43. package/src/components/List/index.tsx +14 -0
  44. package/src/components/SectionHeading/index.tsx +1 -1
  45. package/src/components/Select/Footer.tsx +13 -0
  46. package/src/components/Select/MultiSelect/Option.tsx +25 -0
  47. package/src/components/Select/MultiSelect/OptionList.tsx +30 -63
  48. package/src/components/Select/MultiSelect/__tests__/Option.spec.tsx +16 -0
  49. package/src/components/Select/MultiSelect/__tests__/OptionList.spec.tsx +42 -0
  50. package/src/components/Select/MultiSelect/__tests__/__snapshots__/Option.spec.tsx.snap +70 -0
  51. package/src/components/Select/MultiSelect/__tests__/__snapshots__/OptionList.spec.tsx.snap +627 -0
  52. package/src/components/Select/MultiSelect/__tests__/index.spec.tsx +6 -6
  53. package/src/components/Select/MultiSelect/index.tsx +8 -7
  54. package/src/components/Select/SingleSelect/Option.tsx +23 -0
  55. package/src/components/Select/SingleSelect/OptionList.tsx +43 -0
  56. package/src/components/Select/SingleSelect/__tests__/Option.spec.tsx +16 -0
  57. package/src/components/Select/SingleSelect/__tests__/OptionList.spec.tsx +42 -0
  58. package/src/components/Select/SingleSelect/__tests__/__snapshots__/Option.spec.tsx.snap +56 -0
  59. package/src/components/Select/SingleSelect/__tests__/__snapshots__/OptionList.spec.tsx.snap +571 -0
  60. package/src/components/Select/SingleSelect/__tests__/__snapshots__/index.spec.tsx.snap +1430 -0
  61. package/src/components/Select/SingleSelect/__tests__/index.spec.tsx +89 -0
  62. package/src/components/Select/SingleSelect/index.tsx +89 -0
  63. package/src/components/Select/{MultiSelect/StyledMultiSelect.tsx → StyledSelect.tsx} +1 -1
  64. package/src/components/Select/{MultiSelect/__tests__/StyledMultiSelect.spec.tsx → __tests__/StyledSelect.spec.tsx} +2 -2
  65. package/src/components/Select/{MultiSelect/__tests__/__snapshots__/StyledMultiSelect.spec.tsx.snap → __tests__/__snapshots__/StyledSelect.spec.tsx.snap} +0 -0
  66. package/src/components/Select/helpers.tsx +18 -0
  67. package/src/components/Select/index.tsx +4 -3
  68. package/src/components/Select/{MultiSelect/types.ts → types.ts} +0 -0
  69. package/src/components/Switch/index.tsx +1 -1
  70. package/src/components/Toast/__tests__/__snapshots__/Toast.spec.tsx.snap +2 -2
  71. package/src/components/Toolbar/StyledToolbar.tsx +42 -0
  72. package/src/components/Toolbar/ToolbarGroup.tsx +31 -0
  73. package/src/components/Toolbar/ToolbarItem.tsx +57 -0
  74. package/src/components/Toolbar/__tests__/ToolbarGroup.spec.tsx +32 -0
  75. package/src/components/Toolbar/__tests__/ToolbarItem.spec.tsx +57 -0
  76. package/src/components/Toolbar/__tests__/__snapshots__/ToolbarGroup.spec.tsx.snap +391 -0
  77. package/src/components/Toolbar/__tests__/__snapshots__/ToolbarItem.spec.tsx.snap +355 -0
  78. package/src/components/Toolbar/index.tsx +18 -0
  79. package/src/components/Typography/Text/StyledText.tsx +8 -1
  80. package/src/components/Typography/Text/__tests__/StyledText.spec.tsx +5 -0
  81. package/src/components/Typography/Text/__tests__/__snapshots__/StyledText.spec.tsx.snap +110 -0
  82. package/src/components/Typography/Text/index.tsx +9 -2
  83. package/src/index.ts +4 -0
  84. package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +83 -3
  85. package/src/theme/components/button.ts +2 -0
  86. package/src/theme/components/card.ts +13 -2
  87. package/src/theme/components/icon.ts +1 -0
  88. package/src/theme/components/list.ts +46 -0
  89. package/src/theme/components/toolbar.ts +27 -0
  90. package/src/theme/components/typography.ts +4 -0
  91. package/src/theme/global/colors.ts +9 -2
  92. package/src/theme/global/space.ts +2 -0
  93. package/src/theme/index.ts +6 -0
  94. package/tsconfig.json +1 -2
  95. package/types/components/Avatar/index.d.ts +1 -1
  96. package/types/components/Button/Button.d.ts +2 -2
  97. package/types/components/Button/LoadingIndicator/StyledLoadingIndicator.d.ts +1 -1
  98. package/types/components/Button/LoadingIndicator/index.d.ts +1 -1
  99. package/types/components/Button/StyledButton.d.ts +2 -2
  100. package/types/components/Card/DataCard/StyledDataCard.d.ts +16 -0
  101. package/types/components/{Select/MultiSelect/__tests__/StyledMultiSelect.spec.d.ts → Card/DataCard/__tests__/StyledDataCard.spec.d.ts} +0 -0
  102. package/types/components/Card/DataCard/__tests__/index.spec.d.ts +1 -0
  103. package/types/components/Card/DataCard/index.d.ts +22 -0
  104. package/types/components/Card/index.d.ts +7 -3
  105. package/types/components/Checkbox/index.d.ts +1 -1
  106. package/types/components/Collapse/index.d.ts +1 -1
  107. package/types/components/Icon/HeroIcon/index.d.ts +1 -1
  108. package/types/components/Icon/index.d.ts +2 -2
  109. package/types/components/List/BasicListItem.d.ts +43 -0
  110. package/types/components/List/ListItem.d.ts +51 -0
  111. package/types/components/List/StyledBasicListItem.d.ts +29 -0
  112. package/types/components/List/StyledListItem.d.ts +51 -0
  113. package/types/components/List/__tests__/BasicListItem.spec.d.ts +1 -0
  114. package/types/components/List/__tests__/ListItem.spec.d.ts +1 -0
  115. package/types/components/List/__tests__/StyledBasicListItem.spec.d.ts +1 -0
  116. package/types/components/List/__tests__/StyledListItem.spec.d.ts +1 -0
  117. package/types/components/List/index.d.ts +8 -0
  118. package/types/components/SectionHeading/index.d.ts +1 -1
  119. package/types/components/Select/{MultiSelect/Footer.d.ts → Footer.d.ts} +2 -2
  120. package/types/components/Select/MultiSelect/Option.d.ts +6 -0
  121. package/types/components/Select/MultiSelect/OptionList.d.ts +7 -1
  122. package/types/components/Select/MultiSelect/__tests__/Option.spec.d.ts +1 -0
  123. package/types/components/Select/MultiSelect/__tests__/OptionList.spec.d.ts +1 -0
  124. package/types/components/Select/MultiSelect/index.d.ts +4 -4
  125. package/types/components/Select/SingleSelect/Option.d.ts +6 -0
  126. package/types/components/Select/SingleSelect/OptionList.d.ts +9 -0
  127. package/types/components/Select/SingleSelect/__tests__/Option.spec.d.ts +1 -0
  128. package/types/components/Select/SingleSelect/__tests__/OptionList.spec.d.ts +1 -0
  129. package/types/components/Select/SingleSelect/__tests__/index.spec.d.ts +1 -0
  130. package/types/components/Select/SingleSelect/index.d.ts +35 -0
  131. package/types/components/Select/{MultiSelect/StyledMultiSelect.d.ts → StyledSelect.d.ts} +1 -1
  132. package/types/components/Select/__tests__/StyledSelect.spec.d.ts +1 -0
  133. package/types/components/Select/helpers.d.ts +2 -0
  134. package/types/components/Select/index.d.ts +3 -3
  135. package/types/components/Select/{MultiSelect/types.d.ts → types.d.ts} +0 -0
  136. package/types/components/Switch/index.d.ts +1 -1
  137. package/types/components/Toolbar/StyledToolbar.d.ts +22 -0
  138. package/types/components/Toolbar/ToolbarGroup.d.ts +13 -0
  139. package/types/components/Toolbar/ToolbarItem.d.ts +25 -0
  140. package/types/components/Toolbar/__tests__/ToolbarGroup.spec.d.ts +1 -0
  141. package/types/components/Toolbar/__tests__/ToolbarItem.spec.d.ts +1 -0
  142. package/types/components/Toolbar/index.d.ts +11 -0
  143. package/types/components/Typography/Text/StyledText.d.ts +1 -1
  144. package/types/components/Typography/Text/index.d.ts +2 -2
  145. package/types/index.d.ts +3 -1
  146. package/types/theme/components/button.d.ts +2 -0
  147. package/types/theme/components/card.d.ts +10 -0
  148. package/types/theme/components/icon.d.ts +1 -0
  149. package/types/theme/components/list.d.ts +40 -0
  150. package/types/theme/components/toolbar.d.ts +21 -0
  151. package/types/theme/components/typography.d.ts +4 -0
  152. package/types/theme/global/colors.d.ts +5 -0
  153. package/types/theme/global/index.d.ts +5 -0
  154. package/types/theme/global/space.d.ts +1 -0
  155. package/types/theme/index.d.ts +4 -0
  156. package/playground/.detoxrc.json +0 -49
  157. package/playground/.prettierrc.json +0 -8
  158. package/playground/.turbo/turbo-type-check.log +0 -7
  159. package/playground/app.json +0 -9
  160. package/playground/babel.config.js +0 -63
  161. package/playground/e2e/config.json +0 -9
  162. package/playground/e2e/environment.js +0 -23
  163. package/playground/e2e/firstTest.e2e.js +0 -16
  164. package/playground/expoEntry.js +0 -5
  165. package/playground/fonts/be-vietnam-pro-light.ttf +0 -0
  166. package/playground/fonts/be-vietnam-pro-regular.ttf +0 -0
  167. package/playground/fonts/be-vietnam-pro-semibold.ttf +0 -0
  168. package/playground/fonts/hero-icons.ttf +0 -0
  169. package/playground/index.js +0 -7
  170. package/playground/ios/MobileHeroDesignPlayground/AppDelegate.h +0 -9
  171. package/playground/ios/MobileHeroDesignPlayground/AppDelegate.m +0 -75
  172. package/playground/ios/MobileHeroDesignPlayground/Images.xcassets/AppIcon.appiconset/Contents.json +0 -38
  173. package/playground/ios/MobileHeroDesignPlayground/Images.xcassets/Contents.json +0 -6
  174. package/playground/ios/MobileHeroDesignPlayground/Images.xcassets/SplashScreenBackground.imageset/Contents.json +0 -21
  175. package/playground/ios/MobileHeroDesignPlayground/Images.xcassets/SplashScreenBackground.imageset/image.png +0 -0
  176. package/playground/ios/MobileHeroDesignPlayground/Info.plist +0 -85
  177. package/playground/ios/MobileHeroDesignPlayground/MobileHeroDesignPlayground-Bridging-Header.h +0 -3
  178. package/playground/ios/MobileHeroDesignPlayground/MobileHeroDesignPlayground.entitlements +0 -8
  179. package/playground/ios/MobileHeroDesignPlayground/SplashScreen.storyboard +0 -40
  180. package/playground/ios/MobileHeroDesignPlayground/Supporting/Expo.plist +0 -16
  181. package/playground/ios/MobileHeroDesignPlayground/main.m +0 -10
  182. package/playground/ios/MobileHeroDesignPlayground/noop-file.swift +0 -4
  183. package/playground/ios/MobileHeroDesignPlayground.xcodeproj/project.pbxproj +0 -515
  184. package/playground/ios/MobileHeroDesignPlayground.xcodeproj/xcshareddata/xcschemes/MobileHeroDesignPlayground.xcscheme +0 -88
  185. package/playground/ios/MobileHeroDesignPlayground.xcworkspace/contents.xcworkspacedata +0 -10
  186. package/playground/ios/MobileHeroDesignPlayground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  187. package/playground/ios/Podfile +0 -49
  188. package/playground/ios/Podfile.lock +0 -478
  189. package/playground/ios/Podfile.properties.json +0 -3
  190. package/playground/metro.config.js +0 -24
  191. package/playground/package.json +0 -63
  192. package/playground/src/Alert.tsx +0 -80
  193. package/playground/src/App.tsx +0 -210
  194. package/playground/src/Avatar.tsx +0 -102
  195. package/playground/src/Badge.tsx +0 -187
  196. package/playground/src/BottomNavigation.tsx +0 -72
  197. package/playground/src/BottomSheet.tsx +0 -43
  198. package/playground/src/Button.tsx +0 -170
  199. package/playground/src/Card.tsx +0 -342
  200. package/playground/src/Checkbox.tsx +0 -55
  201. package/playground/src/Collapse.tsx +0 -99
  202. package/playground/src/ContentNavigator.tsx +0 -58
  203. package/playground/src/Divider.tsx +0 -13
  204. package/playground/src/Drawer.tsx +0 -32
  205. package/playground/src/FAB.tsx +0 -66
  206. package/playground/src/Icon.tsx +0 -144
  207. package/playground/src/IconButton.tsx +0 -78
  208. package/playground/src/MultipleThemes.tsx +0 -34
  209. package/playground/src/Progress.tsx +0 -95
  210. package/playground/src/Radio.tsx +0 -25
  211. package/playground/src/SectionHeading.tsx +0 -68
  212. package/playground/src/Select.tsx +0 -32
  213. package/playground/src/Spinner.tsx +0 -19
  214. package/playground/src/Switch.tsx +0 -80
  215. package/playground/src/Tabs.tsx +0 -136
  216. package/playground/src/Tag.tsx +0 -45
  217. package/playground/src/TextInput.tsx +0 -14
  218. package/playground/src/Toast.tsx +0 -114
  219. package/playground/src/Typography.tsx +0 -23
  220. package/playground/tsconfig.json +0 -21
  221. package/src/components/Select/MultiSelect/Footer.tsx +0 -15
@@ -0,0 +1,35 @@
1
+ import React, { ReactNode } from 'react';
2
+ import { StyleProp, ViewStyle, ViewProps } from 'react-native';
3
+ import { StyledDataCard, Indicator } from './StyledDataCard';
4
+
5
+ export interface DataCardProps extends ViewProps {
6
+ /**
7
+ * Card's content.
8
+ */
9
+ children?: ReactNode;
10
+ /**
11
+ * Visual intent color to apply to card.
12
+ */
13
+ intent?: 'success' | 'info' | 'warning' | 'danger' | 'archived';
14
+ /**
15
+ * Additional style.
16
+ */
17
+ style?: StyleProp<ViewStyle>;
18
+ /**
19
+ * Testing id of the component.
20
+ */
21
+ testID?: string;
22
+ }
23
+
24
+ const DataCard = ({
25
+ intent = 'info',
26
+ children,
27
+ ...nativeProps
28
+ }: DataCardProps): JSX.Element => (
29
+ <StyledDataCard {...nativeProps}>
30
+ <Indicator themeIntent={intent} testID="data-card-indicator" />
31
+ {children}
32
+ </StyledDataCard>
33
+ );
34
+
35
+ export default DataCard;
@@ -1,6 +1,5 @@
1
1
  import { View } from 'react-native';
2
2
  import styled from '@emotion/native';
3
- import { scale } from '../../utils/scale';
4
3
 
5
4
  const StyledCard = styled(View)<{ themeVariant: 'basic' | 'data' }>(
6
5
  ({ themeVariant, theme }) => {
@@ -10,7 +9,6 @@ const StyledCard = styled(View)<{ themeVariant: 'basic' | 'data' }>(
10
9
  } as const;
11
10
 
12
11
  const dataStyles = {
13
- flex: 1,
14
12
  flexDirection: 'row',
15
13
  };
16
14
 
@@ -25,7 +23,7 @@ const StyledCard = styled(View)<{ themeVariant: 'basic' | 'data' }>(
25
23
 
26
24
  const LeftDataCard = styled(View)(({ theme }) => ({
27
25
  backgroundColor: theme.__hd__.card.colors.dataCardIndicator,
28
- width: scale(16),
26
+ width: theme.__hd__.card.sizes.indicatorWidth,
29
27
  height: '100%',
30
28
  }));
31
29
 
@@ -36,7 +36,6 @@ exports[`StyledCard renders correct data style 1`] = `
36
36
  Array [
37
37
  Object {
38
38
  "borderRadius": 12,
39
- "flex": 1,
40
39
  "flexDirection": "row",
41
40
  "overflow": "hidden",
42
41
  },
@@ -1,5 +1,6 @@
1
1
  import React, { ReactNode } from 'react';
2
2
  import { StyleProp, ViewStyle, ViewProps } from 'react-native';
3
+ import DataCard from './DataCard';
3
4
  import { StyledCard, LeftDataCard } from './StyledCard';
4
5
 
5
6
  interface CardProps extends ViewProps {
@@ -9,10 +10,12 @@ interface CardProps extends ViewProps {
9
10
  children?: ReactNode;
10
11
  /**
11
12
  * Card type.
13
+ * This is now deprecated. If you want to use "data" variant, please use Card.Data instead.
14
+ * @deprecated
12
15
  */
13
16
  variant?: 'basic' | 'data';
14
17
  /**
15
- * Addditional style.
18
+ * Additional style.
16
19
  */
17
20
  style?: StyleProp<ViewStyle>;
18
21
  /**
@@ -32,4 +35,6 @@ const Card = ({
32
35
  </StyledCard>
33
36
  );
34
37
 
35
- export default Card;
38
+ export default Object.assign(Card, {
39
+ Data: DataCard,
40
+ });
@@ -18,7 +18,7 @@ export interface CheckboxProps {
18
18
  */
19
19
  onPress?: () => void;
20
20
  /**
21
- * Addditional style.
21
+ * Additional style.
22
22
  */
23
23
  style?: StyleProp<ViewStyle>;
24
24
  /**
@@ -23,7 +23,7 @@ interface CollapseProps extends ViewProps {
23
23
  */
24
24
  open?: boolean;
25
25
  /**
26
- * Addditional style.
26
+ * Additional style.
27
27
  */
28
28
  style?: StyleProp<ViewStyle>;
29
29
  /**
@@ -10,7 +10,8 @@ type ThemeIntent =
10
10
  | 'danger'
11
11
  | 'success'
12
12
  | 'warning'
13
- | 'disabled-text';
13
+ | 'disabled-text'
14
+ | 'text-inverted';
14
15
 
15
16
  const HeroIcon = createIconSetFromIcoMoon(
16
17
  heroIconConfig,
@@ -26,6 +27,7 @@ const COLOR_INTENTS = {
26
27
  success: 'success',
27
28
  warning: 'warning',
28
29
  'disabled-text': 'disabledText',
30
+ 'text-inverted': 'invertedText',
29
31
  } as const;
30
32
 
31
33
  const StyledHeroIcon = styled(HeroIcon)<{
@@ -20,13 +20,14 @@ export interface IconProps {
20
20
  | 'danger'
21
21
  | 'success'
22
22
  | 'warning'
23
- | 'disabled-text';
23
+ | 'disabled-text'
24
+ | 'text-inverted';
24
25
  /**
25
26
  * Size of the Icon.
26
27
  */
27
28
  size?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
28
29
  /**
29
- * Addditional style.
30
+ * Additional style.
30
31
  */
31
32
  style?: StyleProp<TextStyle>;
32
33
  /**
@@ -0,0 +1,98 @@
1
+ import React from 'react';
2
+
3
+ import { StyleProp, ViewStyle } from 'react-native';
4
+ import Icon, { IconName } from '../Icon';
5
+ import Typography from '../Typography';
6
+ import {
7
+ StyledPrefixContainer,
8
+ StyledSuffixContainer,
9
+ StyledTitleContainer,
10
+ StyledListItemContainer,
11
+ } from './StyledBasicListItem';
12
+
13
+ export interface ListItemProps {
14
+ /**
15
+ * Name of Icon or component to render on the left side of title.
16
+ */
17
+ prefix?: IconName | React.ReactElement;
18
+ /**
19
+ * Name of Icon or component to render on the right side of title.
20
+ */
21
+ suffix?: IconName | React.ReactElement;
22
+ /**
23
+ * The title of the component.
24
+ */
25
+ title: string;
26
+ /**
27
+ * The subtile title of the component.
28
+ */
29
+ subtitle?: string;
30
+ /**
31
+ * Whether the component is disabled. Default value is false
32
+ */
33
+ disabled?: boolean;
34
+ /**
35
+ * Whether the component is selected. Default value is false
36
+ */
37
+ selected?: boolean;
38
+ /**
39
+ * Additional wrapper style.
40
+ */
41
+ style?: StyleProp<ViewStyle>;
42
+ /**
43
+ * Testing id of the component.
44
+ */
45
+ testID?: string;
46
+ /**
47
+ * Set the handler to handle press event.
48
+ */
49
+ onPress?: () => void;
50
+ }
51
+
52
+ const BasicListItem = ({
53
+ prefix,
54
+ suffix,
55
+ title,
56
+ subtitle,
57
+ style,
58
+ testID,
59
+ selected = false,
60
+ disabled = false,
61
+ onPress,
62
+ }: ListItemProps): JSX.Element => (
63
+ <StyledListItemContainer
64
+ style={style}
65
+ testID={testID}
66
+ themeSelected={selected}
67
+ themeDisabled={disabled}
68
+ onPress={onPress}
69
+ disabled={disabled}
70
+ >
71
+ {prefix && (
72
+ <StyledPrefixContainer>
73
+ {typeof prefix === 'string' ? <Icon icon={prefix} /> : prefix}
74
+ </StyledPrefixContainer>
75
+ )}
76
+ <StyledTitleContainer>
77
+ <Typography.Text intent="body" fontSize="large">
78
+ {title}
79
+ </Typography.Text>
80
+ {subtitle && (
81
+ <Typography.Text intent="subdued" fontSize="small">
82
+ {subtitle}
83
+ </Typography.Text>
84
+ )}
85
+ </StyledTitleContainer>
86
+ {suffix && (
87
+ <StyledSuffixContainer>
88
+ {typeof suffix === 'string' ? (
89
+ <Icon icon={suffix} intent="text" size="small" />
90
+ ) : (
91
+ suffix
92
+ )}
93
+ </StyledSuffixContainer>
94
+ )}
95
+ </StyledListItemContainer>
96
+ );
97
+
98
+ export default BasicListItem;
@@ -0,0 +1,142 @@
1
+ import React, { ReactNode } from 'react';
2
+
3
+ import { StyleProp, ViewStyle, View } from 'react-native';
4
+ import Icon, { IconName } from '../Icon';
5
+ import Typography from '../Typography';
6
+ import {
7
+ StyledListItemContainer,
8
+ StyledChildrenContainer,
9
+ StyledLeadingStatus,
10
+ StyledContentContainer,
11
+ StyledPrefixContainer,
12
+ StyledSuffixContainer,
13
+ StyledTitleContainer,
14
+ } from './StyledListItem';
15
+
16
+ export interface ListItemProps {
17
+ /**
18
+ * Name of Icon or ReactElement to render on the left side of title.
19
+ */
20
+ prefix?: IconName | React.ReactElement;
21
+ /**
22
+ * Name of Icon or ReactElement to render on the right side of title.
23
+ */
24
+ suffix?: IconName | React.ReactElement;
25
+ /**
26
+ * The title of the component.
27
+ */
28
+ title?: string;
29
+ /**
30
+ * The subtile title of the component.
31
+ */
32
+ subtitle?: string;
33
+ /**
34
+ * Additional wrapper style.
35
+ */
36
+ style?: StyleProp<ViewStyle>;
37
+ /**
38
+ * Children to be rendered inside the component.
39
+ */
40
+ children?: ReactNode;
41
+ /**
42
+ * Leading status of the component
43
+ * */
44
+ leadingStatus?: 'success' | 'warning' | 'danger' | 'info' | 'archived';
45
+
46
+ /*
47
+ * Card styles. Default is `full-width`
48
+ */
49
+ variant?: 'full-width' | 'card';
50
+ /**
51
+ * Whether the component is disabled. Default value is false
52
+ */
53
+ disabled?: boolean;
54
+ /** * Whether the component is selected. Default value is false
55
+ */
56
+ selected?: boolean;
57
+ /**
58
+ * Testing id of the component.
59
+ */
60
+ testID?: string;
61
+ /**
62
+ * Set the handler to handle press event.
63
+ */
64
+ onPress?: () => void;
65
+ }
66
+
67
+ const ListItem = ({
68
+ prefix,
69
+ suffix,
70
+ title,
71
+ subtitle,
72
+ style,
73
+ testID,
74
+ selected = false,
75
+ children,
76
+ leadingStatus,
77
+ variant = 'full-width',
78
+ onPress,
79
+ disabled = false,
80
+ }: ListItemProps): JSX.Element => (
81
+ <StyledListItemContainer
82
+ style={style}
83
+ testID={testID}
84
+ themeSelected={selected}
85
+ themeVariant={variant}
86
+ onPress={onPress}
87
+ disabled={disabled}
88
+ >
89
+ {leadingStatus && (
90
+ <StyledLeadingStatus
91
+ themeLeadingStatusIntent={leadingStatus}
92
+ testID="leadingStatus"
93
+ />
94
+ )}
95
+ <StyledContentContainer>
96
+ <View
97
+ style={{
98
+ flexDirection: 'row',
99
+ alignItems: 'center',
100
+ }}
101
+ >
102
+ {prefix && (
103
+ <StyledPrefixContainer>
104
+ {typeof prefix === 'string' ? <Icon icon={prefix} /> : prefix}
105
+ </StyledPrefixContainer>
106
+ )}
107
+ <StyledTitleContainer>
108
+ <Typography.Text
109
+ intent="body"
110
+ fontSize="large"
111
+ fontWeight="semi-bold"
112
+ >
113
+ {title}
114
+ </Typography.Text>
115
+ {subtitle && (
116
+ <Typography.Text intent="subdued" fontSize="small">
117
+ {subtitle}
118
+ </Typography.Text>
119
+ )}
120
+ </StyledTitleContainer>
121
+ {suffix && (
122
+ <StyledSuffixContainer>
123
+ {typeof suffix === 'string' ? (
124
+ <Icon
125
+ icon={suffix}
126
+ intent={disabled ? 'disabled-text' : 'primary'}
127
+ size="small"
128
+ />
129
+ ) : (
130
+ suffix
131
+ )}
132
+ </StyledSuffixContainer>
133
+ )}
134
+ </View>
135
+ {children && (
136
+ <StyledChildrenContainer>{children}</StyledChildrenContainer>
137
+ )}
138
+ </StyledContentContainer>
139
+ </StyledListItemContainer>
140
+ );
141
+
142
+ export default ListItem;
@@ -0,0 +1,34 @@
1
+ import styled from '@emotion/native';
2
+ import { TouchableOpacity, View } from 'react-native';
3
+
4
+ const StyledPrefixContainer = styled(View)(({ theme }) => ({
5
+ marginRight: theme.__hd__.list.space.prefixContainerMarginRight,
6
+ }));
7
+ const StyledSuffixContainer = styled(View)(({ theme }) => ({
8
+ marginLeft: theme.__hd__.list.space.suffixContainerMarginLeft,
9
+ }));
10
+ const StyledTitleContainer = styled(View)(() => ({
11
+ flex: 1,
12
+ }));
13
+
14
+ const StyledListItemContainer = styled(TouchableOpacity)<{
15
+ themeSelected?: boolean;
16
+ themeDisabled?: boolean;
17
+ }>(({ theme, themeSelected, themeDisabled }) => ({
18
+ alignItems: 'center',
19
+ flex: 1,
20
+ flexDirection: 'row',
21
+ backgroundColor: themeSelected
22
+ ? theme.__hd__.select.colors.checkedOption
23
+ : theme.__hd__.select.colors.option,
24
+ padding: theme.__hd__.list.space.listItemContainerPadding,
25
+ opacity: themeDisabled
26
+ ? theme.__hd__.list.opacity.disabled
27
+ : theme.__hd__.list.opacity.enabled,
28
+ }));
29
+ export {
30
+ StyledListItemContainer,
31
+ StyledPrefixContainer,
32
+ StyledTitleContainer,
33
+ StyledSuffixContainer,
34
+ };
@@ -0,0 +1,82 @@
1
+ import { TouchableOpacity, View } from 'react-native';
2
+ import styled from '@emotion/native';
3
+
4
+ export type Variant = 'full-width' | 'card';
5
+ export type LeadingStatusIntent =
6
+ | 'success'
7
+ | 'warning'
8
+ | 'danger'
9
+ | 'info'
10
+ | 'archived';
11
+
12
+ const StyledListItemContainer = styled(TouchableOpacity)<{
13
+ themeSelected?: boolean;
14
+ themeVariant?: Variant;
15
+ }>(({ theme, themeSelected = false, themeVariant = 'basic' }) => {
16
+ const sharedStyles = {
17
+ flexDirection: 'row' as const,
18
+ backgroundColor: themeSelected
19
+ ? theme.__hd__.list.colors.checkedListItemContainerBackground
20
+ : theme.__hd__.list.colors.listItemContainerBackground,
21
+ padding: theme.__hd__.list.space.listItemContainerPadding,
22
+ };
23
+
24
+ switch (themeVariant) {
25
+ case 'basic':
26
+ return sharedStyles;
27
+ case 'card':
28
+ return {
29
+ ...sharedStyles,
30
+ alignItems: 'center',
31
+ borderRadius: theme.__hd__.list.radii.card,
32
+ shadowColor: theme.colors.shadow,
33
+ shadowRadius: theme.__hd__.list.radii.cardShadow,
34
+ shadowOffset: theme.__hd__.list.offsets.cardShadow,
35
+ shadowOpacity: theme.__hd__.list.opacity.cardShadow,
36
+ };
37
+ default:
38
+ return sharedStyles;
39
+ }
40
+ });
41
+
42
+ const StyledContentContainer = styled(View)(() => ({
43
+ flexDirection: 'column',
44
+ flex: 1,
45
+ flexGrow: 2,
46
+ }));
47
+
48
+ const StyledChildrenContainer = styled(View)(() => ({
49
+ flexDirection: 'column',
50
+ justifyContent: 'flex-start',
51
+ alignItems: 'flex-start',
52
+ }));
53
+
54
+ const StyledLeadingStatus = styled(View)<{
55
+ themeLeadingStatusIntent: LeadingStatusIntent;
56
+ }>(({ theme, themeLeadingStatusIntent }) => ({
57
+ width: theme.__hd__.list.widths.leadingStatus,
58
+ marginRight: theme.__hd__.list.space.leadingStatusMarginRight,
59
+ borderRadius: theme.__hd__.list.radii.leadingStatus,
60
+ backgroundColor:
61
+ theme.__hd__.list.colors.leadingStatus[themeLeadingStatusIntent],
62
+ }));
63
+
64
+ const StyledPrefixContainer = styled(View)(({ theme }) => ({
65
+ marginRight: theme.__hd__.list.space.prefixContainerMarginRight,
66
+ }));
67
+ const StyledSuffixContainer = styled(View)(({ theme }) => ({
68
+ marginLeft: theme.__hd__.list.space.suffixContainerMarginLeft,
69
+ }));
70
+ const StyledTitleContainer = styled(View)(() => ({
71
+ flex: 1,
72
+ }));
73
+
74
+ export {
75
+ StyledListItemContainer,
76
+ StyledContentContainer,
77
+ StyledChildrenContainer,
78
+ StyledLeadingStatus,
79
+ StyledPrefixContainer,
80
+ StyledTitleContainer,
81
+ StyledSuffixContainer,
82
+ };
@@ -0,0 +1,37 @@
1
+ import { fireEvent } from '@testing-library/react-native';
2
+ import React from 'react';
3
+ import renderWithTheme from '../../../testHelpers/renderWithTheme';
4
+ import BasicListItem from '../BasicListItem';
5
+
6
+ describe('BasicListItem', () => {
7
+ it('renders correctly', () => {
8
+ const wrapper = renderWithTheme(
9
+ <BasicListItem
10
+ title="List item"
11
+ subtitle="subtitle"
12
+ suffix="checkmark"
13
+ testID="basic-list-item"
14
+ />
15
+ );
16
+ expect(wrapper.toJSON()).toMatchSnapshot();
17
+ expect(wrapper.queryAllByTestId('basic-list-item')).toHaveLength(1);
18
+ expect(wrapper.queryAllByText('List item')).toHaveLength(1);
19
+ expect(wrapper.queryAllByText('subtitle')).toHaveLength(1);
20
+ });
21
+
22
+ it('onPress', () => {
23
+ const onPress = jest.fn();
24
+ const { getByTestId } = renderWithTheme(
25
+ <BasicListItem
26
+ title="List item"
27
+ subtitle="subtitle"
28
+ suffix="checkmark"
29
+ testID="basic-list-item"
30
+ onPress={onPress}
31
+ />
32
+ );
33
+
34
+ fireEvent.press(getByTestId('basic-list-item'));
35
+ expect(onPress).toHaveBeenCalledTimes(1);
36
+ });
37
+ });
@@ -0,0 +1,110 @@
1
+ import { fireEvent } from '@testing-library/react-native';
2
+ import React from 'react';
3
+ import { View } from 'react-native';
4
+ import renderWithTheme from '../../../testHelpers/renderWithTheme';
5
+ import Avatar from '../../Avatar';
6
+ import Switch from '../../Switch';
7
+ import Typography from '../../Typography';
8
+ import ListItem from '../ListItem';
9
+
10
+ describe('ListItem', () => {
11
+ it('renders correctly ListItem with icon', () => {
12
+ const wrapper = renderWithTheme(
13
+ <ListItem
14
+ title="List item"
15
+ subtitle="subtitle"
16
+ suffix="checkmark"
17
+ testID="list-item"
18
+ />
19
+ );
20
+ expect(wrapper.toJSON()).toMatchSnapshot();
21
+ expect(wrapper.queryAllByTestId('list-item')).toHaveLength(1);
22
+ expect(wrapper.queryAllByText('List item')).toHaveLength(1);
23
+ expect(wrapper.queryAllByText('subtitle')).toHaveLength(1);
24
+ expect(wrapper.queryAllByTestId('leadingStatus')).toHaveLength(0);
25
+ });
26
+
27
+ it('renders correctly ListItem with prefix suffix is React.Element', () => {
28
+ const wrapper = renderWithTheme(
29
+ <ListItem
30
+ prefix={<Avatar title="ML" />}
31
+ suffix={<Switch checked testID="switch" />}
32
+ title="List item"
33
+ subtitle="subtitle"
34
+ testID="list-item"
35
+ />
36
+ );
37
+ expect(wrapper.toJSON()).toMatchSnapshot();
38
+ expect(wrapper.queryAllByTestId('list-item')).toHaveLength(1);
39
+ expect(wrapper.queryAllByText('List item')).toHaveLength(1);
40
+ expect(wrapper.queryAllByText('subtitle')).toHaveLength(1);
41
+ expect(wrapper.queryAllByText('ML')).toHaveLength(1);
42
+ expect(wrapper.queryAllByTestId('switch')).toHaveLength(1);
43
+ });
44
+
45
+ it('renders correctly ListItem with children', () => {
46
+ const wrapper = renderWithTheme(
47
+ <ListItem
48
+ prefix={<Avatar title="ML" />}
49
+ suffix="arrow-right"
50
+ title="Menu List"
51
+ subtitle="Got a common question?"
52
+ >
53
+ <View
54
+ style={{
55
+ flexDirection: 'row',
56
+ alignSelf: 'stretch',
57
+ justifyContent: 'space-between',
58
+ }}
59
+ >
60
+ <Typography.Text>Gross pay</Typography.Text>
61
+ <Typography.Text>$1052.03</Typography.Text>
62
+ </View>
63
+ <View
64
+ style={{
65
+ flexDirection: 'row',
66
+ alignSelf: 'stretch',
67
+ justifyContent: 'space-between',
68
+ }}
69
+ >
70
+ <Typography.Text>Gross pay</Typography.Text>
71
+ <Typography.Text>$1052.03</Typography.Text>
72
+ </View>
73
+ </ListItem>
74
+ );
75
+ expect(wrapper.toJSON()).toMatchSnapshot();
76
+ expect(wrapper.queryAllByText('Menu List')).toHaveLength(1);
77
+ expect(wrapper.queryAllByText('Got a common question?')).toHaveLength(1);
78
+ expect(wrapper.queryAllByText('ML')).toHaveLength(1);
79
+ expect(wrapper.queryAllByText('Gross pay')).toHaveLength(2);
80
+ expect(wrapper.queryAllByText('$1052.03')).toHaveLength(2);
81
+ });
82
+
83
+ it('renders correctly ListItem with leading status', () => {
84
+ const wrapper = renderWithTheme(
85
+ <ListItem
86
+ leadingStatus="archived"
87
+ suffix="arrow-right"
88
+ title="03:00 PM - 9:00 PM"
89
+ />
90
+ );
91
+ expect(wrapper.toJSON()).toMatchSnapshot();
92
+ expect(wrapper.queryAllByText('03:00 PM - 9:00 PM')).toHaveLength(1);
93
+ expect(wrapper.queryAllByTestId('leadingStatus')).toHaveLength(1);
94
+ });
95
+ it('onPress', () => {
96
+ const onPress = jest.fn();
97
+ const { getByTestId } = renderWithTheme(
98
+ <ListItem
99
+ title="List item"
100
+ subtitle="subtitle"
101
+ suffix="checkmark"
102
+ testID="list-item"
103
+ onPress={onPress}
104
+ />
105
+ );
106
+
107
+ fireEvent.press(getByTestId('list-item'));
108
+ expect(onPress).toHaveBeenCalledTimes(1);
109
+ });
110
+ });
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import renderWithTheme from '../../../testHelpers/renderWithTheme';
3
+ import { StyledListItemContainer } from '../StyledBasicListItem';
4
+
5
+ describe('ListItemContainer', () => {
6
+ it.each`
7
+ themeSelected | themeDisabled
8
+ ${true} | ${false}
9
+ ${false} | ${true}
10
+ ${false} | ${false}
11
+ ${true} | ${true}
12
+ `(
13
+ 'renders correctly themeSelected $themeSelected themeDisabled $themeDisabled',
14
+ ({ themeSelected, themeDisabled }) => {
15
+ const { toJSON } = renderWithTheme(
16
+ <StyledListItemContainer
17
+ themeSelected={themeSelected}
18
+ themeDisabled={themeDisabled}
19
+ />
20
+ );
21
+ expect(toJSON()).toMatchSnapshot();
22
+ }
23
+ );
24
+ });