@hero-design/rn 7.21.0 → 7.22.1

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 (67) hide show
  1. package/.eslintrc.js +11 -0
  2. package/.turbo/turbo-build.log +9 -9
  3. package/babel.config.js +1 -1
  4. package/es/index.js +377 -263
  5. package/lib/index.js +380 -266
  6. package/package.json +7 -15
  7. package/src/components/BottomNavigation/__tests__/index.spec.tsx +1 -1
  8. package/src/components/BottomNavigation/index.tsx +3 -3
  9. package/src/components/BottomSheet/StyledBottomSheet.tsx +10 -0
  10. package/src/components/BottomSheet/__tests__/__snapshots__/index.spec.tsx.snap +326 -292
  11. package/src/components/BottomSheet/index.tsx +46 -26
  12. package/src/components/Box/helpers.ts +1 -1
  13. package/src/components/Calendar/index.tsx +9 -9
  14. package/src/components/Collapse/index.tsx +1 -1
  15. package/src/components/DatePicker/__tests__/__snapshots__/DatePickerIOS.spec.tsx.snap +176 -159
  16. package/src/components/Drawer/DragableDrawer/helpers.ts +7 -3
  17. package/src/components/FAB/ActionGroup/index.tsx +1 -1
  18. package/src/components/Icon/HeroIcon/selection.json +7029 -1
  19. package/src/components/PinInput/index.tsx +1 -1
  20. package/src/components/RichTextEditor/EditorToolbar.tsx +3 -3
  21. package/src/components/RichTextEditor/RichTextEditor.tsx +5 -5
  22. package/src/components/RichTextEditor/__tests__/EditorToolbar.spec.tsx +2 -2
  23. package/src/components/RichTextEditor/__tests__/MentionList.spec.tsx +1 -1
  24. package/src/components/Select/MultiSelect/OptionList.tsx +1 -1
  25. package/src/components/Select/MultiSelect/__tests__/__snapshots__/index.spec.tsx.snap +4691 -4606
  26. package/src/components/Select/MultiSelect/__tests__/index.spec.tsx +1 -1
  27. package/src/components/Select/MultiSelect/index.tsx +3 -3
  28. package/src/components/Select/SingleSelect/__tests__/__snapshots__/index.spec.tsx.snap +4245 -4160
  29. package/src/components/Select/SingleSelect/index.tsx +3 -3
  30. package/src/components/Select/helpers.tsx +4 -4
  31. package/src/components/Slider/index.tsx +1 -1
  32. package/src/components/Switch/SelectorSwitch/Option.tsx +67 -0
  33. package/src/components/Switch/SelectorSwitch/StyledSelectorSwitch.tsx +25 -0
  34. package/src/components/Switch/SelectorSwitch/__tests__/Option.spec.tsx +61 -0
  35. package/src/components/Switch/SelectorSwitch/__tests__/__snapshots__/Option.spec.tsx.snap +195 -0
  36. package/src/components/Switch/SelectorSwitch/__tests__/__snapshots__/index.spec.tsx.snap +121 -0
  37. package/src/components/Switch/SelectorSwitch/__tests__/index.spec.tsx +62 -0
  38. package/src/components/Switch/SelectorSwitch/index.tsx +60 -0
  39. package/src/components/Switch/index.tsx +4 -1
  40. package/src/components/Tabs/ScrollableTabs.tsx +12 -5
  41. package/src/components/Tabs/__tests__/ScrollableTabs.spec.tsx +1 -1
  42. package/src/components/Tabs/__tests__/index.spec.tsx +1 -1
  43. package/src/components/Tabs/index.tsx +13 -6
  44. package/src/components/TextInput/__tests__/__snapshots__/index.spec.tsx.snap +3 -1
  45. package/src/components/TextInput/__tests__/index.spec.tsx +114 -112
  46. package/src/components/TextInput/index.tsx +29 -30
  47. package/src/components/TimePicker/__tests__/__snapshots__/TimePickerIOS.spec.tsx.snap +176 -159
  48. package/src/components/Toast/ToastContainer.tsx +6 -6
  49. package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +14 -12
  50. package/src/theme/components/switch.ts +14 -18
  51. package/testUtils/setup.tsx +1 -1
  52. package/tsconfig.json +1 -1
  53. package/types/components/BottomSheet/StyledBottomSheet.d.ts +8 -2
  54. package/types/components/BottomSheet/index.d.ts +6 -1
  55. package/types/components/Slider/index.d.ts +1 -1
  56. package/types/components/Switch/SelectorSwitch/Option.d.ts +10 -0
  57. package/types/components/Switch/SelectorSwitch/StyledSelectorSwitch.d.ts +19 -0
  58. package/types/components/Switch/SelectorSwitch/__tests__/Option.spec.d.ts +1 -0
  59. package/types/components/Switch/SelectorSwitch/__tests__/index.spec.d.ts +1 -0
  60. package/types/components/Switch/SelectorSwitch/index.d.ts +37 -0
  61. package/types/components/Switch/index.d.ts +5 -3
  62. package/types/components/Tabs/ScrollableTabs.d.ts +1 -1
  63. package/types/components/Tabs/index.d.ts +2 -2
  64. package/types/components/TextInput/index.d.ts +4 -4
  65. package/types/theme/components/switch.d.ts +14 -12
  66. package/.eslintrc.json +0 -62
  67. package/.prettierrc.json +0 -8
@@ -60,7 +60,7 @@ const SingleSelect = <V, T extends OptionType<V>>({
60
60
  const sectionListRef = useRef<SectionList<T, SectionType>>(null);
61
61
  const sections = toSections(options);
62
62
  const flatOptions = toFlatOptions(options);
63
- const displayedValue = flatOptions.find(opt => value === opt.value)?.text;
63
+ const displayedValue = flatOptions.find((opt) => value === opt.value)?.text;
64
64
 
65
65
  return (
66
66
  <>
@@ -89,7 +89,7 @@ const SingleSelect = <V, T extends OptionType<V>>({
89
89
  testID={testID}
90
90
  renderInputValue={
91
91
  renderSelectedValue !== undefined
92
- ? props => renderSelectedValue(value, props)
92
+ ? (props) => renderSelectedValue(value, props)
93
93
  : undefined
94
94
  }
95
95
  />
@@ -129,7 +129,7 @@ const SingleSelect = <V, T extends OptionType<V>>({
129
129
  sections={sections}
130
130
  renderOption={renderOption}
131
131
  value={value}
132
- onPress={selectedValue => {
132
+ onPress={(selectedValue) => {
133
133
  setOpen(false);
134
134
  onConfirm(selectedValue);
135
135
  }}
@@ -44,7 +44,7 @@ export const toFlatOptions = <V, T extends OptionType<V>>(
44
44
  options: CombinedOptionsType<V, T>
45
45
  ): OptionType<V>[] => {
46
46
  if (isSections(options)) {
47
- return options.flatMap(opt => opt.data);
47
+ return options.flatMap((opt) => opt.data);
48
48
  }
49
49
 
50
50
  return options;
@@ -61,8 +61,8 @@ export const getScrollParams = <V, T extends OptionType<V>>(
61
61
  ): ScrollParams => {
62
62
  let itemIndex = -1;
63
63
 
64
- const sectionIndex = sections.findIndex(section => {
65
- itemIndex = section.data.findIndex(opt => opt.value === value);
64
+ const sectionIndex = sections.findIndex((section) => {
65
+ itemIndex = section.data.findIndex((opt) => opt.value === value);
66
66
  return itemIndex !== -1;
67
67
  });
68
68
 
@@ -79,7 +79,7 @@ export const useKeyboard = () => {
79
79
  useEffect(() => {
80
80
  const keyboardWillShowListener = Keyboard.addListener(
81
81
  'keyboardWillShow',
82
- e => {
82
+ (e) => {
83
83
  setKeyboardVisible(true);
84
84
  setKeyboardHeight(e.endCoordinates.height);
85
85
  }
@@ -53,7 +53,7 @@ export interface SliderProps {
53
53
  testID?: string;
54
54
  }
55
55
 
56
- export const Slider = ({
56
+ const Slider = ({
57
57
  minimumValue = 0,
58
58
  maximumValue = 1,
59
59
  step = 0,
@@ -0,0 +1,67 @@
1
+ import React from 'react';
2
+ import type { ReactElement } from 'react';
3
+ import type { BadgeConfigType, OptionType } from '.';
4
+ import { useTheme } from '../../../theme';
5
+ import { StyledIconWrapper, StyledTextWrapper } from './StyledSelectorSwitch';
6
+ import Typography from '../../Typography';
7
+ import Badge from '../../Badge';
8
+ import Icon from '../../Icon';
9
+
10
+ export const OptionContent = ({
11
+ content,
12
+ badge,
13
+ }: {
14
+ content: ReactElement;
15
+ badge?: BadgeConfigType;
16
+ }) => {
17
+ const theme = useTheme();
18
+ if (!badge) {
19
+ return content;
20
+ }
21
+
22
+ if (badge.type === 'status') {
23
+ return (
24
+ <Badge.Status
25
+ visible
26
+ style={{ paddingHorizontal: theme.space.small }}
27
+ testID="selector-switch-status-badge"
28
+ >
29
+ {content}
30
+ </Badge.Status>
31
+ );
32
+ }
33
+
34
+ return content;
35
+ };
36
+
37
+ const Option = <T,>({
38
+ text,
39
+ icon,
40
+ badge,
41
+ selected,
42
+ }: Pick<OptionType<T>, 'text' | 'icon' | 'badge'> & {
43
+ selected: boolean;
44
+ }): ReactElement => {
45
+ if (selected) {
46
+ return (
47
+ <StyledTextWrapper>
48
+ <OptionContent
49
+ content={
50
+ <Typography.Text fontSize="large" intent="inverted">
51
+ {text}
52
+ </Typography.Text>
53
+ }
54
+ badge={badge}
55
+ />
56
+ </StyledTextWrapper>
57
+ );
58
+ }
59
+
60
+ return (
61
+ <StyledIconWrapper>
62
+ <OptionContent content={<Icon icon={icon} />} badge={badge} />
63
+ </StyledIconWrapper>
64
+ );
65
+ };
66
+
67
+ export default Option;
@@ -0,0 +1,25 @@
1
+ import styled from '@emotion/native';
2
+ import { View } from 'react-native';
3
+
4
+ export const StyledWrapper = styled(View)(({ theme }) => ({
5
+ flexDirection: 'row',
6
+ width: '100%',
7
+ height: theme.__hd__.switch.sizes.selector.height,
8
+ borderRadius: theme.__hd__.switch.radii.selector.default,
9
+ backgroundColor: theme.__hd__.switch.colors.selector.background,
10
+ padding: theme.__hd__.switch.spaces.selector.wrapperPadding,
11
+ }));
12
+
13
+ export const StyledTextWrapper = styled(View)(({ theme }) => ({
14
+ flex: 1,
15
+ borderRadius: theme.__hd__.switch.radii.selector.default,
16
+ backgroundColor: theme.__hd__.switch.colors.selector.textBackground,
17
+ justifyContent: 'center',
18
+ alignItems: 'center',
19
+ }));
20
+
21
+ export const StyledIconWrapper = styled(View)(({ theme }) => ({
22
+ paddingHorizontal: theme.__hd__.switch.spaces.selector.iconPadding,
23
+ justifyContent: 'center',
24
+ alignItems: 'center',
25
+ }));
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import renderWithTheme from '../../../../testHelpers/renderWithTheme';
3
+ import Icon from '../../../Icon';
4
+ import Option, { OptionContent } from '../Option';
5
+
6
+ describe('Option', () => {
7
+ it('renders correctly when selected', () => {
8
+ const wrapper = renderWithTheme(
9
+ <Option
10
+ text="My Dashboard"
11
+ icon="user"
12
+ badge={{ type: 'status' }}
13
+ selected
14
+ />
15
+ );
16
+
17
+ expect(wrapper.queryAllByText('My Dashboard')).toHaveLength(1);
18
+ expect(wrapper.toJSON()).toMatchSnapshot();
19
+ });
20
+
21
+ it('renders correctly when not selected', () => {
22
+ const wrapper = renderWithTheme(
23
+ <Option
24
+ text="My Dashboard"
25
+ icon="user"
26
+ badge={{ type: 'status' }}
27
+ selected={false}
28
+ />
29
+ );
30
+
31
+ expect(wrapper.queryAllByText('My Dashboard')).toHaveLength(0);
32
+ expect(wrapper.toJSON()).toMatchSnapshot();
33
+ });
34
+ });
35
+
36
+ describe('OptionContent', () => {
37
+ it('renders correctly there is no badge', () => {
38
+ const wrapper = renderWithTheme(
39
+ <OptionContent content={<Icon icon="user" />} />
40
+ );
41
+
42
+ expect(
43
+ wrapper.queryAllByTestId('selector-switch-status-badge')
44
+ ).toHaveLength(0);
45
+ expect(wrapper.toJSON()).toMatchSnapshot();
46
+ });
47
+
48
+ it('renders correctly when there is a badge', () => {
49
+ const wrapper = renderWithTheme(
50
+ <OptionContent
51
+ content={<Icon icon="user" />}
52
+ badge={{ type: 'status' }}
53
+ />
54
+ );
55
+
56
+ expect(
57
+ wrapper.queryAllByTestId('selector-switch-status-badge')
58
+ ).toHaveLength(1);
59
+ expect(wrapper.toJSON()).toMatchSnapshot();
60
+ });
61
+ });
@@ -0,0 +1,195 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Option renders correctly when not selected 1`] = `
4
+ <View
5
+ style={
6
+ Array [
7
+ Object {
8
+ "alignItems": "center",
9
+ "justifyContent": "center",
10
+ "paddingHorizontal": 16,
11
+ },
12
+ undefined,
13
+ ]
14
+ }
15
+ >
16
+ <View
17
+ style={
18
+ Object {
19
+ "paddingHorizontal": 8,
20
+ }
21
+ }
22
+ testID="selector-switch-status-badge"
23
+ >
24
+ <HeroIcon
25
+ name="user"
26
+ style={
27
+ Array [
28
+ Object {
29
+ "color": "#001f23",
30
+ "fontSize": 24,
31
+ },
32
+ undefined,
33
+ ]
34
+ }
35
+ themeIntent="text"
36
+ themeSize="medium"
37
+ />
38
+ <View
39
+ collapsable={false}
40
+ nativeID="animatedComponent"
41
+ style={
42
+ Object {
43
+ "backgroundColor": "#de350b",
44
+ "borderRadius": 999,
45
+ "height": 8,
46
+ "opacity": 1,
47
+ "position": "absolute",
48
+ "right": -2,
49
+ "top": -2,
50
+ "transform": Array [
51
+ Object {
52
+ "scale": 1,
53
+ },
54
+ ],
55
+ "width": 8,
56
+ }
57
+ }
58
+ themeIntent="danger"
59
+ />
60
+ </View>
61
+ </View>
62
+ `;
63
+
64
+ exports[`Option renders correctly when selected 1`] = `
65
+ <View
66
+ style={
67
+ Array [
68
+ Object {
69
+ "alignItems": "center",
70
+ "backgroundColor": "#401960",
71
+ "borderRadius": 999,
72
+ "flex": 1,
73
+ "justifyContent": "center",
74
+ },
75
+ undefined,
76
+ ]
77
+ }
78
+ >
79
+ <View
80
+ style={
81
+ Object {
82
+ "paddingHorizontal": 8,
83
+ }
84
+ }
85
+ testID="selector-switch-status-badge"
86
+ >
87
+ <Text
88
+ style={
89
+ Array [
90
+ Object {
91
+ "color": "#ffffff",
92
+ "fontFamily": "BeVietnamPro-Regular",
93
+ "fontSize": 16,
94
+ "letterSpacing": 0.48,
95
+ "lineHeight": 24,
96
+ },
97
+ undefined,
98
+ ]
99
+ }
100
+ themeFontSize="large"
101
+ themeFontWeight="regular"
102
+ themeIntent="inverted"
103
+ >
104
+ My Dashboard
105
+ </Text>
106
+ <View
107
+ collapsable={false}
108
+ nativeID="animatedComponent"
109
+ style={
110
+ Object {
111
+ "backgroundColor": "#de350b",
112
+ "borderRadius": 999,
113
+ "height": 8,
114
+ "opacity": 1,
115
+ "position": "absolute",
116
+ "right": -2,
117
+ "top": -2,
118
+ "transform": Array [
119
+ Object {
120
+ "scale": 1,
121
+ },
122
+ ],
123
+ "width": 8,
124
+ }
125
+ }
126
+ themeIntent="danger"
127
+ />
128
+ </View>
129
+ </View>
130
+ `;
131
+
132
+ exports[`OptionContent renders correctly there is no badge 1`] = `
133
+ <HeroIcon
134
+ name="user"
135
+ style={
136
+ Array [
137
+ Object {
138
+ "color": "#001f23",
139
+ "fontSize": 24,
140
+ },
141
+ undefined,
142
+ ]
143
+ }
144
+ themeIntent="text"
145
+ themeSize="medium"
146
+ />
147
+ `;
148
+
149
+ exports[`OptionContent renders correctly when there is a badge 1`] = `
150
+ <View
151
+ style={
152
+ Object {
153
+ "paddingHorizontal": 8,
154
+ }
155
+ }
156
+ testID="selector-switch-status-badge"
157
+ >
158
+ <HeroIcon
159
+ name="user"
160
+ style={
161
+ Array [
162
+ Object {
163
+ "color": "#001f23",
164
+ "fontSize": 24,
165
+ },
166
+ undefined,
167
+ ]
168
+ }
169
+ themeIntent="text"
170
+ themeSize="medium"
171
+ />
172
+ <View
173
+ collapsable={false}
174
+ nativeID="animatedComponent"
175
+ style={
176
+ Object {
177
+ "backgroundColor": "#de350b",
178
+ "borderRadius": 999,
179
+ "height": 8,
180
+ "opacity": 1,
181
+ "position": "absolute",
182
+ "right": -2,
183
+ "top": -2,
184
+ "transform": Array [
185
+ Object {
186
+ "scale": 1,
187
+ },
188
+ ],
189
+ "width": 8,
190
+ }
191
+ }
192
+ themeIntent="danger"
193
+ />
194
+ </View>
195
+ `;
@@ -0,0 +1,121 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`SelectorSwitch renders correctly 1`] = `
4
+ <View
5
+ accessible={true}
6
+ focusable={true}
7
+ onClick={[Function]}
8
+ onResponderGrant={[Function]}
9
+ onResponderMove={[Function]}
10
+ onResponderRelease={[Function]}
11
+ onResponderTerminate={[Function]}
12
+ onResponderTerminationRequest={[Function]}
13
+ onStartShouldSetResponder={[Function]}
14
+ style={
15
+ Array [
16
+ Object {
17
+ "backgroundColor": "#f6f6f7",
18
+ "borderRadius": 999,
19
+ "flexDirection": "row",
20
+ "height": 56,
21
+ "padding": 4,
22
+ "width": "100%",
23
+ },
24
+ undefined,
25
+ ]
26
+ }
27
+ >
28
+ <View
29
+ style={
30
+ Array [
31
+ Object {
32
+ "alignItems": "center",
33
+ "backgroundColor": "#401960",
34
+ "borderRadius": 999,
35
+ "flex": 1,
36
+ "justifyContent": "center",
37
+ },
38
+ undefined,
39
+ ]
40
+ }
41
+ >
42
+ <Text
43
+ style={
44
+ Array [
45
+ Object {
46
+ "color": "#ffffff",
47
+ "fontFamily": "BeVietnamPro-Regular",
48
+ "fontSize": 16,
49
+ "letterSpacing": 0.48,
50
+ "lineHeight": 24,
51
+ },
52
+ undefined,
53
+ ]
54
+ }
55
+ themeFontSize="large"
56
+ themeFontWeight="regular"
57
+ themeIntent="inverted"
58
+ >
59
+ My Dashboard
60
+ </Text>
61
+ </View>
62
+ <View
63
+ style={
64
+ Array [
65
+ Object {
66
+ "alignItems": "center",
67
+ "justifyContent": "center",
68
+ "paddingHorizontal": 16,
69
+ },
70
+ undefined,
71
+ ]
72
+ }
73
+ >
74
+ <View
75
+ style={
76
+ Object {
77
+ "paddingHorizontal": 8,
78
+ }
79
+ }
80
+ testID="selector-switch-status-badge"
81
+ >
82
+ <HeroIcon
83
+ name="multiple-users"
84
+ style={
85
+ Array [
86
+ Object {
87
+ "color": "#001f23",
88
+ "fontSize": 24,
89
+ },
90
+ undefined,
91
+ ]
92
+ }
93
+ themeIntent="text"
94
+ themeSize="medium"
95
+ />
96
+ <View
97
+ collapsable={false}
98
+ nativeID="animatedComponent"
99
+ style={
100
+ Object {
101
+ "backgroundColor": "#de350b",
102
+ "borderRadius": 999,
103
+ "height": 8,
104
+ "opacity": 1,
105
+ "position": "absolute",
106
+ "right": -2,
107
+ "top": -2,
108
+ "transform": Array [
109
+ Object {
110
+ "scale": 1,
111
+ },
112
+ ],
113
+ "width": 8,
114
+ }
115
+ }
116
+ themeIntent="danger"
117
+ />
118
+ </View>
119
+ </View>
120
+ </View>
121
+ `;
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import { fireEvent } from '@testing-library/react-native';
3
+ import renderWithTheme from '../../../../testHelpers/renderWithTheme';
4
+ import SelectorSwitch from '..';
5
+
6
+ type PermissionType = 'employee' | 'manager';
7
+
8
+ describe('SelectorSwitch', () => {
9
+ it('renders correctly', () => {
10
+ const wrapper = renderWithTheme(
11
+ <SelectorSwitch<PermissionType>
12
+ options={[
13
+ {
14
+ value: 'employee',
15
+ text: 'My Dashboard',
16
+ icon: 'user',
17
+ },
18
+ {
19
+ value: 'manager',
20
+ text: 'Manager Dashboard',
21
+ icon: 'multiple-users',
22
+ badge: { type: 'status' },
23
+ },
24
+ ]}
25
+ value="employee"
26
+ />
27
+ );
28
+
29
+ expect(wrapper.queryAllByText('My Dashboard')).toHaveLength(1);
30
+ expect(wrapper.queryAllByText('Manager Dashboard')).toHaveLength(0);
31
+ expect(
32
+ wrapper.queryAllByTestId('selector-switch-status-badge')
33
+ ).toHaveLength(1);
34
+ expect(wrapper.toJSON()).toMatchSnapshot();
35
+ });
36
+
37
+ it('triggers onPress correctly', () => {
38
+ const onPress = jest.fn();
39
+ const wrapper = renderWithTheme(
40
+ <SelectorSwitch<PermissionType>
41
+ options={[
42
+ {
43
+ value: 'employee',
44
+ text: 'My Dashboard',
45
+ icon: 'user',
46
+ },
47
+ {
48
+ value: 'manager',
49
+ text: 'Manager Dashboard',
50
+ icon: 'multiple-users',
51
+ badge: { type: 'status' },
52
+ },
53
+ ]}
54
+ value="manager"
55
+ onPress={onPress}
56
+ />
57
+ );
58
+
59
+ fireEvent.press(wrapper.getByText('Manager Dashboard'));
60
+ expect(onPress).toBeCalledTimes(1);
61
+ });
62
+ });
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+ import type { ReactElement } from 'react';
3
+ import { StyleProp, TouchableWithoutFeedback, ViewStyle } from 'react-native';
4
+ import { StyledWrapper } from './StyledSelectorSwitch';
5
+ import type { IconName } from '../../Icon';
6
+ import Option from './Option';
7
+
8
+ type StatusBadgeType = {
9
+ type: 'status';
10
+ };
11
+ export type BadgeConfigType = StatusBadgeType;
12
+
13
+ export type OptionType<T> = {
14
+ value: T;
15
+ text: string;
16
+ icon: IconName;
17
+ badge?: BadgeConfigType;
18
+ };
19
+
20
+ export interface SelectorSwitchProps<T> {
21
+ /**
22
+ * Array of exactly TWO options to switch between.
23
+ */
24
+ options: [OptionType<T>, OptionType<T>];
25
+ /**
26
+ * Current selected value.
27
+ */
28
+ value: T;
29
+ /**
30
+ * Callback called when an option is pressed.
31
+ */
32
+ onPress?: (value: T) => void;
33
+ /**
34
+ * Additional style.
35
+ */
36
+ style?: StyleProp<ViewStyle>;
37
+ /**
38
+ * Testing id of the component.
39
+ */
40
+ testID?: string;
41
+ }
42
+
43
+ const SelectorSwitch = <T,>({
44
+ options,
45
+ value,
46
+ onPress,
47
+ style,
48
+ testID,
49
+ }: SelectorSwitchProps<T>): ReactElement => (
50
+ <TouchableWithoutFeedback onPress={() => onPress(value)} testID={testID}>
51
+ <StyledWrapper style={style}>
52
+ {options.map((opt, index) => (
53
+ // eslint-disable-next-line react/no-array-index-key
54
+ <Option {...opt} selected={opt.value === value} key={index} />
55
+ ))}
56
+ </StyledWrapper>
57
+ </TouchableWithoutFeedback>
58
+ );
59
+
60
+ export default SelectorSwitch;
@@ -6,6 +6,7 @@ import { Animated, Easing, TouchableWithoutFeedback } from 'react-native';
6
6
  import type { ReactElement } from 'react';
7
7
  import type { StyleProp, ViewStyle } from 'react-native';
8
8
  import { StyledKnot, StyledWrapper, Variant } from './StyledSwitch';
9
+ import SelectorSwitch from './SelectorSwitch';
9
10
 
10
11
  export interface SwitchProps {
11
12
  /**
@@ -88,4 +89,6 @@ const Switch = ({
88
89
  );
89
90
  };
90
91
 
91
- export default Switch;
92
+ export default Object.assign(Switch, {
93
+ Selector: SelectorSwitch,
94
+ });