@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,89 @@
1
+ import { fireEvent } from '@testing-library/react-native';
2
+ import React from 'react';
3
+ import renderWithTheme from '../../../../testHelpers/renderWithTheme';
4
+ import SingleSelect from '..';
5
+
6
+ const options = [
7
+ { text: 'Monday', value: 'mon' },
8
+ { text: 'Tuesday', value: 'tue' },
9
+ { text: 'Wednesday', value: 'wed' },
10
+ { text: 'Thursday', value: 'thu' },
11
+ { text: 'Friday', value: 'fri' },
12
+ { text: 'Saturday', value: 'sat' },
13
+ { text: 'Sunday', value: 'sun' },
14
+ ];
15
+
16
+ describe('rendering', () => {
17
+ it('renders correctly when bottom sheet is NOT visible', () => {
18
+ const { queryAllByText, toJSON, getByTestId } = renderWithTheme(
19
+ <SingleSelect
20
+ label="Allow notifications"
21
+ options={options}
22
+ value="mon"
23
+ onConfirm={jest.fn()}
24
+ />
25
+ );
26
+
27
+ expect(toJSON()).toMatchSnapshot();
28
+ expect(queryAllByText('Allow notifications')).toHaveLength(2);
29
+ expect(getByTestId('text-input').props.value).toBe('Monday');
30
+ });
31
+
32
+ it('renders correctly when bottom sheet is visible', () => {
33
+ const { queryAllByText, getByText, toJSON, getByTestId } = renderWithTheme(
34
+ <SingleSelect
35
+ label="Allow notifications"
36
+ options={options}
37
+ value="mon"
38
+ onConfirm={jest.fn()}
39
+ />
40
+ );
41
+ fireEvent.press(getByTestId('text-input'));
42
+
43
+ expect(toJSON()).toMatchSnapshot();
44
+ expect(queryAllByText('Allow notifications')).toHaveLength(2);
45
+ expect(getByText('Monday')).toBeDefined();
46
+ expect(getByText('Tuesday')).toBeDefined();
47
+ expect(getByText('Wednesday')).toBeDefined();
48
+ expect(getByText('Thursday')).toBeDefined();
49
+ expect(getByText('Friday')).toBeDefined();
50
+ expect(getByText('Saturday')).toBeDefined();
51
+ expect(getByText('Sunday')).toBeDefined();
52
+ });
53
+ });
54
+
55
+ describe('behavior', () => {
56
+ it('calls onConfirm when pressing footer of bottom sheet', () => {
57
+ const onPress = jest.fn();
58
+ const { getByText, getByTestId } = renderWithTheme(
59
+ <SingleSelect
60
+ label="Allow notifications"
61
+ options={options}
62
+ value="mon"
63
+ onConfirm={onPress}
64
+ testID="single-select"
65
+ />
66
+ );
67
+ fireEvent.press(getByTestId('single-select'));
68
+ fireEvent.press(getByText('Monday'));
69
+
70
+ expect(onPress).toBeCalledTimes(1);
71
+ });
72
+
73
+ it('does NOT call onConfirm when pressing closing button of bottom sheet', () => {
74
+ const onPress = jest.fn();
75
+ const { getByTestId } = renderWithTheme(
76
+ <SingleSelect
77
+ label="Allow notifications"
78
+ options={options}
79
+ value="mon"
80
+ onConfirm={onPress}
81
+ testID="single-select"
82
+ />
83
+ );
84
+ fireEvent.press(getByTestId('single-select'));
85
+ fireEvent.press(getByTestId('bottom-sheet-close-icon'));
86
+
87
+ expect(onPress).toBeCalledTimes(0);
88
+ });
89
+ });
@@ -0,0 +1,89 @@
1
+ import { useTheme } from '@emotion/react';
2
+ import React, { useState } from 'react';
3
+ import { StyleProp, ViewStyle, TouchableOpacity } from 'react-native';
4
+
5
+ import { OptionType } from '../types';
6
+ import BottomSheet from '../../BottomSheet';
7
+ import OptionList from './OptionList';
8
+ import TextInput from '../../TextInput';
9
+
10
+ export interface SingleSelectProps<T> {
11
+ /**
12
+ * An array of options to be selected.
13
+ */
14
+ options: OptionType<T>[];
15
+ /**
16
+ * Current selected value.
17
+ */
18
+ value: T | null;
19
+ /**
20
+ * event handler for confirm button
21
+ */
22
+ onConfirm: (value: T | null) => void;
23
+ /**
24
+ * Field label.
25
+ */
26
+ label: string;
27
+ /**
28
+ * Used to extract a unique key for a given option at the specified index. Key is used for caching and as the react key to track item re-ordering.
29
+ * The default extractor checks option.key, and then falls back to using the index, like React does.
30
+ */
31
+ keyExtractor?: (option: OptionType<T>, index?: number) => string;
32
+ /**
33
+ * Additional style.
34
+ */
35
+ style?: StyleProp<ViewStyle>;
36
+ /**
37
+ * Testing id of the component.
38
+ */
39
+ testID?: string;
40
+ }
41
+
42
+ const SingleSelect = <T,>({
43
+ options,
44
+ value,
45
+ testID,
46
+ style,
47
+ label,
48
+ onConfirm,
49
+ }: SingleSelectProps<T>) => {
50
+ const theme = useTheme();
51
+ const [open, setOpen] = useState(false);
52
+ const [selectingValue, setSelectingValue] = useState<T | null>(value);
53
+ const displayedValue = options.find(opt => value === opt.value)?.text;
54
+
55
+ return (
56
+ <TouchableOpacity onPress={() => setOpen(true)}>
57
+ <TextInput
58
+ label={label}
59
+ value={displayedValue}
60
+ onPressIn={() => setOpen(true)}
61
+ editable={false}
62
+ // when input is not editable on Android, the text color is gray
63
+ // hence, adding this to make the text color the same as iOS
64
+ textStyle={{ color: theme.colors.text }}
65
+ suffix="arrow-down"
66
+ multiline
67
+ style={style}
68
+ testID={testID}
69
+ />
70
+ <BottomSheet
71
+ open={open}
72
+ onRequestClose={() => setOpen(false)}
73
+ onDismiss={() => setSelectingValue(value)}
74
+ header={label}
75
+ >
76
+ <OptionList
77
+ options={options}
78
+ value={selectingValue}
79
+ onPress={selectedValue => {
80
+ setOpen(false);
81
+ onConfirm(selectedValue);
82
+ }}
83
+ />
84
+ </BottomSheet>
85
+ </TouchableOpacity>
86
+ );
87
+ };
88
+
89
+ export default SingleSelect;
@@ -1,6 +1,6 @@
1
1
  import { View, TouchableOpacity } from 'react-native';
2
2
  import styled from '@emotion/native';
3
- import Typography from '../../Typography';
3
+ import Typography from '../Typography';
4
4
 
5
5
  const OptionWrapper = styled(TouchableOpacity)<{ themeSelected: boolean }>(
6
6
  ({ theme, themeSelected }) => ({
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
- import renderWithTheme from '../../../../testHelpers/renderWithTheme';
2
+ import renderWithTheme from '../../../testHelpers/renderWithTheme';
3
3
  import {
4
4
  OptionWrapper,
5
5
  OptionListWrapper,
6
6
  Spacer,
7
7
  FooterText,
8
- } from '../StyledMultiSelect';
8
+ } from '../StyledSelect';
9
9
 
10
10
  describe('OptionWrapper', () => {
11
11
  it.each`
@@ -0,0 +1,18 @@
1
+ import { OptionType } from './types';
2
+
3
+ export const getKey = <T,>(
4
+ option: OptionType<T>,
5
+ index: number,
6
+ keyExtractor?: (opt: OptionType<T>, i?: number) => string
7
+ ) => {
8
+ let key: React.Key = '';
9
+ if (keyExtractor !== undefined) {
10
+ key = keyExtractor(option, index);
11
+ } else if (option.key !== undefined) {
12
+ key = option.key;
13
+ } else {
14
+ key = index;
15
+ }
16
+
17
+ return key;
18
+ };
@@ -1,5 +1,6 @@
1
1
  import MultiSelect from './MultiSelect';
2
+ import SingleSelect from './SingleSelect';
2
3
 
3
- const CompoundSelect = { Multi: MultiSelect } as const;
4
-
5
- export default CompoundSelect;
4
+ export default Object.assign(SingleSelect, {
5
+ Multi: MultiSelect,
6
+ });
@@ -34,7 +34,7 @@ export interface SwitchProps {
34
34
  */
35
35
  size?: 'small' | 'medium';
36
36
  /**
37
- * Addditional style.
37
+ * Additional style.
38
38
  */
39
39
  style?: StyleProp<ViewStyle>;
40
40
  /**
@@ -6,7 +6,7 @@ exports[`Toast Icon render custom icon correctly 1`] = `
6
6
  nativeID="animatedComponent"
7
7
  style={
8
8
  Object {
9
- "backgroundColor": "#1dbeee",
9
+ "backgroundColor": "#b5c3fd",
10
10
  "borderRadius": 0,
11
11
  "flexDirection": "row",
12
12
  "minHeight": 48,
@@ -243,7 +243,7 @@ exports[`Toast renders correctly when intent is info 1`] = `
243
243
  nativeID="animatedComponent"
244
244
  style={
245
245
  Object {
246
- "backgroundColor": "#1dbeee",
246
+ "backgroundColor": "#b5c3fd",
247
247
  "borderRadius": 0,
248
248
  "flexDirection": "row",
249
249
  "minHeight": 48,
@@ -0,0 +1,42 @@
1
+ import styled from '@emotion/native';
2
+ import { TouchableOpacity, View, ViewProps } from 'react-native';
3
+
4
+ const ToolbarWrapper = styled(View)<ViewProps>(({ theme }) => ({
5
+ position: 'absolute',
6
+ bottom: 0,
7
+ left: 0,
8
+ right: 0,
9
+ zIndex: 9999,
10
+ elevation: 9999,
11
+ width: '100%',
12
+ paddingVertical: theme.__hd__.toolbar.space.verticalPadding,
13
+ paddingHorizontal: theme.__hd__.toolbar.space.horizontalPadding,
14
+ borderTopWidth: theme.__hd__.toolbar.borderWidths.default,
15
+ borderColor: theme.__hd__.toolbar.colors.border,
16
+ flexDirection: 'row',
17
+ alignItems: 'center',
18
+ backgroundColor: theme.__hd__.toolbar.colors.background,
19
+ }));
20
+
21
+ const alignment = {
22
+ left: 'flex-start',
23
+ center: 'center',
24
+ right: 'flex-end',
25
+ } as const;
26
+
27
+ const ToolbarGroupWrapper = styled(View)<{
28
+ align: 'left' | 'center' | 'right';
29
+ }>(({ align }) => ({
30
+ flex: 1,
31
+ flexDirection: 'row',
32
+ justifyContent: alignment[align],
33
+ alignItems: 'center',
34
+ }));
35
+
36
+ const ToolbarItemWrapper = styled(TouchableOpacity)(({ theme }) => ({
37
+ paddingVertical: theme.__hd__.toolbar.space.verticalPadding,
38
+ paddingHorizontal: theme.__hd__.toolbar.space.horizontalPadding,
39
+ alignItems: 'center',
40
+ }));
41
+
42
+ export { ToolbarWrapper, ToolbarGroupWrapper, ToolbarItemWrapper };
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { ToolbarGroupWrapper } from './StyledToolbar';
3
+ import ToolbarItem, { ToolbarItemProps } from './ToolbarItem';
4
+
5
+ export interface ToolbarGroupProps {
6
+ /**
7
+ * List of action items in the toolbar group.
8
+ */
9
+ items?: ToolbarItemProps[];
10
+ /**
11
+ * Alignment of the items in the group.
12
+ */
13
+ align: 'left' | 'center' | 'right';
14
+ }
15
+
16
+ const ToolbarGroup = ({ align = 'right', items = [] }: ToolbarGroupProps) => (
17
+ <ToolbarGroupWrapper align={align}>
18
+ {items.map(({ label, icon, onPress, disabled, intent }) => (
19
+ <ToolbarItem
20
+ key={`${label}-${icon}`}
21
+ label={label}
22
+ icon={icon}
23
+ intent={intent}
24
+ onPress={onPress}
25
+ disabled={disabled}
26
+ />
27
+ ))}
28
+ </ToolbarGroupWrapper>
29
+ );
30
+
31
+ export default ToolbarGroup;
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ import Icon, { IconName } from '../Icon';
3
+ import Typography from '../Typography';
4
+ import { ToolbarItemWrapper } from './StyledToolbar';
5
+
6
+ export interface ToolbarItemProps {
7
+ /**
8
+ * Visual intent of the toolbar item.
9
+ */
10
+ intent?: 'primary' | 'info' | 'success' | 'danger' | 'warning';
11
+ /**
12
+ * Icon of the toolbar item.
13
+ */
14
+ icon?: IconName;
15
+ /**
16
+ * Action label of the toolbar item.
17
+ */
18
+ label?: string;
19
+ /**
20
+ * Callback that trigger when user press the toolbar item.
21
+ */
22
+ onPress?: () => void;
23
+ /**
24
+ * Whether the toolbar item is disabled.
25
+ */
26
+ disabled?: boolean;
27
+ }
28
+
29
+ const ToolbarItem = ({
30
+ icon,
31
+ label,
32
+ onPress,
33
+ intent = 'primary',
34
+ disabled = false,
35
+ }: ToolbarItemProps) => (
36
+ <ToolbarItemWrapper onPress={onPress} disabled={disabled}>
37
+ {icon ? (
38
+ <Icon
39
+ icon={icon}
40
+ size={label ? 'medium' : 'large'}
41
+ intent={disabled ? 'disabled-text' : intent}
42
+ testID={`toolbar-item-icon-${icon}`}
43
+ />
44
+ ) : null}
45
+ {label ? (
46
+ <Typography.Text
47
+ fontSize={icon ? 'small' : 'large'}
48
+ fontWeight="semi-bold"
49
+ intent={disabled ? 'subdued' : intent}
50
+ >
51
+ {label}
52
+ </Typography.Text>
53
+ ) : null}
54
+ </ToolbarItemWrapper>
55
+ );
56
+
57
+ export default ToolbarItem;
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import renderWithTheme from '../../../testHelpers/renderWithTheme';
3
+ import ToolbarGroup from '../ToolbarGroup';
4
+
5
+ describe('ToolbarGroup', () => {
6
+ it.each`
7
+ align
8
+ ${'left'}
9
+ ${'right'}
10
+ ${'center'}
11
+ `('renders correctly with when align is $align', ({ align }) => {
12
+ const { toJSON } = renderWithTheme(
13
+ <ToolbarGroup
14
+ align={align}
15
+ items={[
16
+ {
17
+ label: 'Discard',
18
+ icon: 'home',
19
+ onPress: jest.fn(),
20
+ },
21
+ {
22
+ label: 'Print',
23
+ icon: 'print',
24
+ onPress: jest.fn(),
25
+ },
26
+ ]}
27
+ />
28
+ );
29
+
30
+ expect(toJSON()).toMatchSnapshot();
31
+ });
32
+ });
@@ -0,0 +1,57 @@
1
+ import { fireEvent } from '@testing-library/react-native';
2
+ import React from 'react';
3
+ import renderWithTheme from '../../../testHelpers/renderWithTheme';
4
+ import ToolbarItem from '../ToolbarItem';
5
+
6
+ describe('ToolbarItems', () => {
7
+ it.each`
8
+ intent
9
+ ${'primary'}
10
+ ${'info'}
11
+ ${'success'}
12
+ ${'danger'}
13
+ ${'warning'}
14
+ `('renders correctly when intent is $intent', ({ intent }) => {
15
+ const onPress = jest.fn();
16
+ const { toJSON, getByText, getByTestId } = renderWithTheme(
17
+ <ToolbarItem
18
+ label="Action"
19
+ intent={intent}
20
+ icon="home"
21
+ onPress={onPress}
22
+ />
23
+ );
24
+
25
+ expect(toJSON()).toMatchSnapshot();
26
+ expect(getByText('Action')).toBeDefined();
27
+ expect(getByTestId('toolbar-item-icon-home')).toBeDefined();
28
+
29
+ fireEvent.press(getByText('Action'));
30
+ expect(onPress).toBeCalled();
31
+ });
32
+
33
+ it('renders correctly when disabled', () => {
34
+ const onPress = jest.fn();
35
+ const { toJSON, getByText } = renderWithTheme(
36
+ <ToolbarItem
37
+ label="Action"
38
+ icon="home"
39
+ intent="primary"
40
+ onPress={onPress}
41
+ disabled
42
+ />
43
+ );
44
+
45
+ expect(toJSON()).toMatchSnapshot();
46
+ fireEvent.press(getByText('Action'));
47
+ expect(onPress).not.toBeCalled();
48
+ });
49
+
50
+ it('not renders icon when icon prop is not provided', () => {
51
+ const { queryByTestId } = renderWithTheme(
52
+ <ToolbarItem label="Action" intent="primary" />
53
+ );
54
+
55
+ expect(queryByTestId('toolbar-item-icon')).toBeNull();
56
+ });
57
+ });