@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.
- package/.eslintrc.js +11 -0
- package/.turbo/turbo-build.log +9 -9
- package/babel.config.js +1 -1
- package/es/index.js +357 -247
- package/lib/index.js +361 -251
- package/package.json +7 -15
- package/src/components/BottomNavigation/__tests__/index.spec.tsx +1 -1
- package/src/components/BottomNavigation/index.tsx +3 -3
- package/src/components/Box/helpers.ts +1 -1
- package/src/components/Calendar/index.tsx +9 -9
- package/src/components/Collapse/index.tsx +1 -1
- package/src/components/Drawer/DragableDrawer/helpers.ts +7 -3
- package/src/components/FAB/ActionGroup/index.tsx +1 -1
- package/src/components/Icon/HeroIcon/selection.json +7029 -1
- package/src/components/PinInput/index.tsx +1 -1
- package/src/components/RichTextEditor/EditorToolbar.tsx +3 -3
- package/src/components/RichTextEditor/RichTextEditor.tsx +5 -5
- package/src/components/RichTextEditor/__tests__/EditorToolbar.spec.tsx +2 -2
- package/src/components/RichTextEditor/__tests__/MentionList.spec.tsx +1 -1
- package/src/components/Select/MultiSelect/OptionList.tsx +1 -1
- package/src/components/Select/MultiSelect/__tests__/index.spec.tsx +1 -1
- package/src/components/Select/MultiSelect/index.tsx +3 -3
- package/src/components/Select/SingleSelect/index.tsx +3 -3
- package/src/components/Select/helpers.tsx +4 -4
- package/src/components/Slider/index.tsx +1 -1
- package/src/components/Switch/SelectorSwitch/Option.tsx +67 -0
- package/src/components/Switch/SelectorSwitch/StyledSelectorSwitch.tsx +25 -0
- package/src/components/Switch/SelectorSwitch/__tests__/Option.spec.tsx +61 -0
- package/src/components/Switch/SelectorSwitch/__tests__/__snapshots__/Option.spec.tsx.snap +195 -0
- package/src/components/Switch/SelectorSwitch/__tests__/__snapshots__/index.spec.tsx.snap +121 -0
- package/src/components/Switch/SelectorSwitch/__tests__/index.spec.tsx +62 -0
- package/src/components/Switch/SelectorSwitch/index.tsx +60 -0
- package/src/components/Switch/index.tsx +4 -1
- package/src/components/Tabs/ScrollableTabs.tsx +12 -5
- package/src/components/Tabs/__tests__/ScrollableTabs.spec.tsx +1 -1
- package/src/components/Tabs/__tests__/index.spec.tsx +1 -1
- package/src/components/Tabs/index.tsx +13 -6
- package/src/components/TextInput/__tests__/__snapshots__/index.spec.tsx.snap +3 -1
- package/src/components/TextInput/__tests__/index.spec.tsx +114 -112
- package/src/components/TextInput/index.tsx +29 -30
- package/src/components/Toast/ToastContainer.tsx +6 -6
- package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +14 -12
- package/src/theme/components/switch.ts +14 -18
- package/testUtils/setup.tsx +1 -1
- package/tsconfig.json +1 -1
- package/types/components/Slider/index.d.ts +1 -1
- package/types/components/Switch/SelectorSwitch/Option.d.ts +10 -0
- package/types/components/Switch/SelectorSwitch/StyledSelectorSwitch.d.ts +19 -0
- package/types/components/Switch/SelectorSwitch/__tests__/Option.spec.d.ts +1 -0
- package/types/components/Switch/SelectorSwitch/__tests__/index.spec.d.ts +1 -0
- package/types/components/Switch/SelectorSwitch/index.d.ts +37 -0
- package/types/components/Switch/index.d.ts +5 -3
- package/types/components/Tabs/ScrollableTabs.d.ts +1 -1
- package/types/components/Tabs/index.d.ts +2 -2
- package/types/components/TextInput/index.d.ts +4 -4
- package/types/theme/components/switch.d.ts +14 -12
- package/.eslintrc.json +0 -62
- 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(
|
|
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
|
|
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) {
|
|
@@ -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(
|
|
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
|
|
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) {
|