@hero-design/rn 8.20.0 → 8.21.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/.turbo/turbo-build.log +9 -9
- package/es/index.js +190 -60
- package/lib/index.js +190 -60
- package/package.json +5 -5
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Button/StyledButton.tsx +0 -3
- package/src/components/Button/__tests__/__snapshots__/Button.spec.tsx.snap +0 -10
- package/src/components/Button/__tests__/__snapshots__/StyledButton.spec.tsx.snap +0 -16
- package/src/components/Calendar/index.tsx +7 -2
- package/src/components/Carousel/StyledCarousel.tsx +11 -3
- package/src/components/Carousel/__tests__/__snapshots__/index.spec.tsx.snap +791 -6
- package/src/components/Carousel/__tests__/index.spec.tsx +41 -31
- package/src/components/Carousel/index.tsx +39 -7
- package/src/components/DatePicker/DatePickerAndroid.tsx +1 -1
- package/src/components/DatePicker/DatePickerCalendar.tsx +110 -0
- package/src/components/DatePicker/DatePickerIOS.tsx +1 -1
- package/src/components/DatePicker/__tests__/DatePicker.spec.tsx +27 -8
- package/src/components/DatePicker/__tests__/DatePickerCalendar.spec.tsx +61 -0
- package/src/components/DatePicker/__tests__/__snapshots__/DatePicker.spec.tsx.snap +670 -0
- package/src/components/DatePicker/__tests__/__snapshots__/DatePickerCalendar.spec.tsx.snap +220 -0
- package/src/components/DatePicker/__tests__/__snapshots__/DatePickerIOS.spec.tsx.snap +0 -1
- package/src/components/DatePicker/index.tsx +5 -1
- package/src/components/DatePicker/types.ts +7 -1
- package/src/components/Select/MultiSelect/__tests__/__snapshots__/index.spec.tsx.snap +0 -3
- package/src/components/TimePicker/__tests__/__snapshots__/TimePickerIOS.spec.tsx.snap +0 -1
- package/src/components/TimePicker/types.ts +1 -1
- package/src/components/Toast/Toast.tsx +3 -1
- package/src/components/Toast/types.ts +4 -0
- package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +2 -3
- package/src/theme/components/button.ts +0 -5
- package/src/theme/components/carousel.ts +3 -0
- package/types/components/Calendar/index.d.ts +6 -2
- package/types/components/Carousel/StyledCarousel.d.ts +7 -1
- package/types/components/Carousel/index.d.ts +7 -1
- package/types/components/DatePicker/DatePickerAndroid.d.ts +1 -1
- package/types/components/DatePicker/DatePickerCalendar.d.ts +3 -0
- package/types/components/DatePicker/DatePickerIOS.d.ts +1 -1
- package/types/components/DatePicker/index.d.ts +1 -1
- package/types/components/DatePicker/types.d.ts +7 -1
- package/types/components/TimePicker/types.d.ts +1 -1
- package/types/components/Toast/Toast.d.ts +1 -1
- package/types/components/Toast/types.d.ts +4 -0
- package/types/theme/components/button.d.ts +0 -3
- package/types/theme/components/carousel.d.ts +2 -0
|
@@ -44,43 +44,53 @@ const carouselData = [
|
|
|
44
44
|
];
|
|
45
45
|
|
|
46
46
|
describe('Carousel', () => {
|
|
47
|
-
it
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
it.each`
|
|
48
|
+
pageControlPosition
|
|
49
|
+
${'bottom'}
|
|
50
|
+
${'top'}
|
|
51
|
+
`(
|
|
52
|
+
'renders correctly with pageControlPosition $pageControlPosition',
|
|
53
|
+
async ({ pageControlPosition }) => {
|
|
54
|
+
const onPress = jest.fn();
|
|
55
|
+
const { getByTestId, queryByText, toJSON } = renderWithTheme(
|
|
56
|
+
<Carousel
|
|
57
|
+
pageControlPosition={pageControlPosition}
|
|
58
|
+
testID="carousel"
|
|
59
|
+
items={carouselData}
|
|
60
|
+
renderActions={(_) => {
|
|
61
|
+
return <Button text="Skip" onPress={onPress} />;
|
|
62
|
+
}}
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
58
65
|
|
|
59
|
-
|
|
66
|
+
expect(getByTestId('carousel')).toBeTruthy();
|
|
60
67
|
|
|
61
|
-
|
|
68
|
+
expect(queryByText('Skip')).toBeTruthy();
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
// Slide 1
|
|
71
|
+
expect(
|
|
72
|
+
queryByText('Welcome to the new Employment Hero app')
|
|
73
|
+
).toBeTruthy();
|
|
65
74
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
// Slide 2
|
|
76
|
+
expect(queryByText('Same app with a new look!')).toBeTruthy();
|
|
77
|
+
expect(
|
|
78
|
+
queryByText(
|
|
79
|
+
'Our app now has a new bright clean modern look and feel with the same great features.'
|
|
80
|
+
)
|
|
81
|
+
).toBeTruthy();
|
|
73
82
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
83
|
+
// Slide 3
|
|
84
|
+
expect(queryByText('Easier to get around')).toBeTruthy();
|
|
85
|
+
expect(
|
|
86
|
+
queryByText(
|
|
87
|
+
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vitae pulvinar quam, ac facilisis massa. Aliquam facilisis nisi eu justo dignissim, vel tempus justo iaculis.'
|
|
88
|
+
)
|
|
89
|
+
).toBeTruthy();
|
|
81
90
|
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
expect(toJSON()).toMatchSnapshot();
|
|
92
|
+
}
|
|
93
|
+
);
|
|
84
94
|
|
|
85
95
|
it('should call skip call back when press skip', () => {
|
|
86
96
|
const onSkip = jest.fn();
|
|
@@ -22,9 +22,11 @@ import {
|
|
|
22
22
|
StyledCarouselFooterWrapper,
|
|
23
23
|
StyledCarouselView,
|
|
24
24
|
StyledPageControl,
|
|
25
|
+
StyledPageControlWrapper,
|
|
25
26
|
} from './StyledCarousel';
|
|
26
27
|
import CarouselItem from './CarouselItem';
|
|
27
28
|
import { CardCarousel } from './CardCarousel';
|
|
29
|
+
import { useDeprecation } from '../../utils/hooks';
|
|
28
30
|
|
|
29
31
|
interface CarouselProps extends ViewProps {
|
|
30
32
|
/**
|
|
@@ -48,6 +50,8 @@ interface CarouselProps extends ViewProps {
|
|
|
48
50
|
*/
|
|
49
51
|
renderActions?: (pageIndex: number) => JSX.Element;
|
|
50
52
|
/**
|
|
53
|
+
* @deprecated will be removed in 9.0.0
|
|
54
|
+
*
|
|
51
55
|
* Should show paginations
|
|
52
56
|
*/
|
|
53
57
|
shouldShowPagination?: (pageIndex: number) => boolean;
|
|
@@ -55,6 +59,10 @@ interface CarouselProps extends ViewProps {
|
|
|
55
59
|
* Current selected item index.
|
|
56
60
|
*/
|
|
57
61
|
selectedItemIndex?: number;
|
|
62
|
+
/**
|
|
63
|
+
* position of the page control
|
|
64
|
+
*/
|
|
65
|
+
pageControlPosition?: 'top' | 'bottom';
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
export function useStateFromProp<T>(
|
|
@@ -67,15 +75,27 @@ export function useStateFromProp<T>(
|
|
|
67
75
|
return [value, setValue];
|
|
68
76
|
}
|
|
69
77
|
|
|
78
|
+
const noop = (_: number): boolean => {
|
|
79
|
+
return true;
|
|
80
|
+
};
|
|
70
81
|
const Carousel = ({
|
|
71
82
|
items,
|
|
72
83
|
onItemIndexChange,
|
|
73
84
|
renderActions,
|
|
74
85
|
selectedItemIndex = 0,
|
|
75
86
|
style,
|
|
76
|
-
shouldShowPagination =
|
|
87
|
+
shouldShowPagination = noop,
|
|
88
|
+
pageControlPosition = 'bottom',
|
|
77
89
|
...nativeProps
|
|
78
90
|
}: CarouselProps) => {
|
|
91
|
+
useDeprecation(
|
|
92
|
+
`shouldShowPagination prop has been deprecated`,
|
|
93
|
+
shouldShowPagination !== noop
|
|
94
|
+
);
|
|
95
|
+
useDeprecation(
|
|
96
|
+
`The use of 'pageControlPosition == bottom' has been deprecated`,
|
|
97
|
+
pageControlPosition !== 'bottom'
|
|
98
|
+
);
|
|
79
99
|
const carouselRef = useRef<FlatList>(null);
|
|
80
100
|
|
|
81
101
|
const [currentSlideIndex, setCurrentSlideIndex] =
|
|
@@ -120,6 +140,17 @@ const Carousel = ({
|
|
|
120
140
|
<StyledBackDrop
|
|
121
141
|
themeSlideBackground={items[currentSlideIndex].background}
|
|
122
142
|
/>
|
|
143
|
+
|
|
144
|
+
<StyledPageControlWrapper>
|
|
145
|
+
{pageControlPosition === 'top' &&
|
|
146
|
+
shouldShowPagination(currentSlideIndex) && (
|
|
147
|
+
<StyledPageControl
|
|
148
|
+
numberOfPages={items.length}
|
|
149
|
+
currentPage={currentSlideIndex}
|
|
150
|
+
/>
|
|
151
|
+
)}
|
|
152
|
+
</StyledPageControlWrapper>
|
|
153
|
+
|
|
123
154
|
<StyledCarouselView>
|
|
124
155
|
<FlatList
|
|
125
156
|
horizontal
|
|
@@ -153,12 +184,13 @@ const Carousel = ({
|
|
|
153
184
|
/>
|
|
154
185
|
<StyledCarouselFooterWrapper>
|
|
155
186
|
{renderActions && renderActions(currentSlideIndex)}
|
|
156
|
-
{
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
187
|
+
{pageControlPosition === 'bottom' &&
|
|
188
|
+
shouldShowPagination(currentSlideIndex) && (
|
|
189
|
+
<StyledPageControl
|
|
190
|
+
numberOfPages={items.length}
|
|
191
|
+
currentPage={currentSlideIndex}
|
|
192
|
+
/>
|
|
193
|
+
)}
|
|
162
194
|
</StyledCarouselFooterWrapper>
|
|
163
195
|
</StyledCarouselView>
|
|
164
196
|
</View>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import formatDate from 'date-fns/fp/format';
|
|
4
|
+
|
|
5
|
+
import BottomSheet from '../BottomSheet';
|
|
6
|
+
import TextInput from '../TextInput';
|
|
7
|
+
import Button from '../Button';
|
|
8
|
+
import type { DatePickerProps } from './types';
|
|
9
|
+
import Calendar, { CalendarProps } from '../Calendar';
|
|
10
|
+
|
|
11
|
+
const InternalCalendar = ({
|
|
12
|
+
minDate,
|
|
13
|
+
maxDate,
|
|
14
|
+
value,
|
|
15
|
+
onChange,
|
|
16
|
+
}: Pick<CalendarProps, 'minDate' | 'maxDate' | 'value' | 'onChange'>) => {
|
|
17
|
+
const [visibleDate, setVisibleDate] = useState(value || new Date());
|
|
18
|
+
const [selectingDate, setSelectingDate] = useState<Date>(value || new Date());
|
|
19
|
+
return (
|
|
20
|
+
<Calendar
|
|
21
|
+
testID="calendar"
|
|
22
|
+
value={selectingDate}
|
|
23
|
+
visibleDate={visibleDate}
|
|
24
|
+
onChange={(date) => {
|
|
25
|
+
setSelectingDate(date);
|
|
26
|
+
if (onChange) {
|
|
27
|
+
onChange(date);
|
|
28
|
+
}
|
|
29
|
+
}}
|
|
30
|
+
onPreviousPress={() =>
|
|
31
|
+
setVisibleDate(
|
|
32
|
+
new Date(visibleDate.getFullYear(), visibleDate.getMonth() - 1, 1)
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
onNextPress={() =>
|
|
36
|
+
setVisibleDate(
|
|
37
|
+
new Date(visibleDate.getFullYear(), visibleDate.getMonth() + 1, 1)
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
minDate={minDate}
|
|
41
|
+
maxDate={maxDate}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const DatePickerCalendar = ({
|
|
47
|
+
value,
|
|
48
|
+
minDate = new Date('1900-01-01T00:00:00.000Z'),
|
|
49
|
+
maxDate = new Date('2100-01-01T00:00:00.000Z'),
|
|
50
|
+
label,
|
|
51
|
+
placeholder,
|
|
52
|
+
onChange,
|
|
53
|
+
confirmLabel,
|
|
54
|
+
displayFormat = 'dd/MM/yyyy',
|
|
55
|
+
disabled = false,
|
|
56
|
+
required,
|
|
57
|
+
error,
|
|
58
|
+
helpText,
|
|
59
|
+
style,
|
|
60
|
+
testID,
|
|
61
|
+
}: Omit<DatePickerProps, 'variant'>) => {
|
|
62
|
+
const [open, setOpen] = useState(false);
|
|
63
|
+
|
|
64
|
+
const [selectingDate, setSelectingDate] = useState<Date>(value || new Date());
|
|
65
|
+
const displayValue = value ? formatDate(displayFormat, value) : '';
|
|
66
|
+
return (
|
|
67
|
+
<TouchableOpacity onPress={() => setOpen(true)} disabled={disabled}>
|
|
68
|
+
<View pointerEvents="none" testID="datePickerCalendar">
|
|
69
|
+
<TextInput
|
|
70
|
+
label={label}
|
|
71
|
+
value={displayValue}
|
|
72
|
+
suffix="calendar-dates-outlined"
|
|
73
|
+
placeholder={placeholder || displayFormat}
|
|
74
|
+
disabled={disabled}
|
|
75
|
+
error={error}
|
|
76
|
+
required={required}
|
|
77
|
+
helpText={helpText}
|
|
78
|
+
testID={testID}
|
|
79
|
+
style={style}
|
|
80
|
+
/>
|
|
81
|
+
</View>
|
|
82
|
+
<BottomSheet
|
|
83
|
+
open={open}
|
|
84
|
+
onRequestClose={() => setOpen(false)}
|
|
85
|
+
header={label}
|
|
86
|
+
footer={
|
|
87
|
+
<Button
|
|
88
|
+
variant="text"
|
|
89
|
+
text={confirmLabel}
|
|
90
|
+
onPress={() => {
|
|
91
|
+
if (selectingDate) {
|
|
92
|
+
onChange(selectingDate);
|
|
93
|
+
}
|
|
94
|
+
setOpen(false);
|
|
95
|
+
}}
|
|
96
|
+
/>
|
|
97
|
+
}
|
|
98
|
+
>
|
|
99
|
+
<InternalCalendar
|
|
100
|
+
minDate={minDate}
|
|
101
|
+
maxDate={maxDate}
|
|
102
|
+
value={value}
|
|
103
|
+
onChange={setSelectingDate}
|
|
104
|
+
/>
|
|
105
|
+
</BottomSheet>
|
|
106
|
+
</TouchableOpacity>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export default DatePickerCalendar;
|
|
@@ -25,7 +25,7 @@ const DatePickerIOS = ({
|
|
|
25
25
|
helpText,
|
|
26
26
|
style,
|
|
27
27
|
testID,
|
|
28
|
-
}: DatePickerProps) => {
|
|
28
|
+
}: Omit<DatePickerProps, 'variant'>) => {
|
|
29
29
|
const [selectingDate, setSelectingDate] = useState<Date>(value || new Date());
|
|
30
30
|
const [open, setOpen] = useState(false);
|
|
31
31
|
|
|
@@ -6,33 +6,52 @@ import renderWithTheme from '../../../testHelpers/renderWithTheme';
|
|
|
6
6
|
describe('DatePicker', () => {
|
|
7
7
|
it('renders DatePickerIOS when OS is iOS', () => {
|
|
8
8
|
Platform.OS = 'ios';
|
|
9
|
-
const { getByTestId } = renderWithTheme(
|
|
9
|
+
const { getByTestId, toJSON } = renderWithTheme(
|
|
10
10
|
<DatePicker
|
|
11
11
|
label="Start date"
|
|
12
|
-
value={new Date('
|
|
13
|
-
minDate={new Date('
|
|
14
|
-
maxDate={new Date('
|
|
12
|
+
value={new Date('1995-12-17T00:00:00.000Z')}
|
|
13
|
+
minDate={new Date('1994-12-17T00:00:00.000Z')}
|
|
14
|
+
maxDate={new Date('1996-12-17T00:00:00.000Z')}
|
|
15
15
|
confirmLabel="Confirm"
|
|
16
16
|
onChange={jest.fn()}
|
|
17
17
|
/>
|
|
18
18
|
);
|
|
19
19
|
|
|
20
|
+
expect(toJSON()).toMatchSnapshot();
|
|
20
21
|
expect(getByTestId('datePickerInputIOS')).toBeDefined();
|
|
21
22
|
});
|
|
22
23
|
|
|
23
24
|
it('renders DatePickerAndroid when OS is android', () => {
|
|
24
25
|
Platform.OS = 'android';
|
|
25
|
-
const { getByTestId } = renderWithTheme(
|
|
26
|
+
const { getByTestId, toJSON } = renderWithTheme(
|
|
26
27
|
<DatePicker
|
|
27
28
|
label="Start date"
|
|
28
|
-
value={new Date('
|
|
29
|
-
minDate={new Date('
|
|
30
|
-
maxDate={new Date('
|
|
29
|
+
value={new Date('1995-12-17T00:00:00.000Z')}
|
|
30
|
+
minDate={new Date('1994-12-17T00:00:00.000Z')}
|
|
31
|
+
maxDate={new Date('1996-12-17T00:00:00.000Z')}
|
|
31
32
|
confirmLabel="Confirm"
|
|
32
33
|
onChange={jest.fn()}
|
|
33
34
|
/>
|
|
34
35
|
);
|
|
35
36
|
|
|
37
|
+
expect(toJSON()).toMatchSnapshot();
|
|
36
38
|
expect(getByTestId('datePickerInputAndroid')).toBeDefined();
|
|
37
39
|
});
|
|
40
|
+
|
|
41
|
+
it('renders variant Calendar', () => {
|
|
42
|
+
const { toJSON, getByTestId } = renderWithTheme(
|
|
43
|
+
<DatePicker
|
|
44
|
+
label="Start date"
|
|
45
|
+
value={new Date('1995-12-17T00:00:00.000Z')}
|
|
46
|
+
minDate={new Date('1994-12-17T00:00:00.000Z')}
|
|
47
|
+
maxDate={new Date('1996-12-17T00:00:00.000Z')}
|
|
48
|
+
confirmLabel="Confirm"
|
|
49
|
+
variant="calendar"
|
|
50
|
+
onChange={jest.fn()}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(toJSON()).toMatchSnapshot();
|
|
55
|
+
expect(getByTestId('datePickerCalendar')).toBeDefined();
|
|
56
|
+
});
|
|
38
57
|
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { fireEvent } from '@testing-library/react-native';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import type { ModalProps } from 'react-native';
|
|
4
|
+
import renderWithTheme from '../../../testHelpers/renderWithTheme';
|
|
5
|
+
import DatePickerCalendar from '../DatePickerCalendar';
|
|
6
|
+
|
|
7
|
+
jest.mock('react-native/Libraries/Modal/Modal', () => {
|
|
8
|
+
const Modal = jest.requireActual('react-native/Libraries/Modal/Modal');
|
|
9
|
+
return (props: ModalProps) => <Modal {...props} />;
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe('DatePickerCalendar', () => {
|
|
13
|
+
it('renders correctly', () => {
|
|
14
|
+
const onChange = jest.fn();
|
|
15
|
+
const { getByText, queryByTestId, toJSON } = renderWithTheme(
|
|
16
|
+
<DatePickerCalendar
|
|
17
|
+
value={new Date('1995-12-21T00:00:00.000Z')}
|
|
18
|
+
label="Start date"
|
|
19
|
+
confirmLabel="Confirm"
|
|
20
|
+
onChange={onChange}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
expect(toJSON()).toMatchSnapshot();
|
|
25
|
+
expect(getByText('Start date')).toBeDefined();
|
|
26
|
+
expect(queryByTestId('text-input').props.value).toBe('21/12/1995');
|
|
27
|
+
expect(queryByTestId('calendar')).toBeNull();
|
|
28
|
+
|
|
29
|
+
// Open date picker
|
|
30
|
+
fireEvent.press(getByText('Start date'));
|
|
31
|
+
expect(queryByTestId('calendar')).toBeTruthy();
|
|
32
|
+
|
|
33
|
+
expect(getByText('December 1995')).toBeDefined();
|
|
34
|
+
expect(getByText('Mo')).toBeDefined();
|
|
35
|
+
expect(getByText('Tu')).toBeDefined();
|
|
36
|
+
expect(getByText('We')).toBeDefined();
|
|
37
|
+
expect(getByText('Th')).toBeDefined();
|
|
38
|
+
expect(getByText('Fr')).toBeDefined();
|
|
39
|
+
expect(getByText('Sa')).toBeDefined();
|
|
40
|
+
expect(getByText('Su')).toBeDefined();
|
|
41
|
+
// Change date
|
|
42
|
+
fireEvent.press(getByText('14'));
|
|
43
|
+
fireEvent.press(getByText('Confirm'));
|
|
44
|
+
|
|
45
|
+
expect(onChange).toBeCalledWith(new Date('1995-12-14T00:00:00.000Z'));
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('renders correct help text', () => {
|
|
49
|
+
const { getByText } = renderWithTheme(
|
|
50
|
+
<DatePickerCalendar
|
|
51
|
+
value={new Date('December 21, 1995')}
|
|
52
|
+
label="Start date"
|
|
53
|
+
confirmLabel="Confirm"
|
|
54
|
+
helpText="This is help text"
|
|
55
|
+
onChange={jest.fn()}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
expect(getByText('This is help text')).toBeTruthy();
|
|
60
|
+
});
|
|
61
|
+
});
|