@hero-design/rn 8.29.5 → 8.30.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.
- package/.turbo/turbo-build.log +1 -1
- package/es/index.js +167 -92
- package/lib/index.js +167 -91
- package/package.json +5 -5
- package/src/components/Rate/StyledRate.tsx +16 -0
- package/src/components/Rate/__tests__/__snapshots__/index.spec.tsx.snap +742 -0
- package/src/components/Rate/__tests__/index.spec.tsx +47 -0
- package/src/components/Rate/index.tsx +90 -0
- package/src/index.ts +2 -0
- package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +9 -0
- package/src/theme/components/rate.ts +16 -0
- package/src/theme/getTheme.ts +3 -0
- package/testUtils/setup.tsx +5 -2
- package/types/components/Rate/StyledRate.d.ts +13 -0
- package/types/components/Rate/index.d.ts +28 -0
- package/types/index.d.ts +2 -1
- package/types/theme/components/rate.d.ts +11 -0
- package/types/theme/getTheme.d.ts +2 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { fireEvent } from '@testing-library/react-native';
|
|
3
|
+
import renderWithTheme from '../../../testHelpers/renderWithTheme';
|
|
4
|
+
import Rate from '..';
|
|
5
|
+
|
|
6
|
+
const ratingData = [
|
|
7
|
+
{ value: 1 },
|
|
8
|
+
{ value: 2 },
|
|
9
|
+
{ value: 3 },
|
|
10
|
+
{ value: 4 },
|
|
11
|
+
{ value: 5 },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
describe('Rate', () => {
|
|
15
|
+
it('renders correctly', () => {
|
|
16
|
+
const onChange = jest.fn();
|
|
17
|
+
const { toJSON, getByTestId } = renderWithTheme(
|
|
18
|
+
<Rate value={3} onChange={onChange} options={ratingData} />
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
fireEvent.press(getByTestId('1'));
|
|
22
|
+
expect(onChange).toHaveBeenCalled();
|
|
23
|
+
expect(toJSON()).toMatchSnapshot();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('renders correctly it is readonly', () => {
|
|
27
|
+
const onChange = jest.fn();
|
|
28
|
+
const { getByTestId, toJSON } = renderWithTheme(
|
|
29
|
+
<Rate readonly value={3} onChange={onChange} options={ratingData} />
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
fireEvent.press(getByTestId('1'));
|
|
33
|
+
expect(onChange).toBeCalledTimes(0);
|
|
34
|
+
expect(toJSON()).toMatchSnapshot();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('renders correctly when disabled', () => {
|
|
38
|
+
const onChange = jest.fn();
|
|
39
|
+
const { getByTestId, toJSON } = renderWithTheme(
|
|
40
|
+
<Rate disabled value={3} onChange={onChange} options={ratingData} />
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
fireEvent.press(getByTestId('1'));
|
|
44
|
+
expect(onChange).toBeCalledTimes(0);
|
|
45
|
+
expect(toJSON()).toMatchSnapshot();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React, { useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { Animated, Platform, Pressable, ViewProps } from 'react-native';
|
|
3
|
+
import Icon from '../Icon';
|
|
4
|
+
import { StyledIconWrapper, StyledWrapper } from './StyledRate';
|
|
5
|
+
|
|
6
|
+
export interface RateOption<T extends string | number> {
|
|
7
|
+
value: T;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface RateProps<T extends string | number> extends ViewProps {
|
|
11
|
+
/**
|
|
12
|
+
* Options for rate component.
|
|
13
|
+
*/
|
|
14
|
+
options: RateOption<T>[];
|
|
15
|
+
/**
|
|
16
|
+
* Value of the component.
|
|
17
|
+
*/
|
|
18
|
+
value?: T;
|
|
19
|
+
/**
|
|
20
|
+
* Callback when value changes.
|
|
21
|
+
*/
|
|
22
|
+
onChange?: (value: T) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Whether the component is readonly.
|
|
25
|
+
*/
|
|
26
|
+
readonly?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Whether the component is disabled.
|
|
29
|
+
*/
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const Rate = <T extends string | number>({
|
|
34
|
+
options,
|
|
35
|
+
value,
|
|
36
|
+
onChange,
|
|
37
|
+
readonly = false,
|
|
38
|
+
disabled = false,
|
|
39
|
+
...otherProps
|
|
40
|
+
}: RateProps<T>) => {
|
|
41
|
+
const valueIndex = useMemo(
|
|
42
|
+
() => options.findIndex((item) => item.value === value),
|
|
43
|
+
[value, options]
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const animatedValue = useRef(new Animated.Value(0)).current;
|
|
47
|
+
|
|
48
|
+
const scale = animatedValue.interpolate({
|
|
49
|
+
inputRange: [0, 1],
|
|
50
|
+
outputRange: [0.8, 1],
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
animatedValue.setValue(0);
|
|
55
|
+
|
|
56
|
+
Animated.spring(animatedValue, {
|
|
57
|
+
toValue: 1,
|
|
58
|
+
useNativeDriver: Platform.OS !== 'web',
|
|
59
|
+
}).start();
|
|
60
|
+
}, [value, animatedValue]);
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<StyledWrapper {...otherProps}>
|
|
64
|
+
{options.length > 0 &&
|
|
65
|
+
options.map((item, index) => (
|
|
66
|
+
<Pressable
|
|
67
|
+
key={item.value}
|
|
68
|
+
disabled={disabled || readonly}
|
|
69
|
+
onPress={() => onChange?.(item.value)}
|
|
70
|
+
testID={item.value.toString()}
|
|
71
|
+
>
|
|
72
|
+
<StyledIconWrapper
|
|
73
|
+
style={
|
|
74
|
+
valueIndex === index && {
|
|
75
|
+
transform: [{ scale }],
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
>
|
|
79
|
+
<Icon
|
|
80
|
+
icon={index <= valueIndex ? 'star' : 'star-outlined'}
|
|
81
|
+
intent={disabled ? 'disabled-text' : 'primary'}
|
|
82
|
+
/>
|
|
83
|
+
</StyledIconWrapper>
|
|
84
|
+
</Pressable>
|
|
85
|
+
))}
|
|
86
|
+
</StyledWrapper>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export default Rate;
|
package/src/index.ts
CHANGED
|
@@ -55,6 +55,7 @@ import TimePicker from './components/TimePicker';
|
|
|
55
55
|
import Toast from './components/Toast';
|
|
56
56
|
import Toolbar from './components/Toolbar';
|
|
57
57
|
import Typography from './components/Typography';
|
|
58
|
+
import Rate from './components/Rate';
|
|
58
59
|
import RefreshControl from './components/RefreshControl';
|
|
59
60
|
import RichTextEditor from './components/RichTextEditor';
|
|
60
61
|
import PageControl from './components/PageControl';
|
|
@@ -117,6 +118,7 @@ export {
|
|
|
117
118
|
Toast,
|
|
118
119
|
Toolbar,
|
|
119
120
|
Typography,
|
|
121
|
+
Rate,
|
|
120
122
|
RefreshControl,
|
|
121
123
|
RichTextEditor,
|
|
122
124
|
};
|
|
@@ -690,6 +690,15 @@ Object {
|
|
|
690
690
|
"groupTopMargin": 4,
|
|
691
691
|
},
|
|
692
692
|
},
|
|
693
|
+
"rate": Object {
|
|
694
|
+
"colors": Object {
|
|
695
|
+
"iconStroke": "#401960",
|
|
696
|
+
},
|
|
697
|
+
"spaces": Object {
|
|
698
|
+
"iconWrapperMarginRight": 4,
|
|
699
|
+
"iconWrapperPadding": 8,
|
|
700
|
+
},
|
|
701
|
+
},
|
|
693
702
|
"refreshControl": Object {
|
|
694
703
|
"colors": Object {
|
|
695
704
|
"indicator": "#401960",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GlobalTheme } from '../global';
|
|
2
|
+
|
|
3
|
+
const getRateTheme = (theme: GlobalTheme) => {
|
|
4
|
+
const colors = {
|
|
5
|
+
iconStroke: theme.colors.primary,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const spaces = {
|
|
9
|
+
iconWrapperPadding: theme.space.small,
|
|
10
|
+
iconWrapperMarginRight: theme.space.xsmall,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
return { colors, spaces };
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default getRateTheme;
|
package/src/theme/getTheme.ts
CHANGED
|
@@ -27,6 +27,7 @@ import getPageControlTheme from './components/pageControl';
|
|
|
27
27
|
import getPinInputTheme from './components/pinInput';
|
|
28
28
|
import getProgressTheme from './components/progress';
|
|
29
29
|
import getRadioTheme from './components/radio';
|
|
30
|
+
import getRateTheme from './components/rate';
|
|
30
31
|
import getRefreshControlTheme from './components/refreshControl';
|
|
31
32
|
import getRichTextEditorTheme from './components/richTextEditor';
|
|
32
33
|
import getSectionHeadingTheme from './components/sectionHeading';
|
|
@@ -76,6 +77,7 @@ type Theme = GlobalTheme & {
|
|
|
76
77
|
pinInput: ReturnType<typeof getPinInputTheme>;
|
|
77
78
|
progress: ReturnType<typeof getProgressTheme>;
|
|
78
79
|
radio: ReturnType<typeof getRadioTheme>;
|
|
80
|
+
rate: ReturnType<typeof getRateTheme>;
|
|
79
81
|
refreshControl: ReturnType<typeof getRefreshControlTheme>;
|
|
80
82
|
richTextEditor: ReturnType<typeof getRichTextEditorTheme>;
|
|
81
83
|
sectionHeading: ReturnType<typeof getSectionHeadingTheme>;
|
|
@@ -131,6 +133,7 @@ const getTheme = (
|
|
|
131
133
|
pinInput: getPinInputTheme(globalTheme),
|
|
132
134
|
progress: getProgressTheme(globalTheme),
|
|
133
135
|
radio: getRadioTheme(globalTheme),
|
|
136
|
+
rate: getRateTheme(globalTheme),
|
|
134
137
|
refreshControl: getRefreshControlTheme(globalTheme),
|
|
135
138
|
richTextEditor: getRichTextEditorTheme(globalTheme),
|
|
136
139
|
sectionHeading: getSectionHeadingTheme(globalTheme),
|
package/testUtils/setup.tsx
CHANGED
|
@@ -10,12 +10,15 @@ jest.mock('react-native-vector-icons', () => ({
|
|
|
10
10
|
jest.mock('react-native', () => {
|
|
11
11
|
const RN = jest.requireActual('react-native');
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
const mockedAnimatedFunctions = {
|
|
14
14
|
start: () => jest.fn(),
|
|
15
15
|
stop: () => jest.fn(),
|
|
16
16
|
_isUsingNativeDriver: () => jest.fn(),
|
|
17
17
|
_startNativeLoop: () => jest.fn(),
|
|
18
|
-
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
RN.Animated.timing = () => mockedAnimatedFunctions;
|
|
21
|
+
RN.Animated.spring = () => mockedAnimatedFunctions;
|
|
19
22
|
|
|
20
23
|
return RN;
|
|
21
24
|
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { Animated, View } from 'react-native';
|
|
3
|
+
declare const StyledWrapper: import("@emotion/native").StyledComponent<import("../Box").BoxProps & {
|
|
4
|
+
theme?: import("@emotion/react").Theme | undefined;
|
|
5
|
+
as?: import("react").ElementType<any> | undefined;
|
|
6
|
+
}, {}, {}>;
|
|
7
|
+
declare const StyledIconWrapper: import("@emotion/native").StyledComponent<Animated.AnimatedProps<import("react-native").ViewProps & import("react").RefAttributes<View>> & {
|
|
8
|
+
children?: import("react").ReactNode;
|
|
9
|
+
} & {
|
|
10
|
+
theme?: import("@emotion/react").Theme | undefined;
|
|
11
|
+
as?: import("react").ElementType<any> | undefined;
|
|
12
|
+
}, {}, {}>;
|
|
13
|
+
export { StyledWrapper, StyledIconWrapper };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ViewProps } from 'react-native';
|
|
2
|
+
export interface RateOption<T extends string | number> {
|
|
3
|
+
value: T;
|
|
4
|
+
}
|
|
5
|
+
export interface RateProps<T extends string | number> extends ViewProps {
|
|
6
|
+
/**
|
|
7
|
+
* Options for rate component.
|
|
8
|
+
*/
|
|
9
|
+
options: RateOption<T>[];
|
|
10
|
+
/**
|
|
11
|
+
* Value of the component.
|
|
12
|
+
*/
|
|
13
|
+
value?: T;
|
|
14
|
+
/**
|
|
15
|
+
* Callback when value changes.
|
|
16
|
+
*/
|
|
17
|
+
onChange?: (value: T) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Whether the component is readonly.
|
|
20
|
+
*/
|
|
21
|
+
readonly?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Whether the component is disabled.
|
|
24
|
+
*/
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
}
|
|
27
|
+
declare const Rate: <T extends string | number>({ options, value, onChange, readonly, disabled, ...otherProps }: RateProps<T>) => JSX.Element;
|
|
28
|
+
export default Rate;
|
package/types/index.d.ts
CHANGED
|
@@ -42,8 +42,9 @@ import TimePicker from './components/TimePicker';
|
|
|
42
42
|
import Toast from './components/Toast';
|
|
43
43
|
import Toolbar from './components/Toolbar';
|
|
44
44
|
import Typography from './components/Typography';
|
|
45
|
+
import Rate from './components/Rate';
|
|
45
46
|
import RefreshControl from './components/RefreshControl';
|
|
46
47
|
import RichTextEditor from './components/RichTextEditor';
|
|
47
48
|
import PageControl from './components/PageControl';
|
|
48
|
-
export { theme, getTheme, useTheme, scale, ThemeProvider, ThemeSwitcher, withTheme, swagSystemPalette, swagDarkSystemPalette, workSystemPalette, jobsSystemPalette, walletSystemPalette, eBensSystemPalette, Accordion, Alert, Attachment, Avatar, useAvatarColors, Badge, BottomNavigation, BottomSheet, Box, Button, Calendar, Card, Carousel, Collapse, Checkbox, ContentNavigator, DatePicker, Divider, Drawer, Empty, Error, FAB, Icon, Image, List, PinInput, Progress, PageControl, Skeleton, Slider, Spinner, Swipeable, Radio, SectionHeading, Select, Success, Switch, Tabs, Tag, TextInput, TimePicker, Toast, Toolbar, Typography, RefreshControl, RichTextEditor, };
|
|
49
|
+
export { theme, getTheme, useTheme, scale, ThemeProvider, ThemeSwitcher, withTheme, swagSystemPalette, swagDarkSystemPalette, workSystemPalette, jobsSystemPalette, walletSystemPalette, eBensSystemPalette, Accordion, Alert, Attachment, Avatar, useAvatarColors, Badge, BottomNavigation, BottomSheet, Box, Button, Calendar, Card, Carousel, Collapse, Checkbox, ContentNavigator, DatePicker, Divider, Drawer, Empty, Error, FAB, Icon, Image, List, PinInput, Progress, PageControl, Skeleton, Slider, Spinner, Swipeable, Radio, SectionHeading, Select, Success, Switch, Tabs, Tag, TextInput, TimePicker, Toast, Toolbar, Typography, Rate, RefreshControl, RichTextEditor, };
|
|
49
50
|
export * from './types';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GlobalTheme } from '../global';
|
|
2
|
+
declare const getRateTheme: (theme: GlobalTheme) => {
|
|
3
|
+
colors: {
|
|
4
|
+
iconStroke: string;
|
|
5
|
+
};
|
|
6
|
+
spaces: {
|
|
7
|
+
iconWrapperPadding: number;
|
|
8
|
+
iconWrapperMarginRight: number;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export default getRateTheme;
|
|
@@ -25,6 +25,7 @@ import getPageControlTheme from './components/pageControl';
|
|
|
25
25
|
import getPinInputTheme from './components/pinInput';
|
|
26
26
|
import getProgressTheme from './components/progress';
|
|
27
27
|
import getRadioTheme from './components/radio';
|
|
28
|
+
import getRateTheme from './components/rate';
|
|
28
29
|
import getRefreshControlTheme from './components/refreshControl';
|
|
29
30
|
import getRichTextEditorTheme from './components/richTextEditor';
|
|
30
31
|
import getSectionHeadingTheme from './components/sectionHeading';
|
|
@@ -72,6 +73,7 @@ declare type Theme = GlobalTheme & {
|
|
|
72
73
|
pinInput: ReturnType<typeof getPinInputTheme>;
|
|
73
74
|
progress: ReturnType<typeof getProgressTheme>;
|
|
74
75
|
radio: ReturnType<typeof getRadioTheme>;
|
|
76
|
+
rate: ReturnType<typeof getRateTheme>;
|
|
75
77
|
refreshControl: ReturnType<typeof getRefreshControlTheme>;
|
|
76
78
|
richTextEditor: ReturnType<typeof getRichTextEditorTheme>;
|
|
77
79
|
sectionHeading: ReturnType<typeof getSectionHeadingTheme>;
|