@hero-design/rn 7.21.0 → 7.22.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 (58) 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 +357 -247
  5. package/lib/index.js +361 -251
  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/Box/helpers.ts +1 -1
  10. package/src/components/Calendar/index.tsx +9 -9
  11. package/src/components/Collapse/index.tsx +1 -1
  12. package/src/components/Drawer/DragableDrawer/helpers.ts +7 -3
  13. package/src/components/FAB/ActionGroup/index.tsx +1 -1
  14. package/src/components/Icon/HeroIcon/selection.json +7029 -1
  15. package/src/components/PinInput/index.tsx +1 -1
  16. package/src/components/RichTextEditor/EditorToolbar.tsx +3 -3
  17. package/src/components/RichTextEditor/RichTextEditor.tsx +5 -5
  18. package/src/components/RichTextEditor/__tests__/EditorToolbar.spec.tsx +2 -2
  19. package/src/components/RichTextEditor/__tests__/MentionList.spec.tsx +1 -1
  20. package/src/components/Select/MultiSelect/OptionList.tsx +1 -1
  21. package/src/components/Select/MultiSelect/__tests__/index.spec.tsx +1 -1
  22. package/src/components/Select/MultiSelect/index.tsx +3 -3
  23. package/src/components/Select/SingleSelect/index.tsx +3 -3
  24. package/src/components/Select/helpers.tsx +4 -4
  25. package/src/components/Slider/index.tsx +1 -1
  26. package/src/components/Switch/SelectorSwitch/Option.tsx +67 -0
  27. package/src/components/Switch/SelectorSwitch/StyledSelectorSwitch.tsx +25 -0
  28. package/src/components/Switch/SelectorSwitch/__tests__/Option.spec.tsx +61 -0
  29. package/src/components/Switch/SelectorSwitch/__tests__/__snapshots__/Option.spec.tsx.snap +195 -0
  30. package/src/components/Switch/SelectorSwitch/__tests__/__snapshots__/index.spec.tsx.snap +121 -0
  31. package/src/components/Switch/SelectorSwitch/__tests__/index.spec.tsx +62 -0
  32. package/src/components/Switch/SelectorSwitch/index.tsx +60 -0
  33. package/src/components/Switch/index.tsx +4 -1
  34. package/src/components/Tabs/ScrollableTabs.tsx +12 -5
  35. package/src/components/Tabs/__tests__/ScrollableTabs.spec.tsx +1 -1
  36. package/src/components/Tabs/__tests__/index.spec.tsx +1 -1
  37. package/src/components/Tabs/index.tsx +13 -6
  38. package/src/components/TextInput/__tests__/__snapshots__/index.spec.tsx.snap +3 -1
  39. package/src/components/TextInput/__tests__/index.spec.tsx +114 -112
  40. package/src/components/TextInput/index.tsx +29 -30
  41. package/src/components/Toast/ToastContainer.tsx +6 -6
  42. package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +14 -12
  43. package/src/theme/components/switch.ts +14 -18
  44. package/testUtils/setup.tsx +1 -1
  45. package/tsconfig.json +1 -1
  46. package/types/components/Slider/index.d.ts +1 -1
  47. package/types/components/Switch/SelectorSwitch/Option.d.ts +10 -0
  48. package/types/components/Switch/SelectorSwitch/StyledSelectorSwitch.d.ts +19 -0
  49. package/types/components/Switch/SelectorSwitch/__tests__/Option.spec.d.ts +1 -0
  50. package/types/components/Switch/SelectorSwitch/__tests__/index.spec.d.ts +1 -0
  51. package/types/components/Switch/SelectorSwitch/index.d.ts +37 -0
  52. package/types/components/Switch/index.d.ts +5 -3
  53. package/types/components/Tabs/ScrollableTabs.d.ts +1 -1
  54. package/types/components/Tabs/index.d.ts +2 -2
  55. package/types/components/TextInput/index.d.ts +4 -4
  56. package/types/theme/components/switch.d.ts +14 -12
  57. package/.eslintrc.json +0 -62
  58. package/.prettierrc.json +0 -8
@@ -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
+ });
@@ -63,12 +63,15 @@ const ScrollableTab = ({
63
63
  barStyle,
64
64
  lazy = false,
65
65
  lazyPreloadDistance = 1,
66
+ testID: componentTestID,
66
67
  }: TabsProps) => {
67
68
  const flatListRef = React.useRef<FlatList>(null);
68
69
  const pagerViewRef = React.useRef<PagerView>(null);
69
70
  const insets = useSafeAreaInsets();
70
71
  const theme = useTheme();
71
- const selectedTabIndex = tabs.findIndex(item => item.key === selectedTabKey);
72
+ const selectedTabIndex = tabs.findIndex(
73
+ (item) => item.key === selectedTabKey
74
+ );
72
75
  const tabsAnims = useAnimatedValueArray(
73
76
  tabs.map((_, i) => (i === selectedTabIndex ? 1 : 0))
74
77
  );
@@ -97,13 +100,17 @@ const ScrollableTab = ({
97
100
  }, [selectedTabIndex]);
98
101
 
99
102
  return (
100
- <TabContainer style={containerStyle}>
101
- <HeaderTabWrapper themeInsets={insets} style={barStyle}>
103
+ <TabContainer style={containerStyle} testID={componentTestID}>
104
+ <HeaderTabWrapper
105
+ themeInsets={insets}
106
+ style={barStyle}
107
+ testID={componentTestID ? `${componentTestID}-tab-bar` : undefined}
108
+ >
102
109
  <FlatList<TabType>
103
110
  ref={flatListRef}
104
111
  horizontal
105
112
  data={tabs}
106
- keyExtractor={tab => String(tab.key)}
113
+ keyExtractor={(tab) => String(tab.key)}
107
114
  showsHorizontalScrollIndicator={false}
108
115
  onScrollToIndexFailed={({ index }) => {
109
116
  setTimeout(
@@ -184,7 +191,7 @@ const ScrollableTab = ({
184
191
  <ContentWrapper
185
192
  initialPage={selectedTabIndex}
186
193
  ref={pagerViewRef}
187
- onPageSelected={e => {
194
+ onPageSelected={(e) => {
188
195
  const index = e.nativeEvent.position;
189
196
  const selectedItem = tabs[index];
190
197
  if (selectedItem) {
@@ -62,7 +62,7 @@ const TestTabsComponent = (
62
62
  {...props}
63
63
  tabs={tabs}
64
64
  selectedTabKey={selectedTabKey}
65
- onTabPress={newTabKey => setSelectedTabKey(newTabKey)}
65
+ onTabPress={(newTabKey) => setSelectedTabKey(newTabKey)}
66
66
  />
67
67
  </SafeAreaProvider>
68
68
  );
@@ -59,7 +59,7 @@ const TestTabsComponent = (
59
59
  {...props}
60
60
  tabs={tabs}
61
61
  selectedTabKey={selectedTabKey}
62
- onTabPress={newTabKey => setSelectedTabKey(newTabKey)}
62
+ onTabPress={(newTabKey) => setSelectedTabKey(newTabKey)}
63
63
  />
64
64
  </SafeAreaProvider>
65
65
  );
@@ -105,11 +105,14 @@ const Tabs = ({
105
105
  barStyle,
106
106
  lazy = false,
107
107
  lazyPreloadDistance = 1,
108
+ testID: componentTestID,
108
109
  }: TabsProps): JSX.Element => {
109
110
  const theme = useTheme();
110
111
  const insets = useSafeAreaInsets();
111
112
  const pagerViewRef = React.useRef<PagerView>(null);
112
- const selectedTabIndex = tabs.findIndex(item => item.key === selectedTabKey);
113
+ const selectedTabIndex = tabs.findIndex(
114
+ (item) => item.key === selectedTabKey
115
+ );
113
116
  const scrollOffsetAnimatedValue = React.useRef(new Animated.Value(0)).current;
114
117
  const positionAnimatedValue = React.useRef(new Animated.Value(0)).current;
115
118
  const [tabsWidth, setTabsWidth] = React.useState<number>(0);
@@ -121,18 +124,22 @@ const Tabs = ({
121
124
  }, [selectedTabIndex]);
122
125
 
123
126
  return (
124
- <TabContainer style={containerStyle}>
125
- <HeaderTabWrapper themeInsets={insets} style={barStyle}>
127
+ <TabContainer style={containerStyle} testID={componentTestID}>
128
+ <HeaderTabWrapper
129
+ themeInsets={insets}
130
+ style={barStyle}
131
+ testID={componentTestID ? `${componentTestID}-tab-bar` : undefined}
132
+ >
126
133
  <View>
127
134
  <HeaderTab
128
- onLayout={e => {
135
+ onLayout={(e) => {
129
136
  const { width } = e.nativeEvent.layout;
130
137
  if (tabsWidth !== width) {
131
138
  setTabsWidth(width);
132
139
  }
133
140
  }}
134
141
  >
135
- {tabs.map(tab => {
142
+ {tabs.map((tab) => {
136
143
  const {
137
144
  key,
138
145
  testID,
@@ -180,7 +187,7 @@ const Tabs = ({
180
187
  <ContentWrapper
181
188
  initialPage={selectedTabIndex}
182
189
  ref={pagerViewRef}
183
- onPageSelected={e => {
190
+ onPageSelected={(e) => {
184
191
  const index = e.nativeEvent.position;
185
192
  const selectedItem = tabs[index];
186
193
  if (selectedItem) {
@@ -1396,7 +1396,9 @@ exports[`TextInput idle renders correctly 1`] = `
1396
1396
  "right": 0,
1397
1397
  "top": 0,
1398
1398
  },
1399
- undefined,
1399
+ Object {
1400
+ "borderColor": "#de350b",
1401
+ },
1400
1402
  ]
1401
1403
  }
1402
1404
  themeVariant="default"