@hero-design/rn 8.63.3 → 8.64.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 +1 -1
- package/CHANGELOG.md +6 -0
- package/es/index.js +85 -38
- package/eslint.config.js +42 -0
- package/lib/index.js +85 -38
- package/package.json +7 -3
- package/rollup.config.js +13 -0
- package/sonar-project.properties +1 -1
- package/src/components/BottomSheet/__tests__/__snapshots__/index.spec.tsx.snap +5 -0
- package/src/components/BottomSheet/__tests__/index.spec.tsx +17 -0
- package/src/components/BottomSheet/index.tsx +6 -0
- package/src/components/Calendar/CalendarRowItem.tsx +3 -1
- package/src/components/Calendar/StyledCalendar.tsx +21 -8
- package/src/components/Calendar/__tests__/CalendarRowItem.spec.tsx +1 -0
- package/src/components/Calendar/__tests__/__snapshots__/CalendarRowItem.spec.tsx.snap +4 -2
- package/src/components/Calendar/__tests__/index.spec.tsx +7 -1
- package/src/components/Calendar/index.tsx +30 -8
- package/src/components/DatePicker/DatePickerCalendar.tsx +14 -10
- package/src/components/DatePicker/DatePickerIOS.tsx +2 -0
- package/src/components/DatePicker/__tests__/DatePickerCalendar.spec.tsx +37 -0
- package/src/components/DatePicker/__tests__/DatePickerIOS.spec.tsx +34 -0
- package/src/components/DatePicker/__tests__/__snapshots__/DatePickerIOS.spec.tsx.snap +5 -0
- package/src/components/DatePicker/types.ts +4 -0
- package/src/components/FAB/ActionGroup/__tests__/__snapshots__/index.spec.tsx.snap +5 -0
- package/src/components/FAB/ActionGroup/__tests__/index.spec.tsx +45 -24
- package/src/components/FAB/ActionGroup/index.tsx +6 -0
- package/src/components/Select/MultiSelect/__tests__/__snapshots__/index.spec.tsx.snap +20 -0
- package/src/components/Select/MultiSelect/__tests__/index.spec.tsx +28 -0
- package/src/components/Select/MultiSelect/index.tsx +6 -0
- package/src/components/Select/SingleSelect/__tests__/__snapshots__/index.spec.tsx.snap +15 -0
- package/src/components/Select/SingleSelect/__tests__/index.spec.tsx +25 -0
- package/src/components/Select/SingleSelect/index.tsx +6 -0
- package/src/components/TimePicker/TimePickerIOS.tsx +2 -0
- package/src/components/TimePicker/__tests__/TimePickerIOS.spec.tsx +31 -0
- package/src/components/TimePicker/__tests__/__snapshots__/TimePickerIOS.spec.tsx.snap +5 -0
- package/src/components/TimePicker/types.ts +4 -0
- package/src/testHelpers/utils.ts +21 -0
- package/stats/8.63.3/rn-stats.html +4844 -0
- package/stats/8.64.0/rn-stats.html +4842 -0
- package/types/components/BottomSheet/index.d.ts +5 -1
- package/types/components/Calendar/CalendarRowItem.d.ts +2 -1
- package/types/components/Calendar/StyledCalendar.d.ts +7 -0
- package/types/components/DatePicker/DatePickerCalendar.d.ts +1 -1
- package/types/components/DatePicker/DatePickerIOS.d.ts +1 -1
- package/types/components/DatePicker/types.d.ts +4 -0
- package/types/components/FAB/ActionGroup/index.d.ts +4 -0
- package/types/components/Select/MultiSelect/index.d.ts +5 -1
- package/types/components/Select/SingleSelect/index.d.ts +5 -1
- package/types/components/Select/index.d.ts +1 -1
- package/types/components/TimePicker/TimePickerIOS.d.ts +1 -1
- package/types/components/TimePicker/types.d.ts +4 -0
- package/types/testHelpers/utils.d.ts +1 -0
- package/.eslintrc.js +0 -13
- package/src/theme/components/.eslintrc.json +0 -10
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
MonthYearPickerViewIOS,
|
|
4
4
|
} from '@hero-design/react-native-month-year-picker';
|
|
5
5
|
import format from 'date-fns/fp/format';
|
|
6
|
-
import React from 'react';
|
|
6
|
+
import React, { useMemo, useState } from 'react';
|
|
7
7
|
import { Platform, TouchableOpacity } from 'react-native';
|
|
8
8
|
import { useTheme } from '../../theme';
|
|
9
9
|
import { noop } from '../../utils/functions';
|
|
@@ -121,8 +121,13 @@ const Calendar = ({
|
|
|
121
121
|
}),
|
|
122
122
|
{}
|
|
123
123
|
);
|
|
124
|
-
const [monthPickerVisible, setMonthPickerVisible] =
|
|
125
|
-
const [contentHeight, setContentHeight] =
|
|
124
|
+
const [monthPickerVisible, setMonthPickerVisible] = useState(false);
|
|
125
|
+
const [contentHeight, setContentHeight] = useState(0);
|
|
126
|
+
const [contentWidth, setContentWidth] = useState(0);
|
|
127
|
+
const calendarItemWidth = useMemo(
|
|
128
|
+
() => (contentWidth > 0 ? contentWidth / 7 : undefined),
|
|
129
|
+
[contentWidth]
|
|
130
|
+
);
|
|
126
131
|
|
|
127
132
|
const useMonthPicker = onMonthChange !== noop;
|
|
128
133
|
|
|
@@ -241,6 +246,7 @@ const Calendar = ({
|
|
|
241
246
|
theme.__hd__.calendar.space.iosPickerMarginVertical * 2,
|
|
242
247
|
marginVertical:
|
|
243
248
|
-theme.__hd__.calendar.space.iosPickerMarginVertical,
|
|
249
|
+
width: contentWidth,
|
|
244
250
|
}}
|
|
245
251
|
/>
|
|
246
252
|
</Box>
|
|
@@ -248,14 +254,18 @@ const Calendar = ({
|
|
|
248
254
|
<Box
|
|
249
255
|
onLayout={
|
|
250
256
|
Platform.OS === 'ios'
|
|
251
|
-
? (e) =>
|
|
257
|
+
? (e) => {
|
|
258
|
+
const { width, height } = e.nativeEvent.layout;
|
|
259
|
+
setContentHeight(height);
|
|
260
|
+
setContentWidth(width);
|
|
261
|
+
}
|
|
252
262
|
: undefined
|
|
253
263
|
}
|
|
254
264
|
>
|
|
255
265
|
<StyledCalendarRow>
|
|
256
266
|
{DAYS_OF_WEEK.map((day) => (
|
|
257
267
|
<StyledCalendarRowItem key={day}>
|
|
258
|
-
<StyledCalendarDayNameCell>
|
|
268
|
+
<StyledCalendarDayNameCell themeItemWidth={calendarItemWidth}>
|
|
259
269
|
<Typography.Body variant="small">{day}</Typography.Body>
|
|
260
270
|
</StyledCalendarDayNameCell>
|
|
261
271
|
</StyledCalendarRowItem>
|
|
@@ -272,14 +282,19 @@ const Calendar = ({
|
|
|
272
282
|
onPress={() => onChange?.(date)}
|
|
273
283
|
textIntent="subdued"
|
|
274
284
|
marked={parsedMaskedDate[date.toDateString()]}
|
|
285
|
+
itemWidth={contentWidth > 0 ? contentWidth / 7 : undefined}
|
|
275
286
|
/>
|
|
276
287
|
) : (
|
|
277
|
-
<StyledDisabledCalendarRowItem
|
|
288
|
+
<StyledDisabledCalendarRowItem
|
|
289
|
+
themeItemWidth={calendarItemWidth}
|
|
290
|
+
testID="calendar-disabled-cell"
|
|
291
|
+
/>
|
|
278
292
|
)
|
|
279
293
|
)}
|
|
280
294
|
{daysOfCurrentMonth.map((date) =>
|
|
281
295
|
date ? (
|
|
282
296
|
<CalendarRowItem
|
|
297
|
+
itemWidth={calendarItemWidth}
|
|
283
298
|
key={date.toDateString()}
|
|
284
299
|
date={date}
|
|
285
300
|
isCurrent={isEqDate(now, date)}
|
|
@@ -288,12 +303,16 @@ const Calendar = ({
|
|
|
288
303
|
marked={parsedMaskedDate[date.toDateString()]}
|
|
289
304
|
/>
|
|
290
305
|
) : (
|
|
291
|
-
<StyledDisabledCalendarRowItem
|
|
306
|
+
<StyledDisabledCalendarRowItem
|
|
307
|
+
themeItemWidth={calendarItemWidth}
|
|
308
|
+
testID="calendar-disabled-cell"
|
|
309
|
+
/>
|
|
292
310
|
)
|
|
293
311
|
)}
|
|
294
312
|
{daysOfNextMonth.map((date) =>
|
|
295
313
|
date ? (
|
|
296
314
|
<CalendarRowItem
|
|
315
|
+
itemWidth={calendarItemWidth}
|
|
297
316
|
key={date.toDateString()}
|
|
298
317
|
date={date}
|
|
299
318
|
isCurrent={isEqDate(now, date)}
|
|
@@ -303,7 +322,10 @@ const Calendar = ({
|
|
|
303
322
|
marked={parsedMaskedDate[date.toDateString()]}
|
|
304
323
|
/>
|
|
305
324
|
) : (
|
|
306
|
-
<StyledDisabledCalendarRowItem
|
|
325
|
+
<StyledDisabledCalendarRowItem
|
|
326
|
+
themeItemWidth={calendarItemWidth}
|
|
327
|
+
testID="calendar-disabled-cell"
|
|
328
|
+
/>
|
|
307
329
|
)
|
|
308
330
|
)}
|
|
309
331
|
</StyledCalendarRow>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import formatDate from 'date-fns/fp/format';
|
|
2
2
|
import React, { useState } from 'react';
|
|
3
|
-
import { Platform, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import { Platform, ScrollView, TouchableOpacity, View } from 'react-native';
|
|
4
4
|
|
|
5
5
|
import BottomSheet from '../BottomSheet';
|
|
6
6
|
import Button from '../Button';
|
|
@@ -77,6 +77,7 @@ const DatePickerCalendar = ({
|
|
|
77
77
|
testID,
|
|
78
78
|
monthPickerConfirmLabel,
|
|
79
79
|
monthPickerCancelLabel,
|
|
80
|
+
supportedOrientations = ['portrait'],
|
|
80
81
|
}: Omit<DatePickerProps, 'variant'>) => {
|
|
81
82
|
const [open, setOpen] = useState(false);
|
|
82
83
|
const [monthPickerVisible, setMonthPickerVisible] = useState(false);
|
|
@@ -121,16 +122,19 @@ const DatePickerCalendar = ({
|
|
|
121
122
|
/>
|
|
122
123
|
)
|
|
123
124
|
}
|
|
125
|
+
supportedOrientations={supportedOrientations}
|
|
124
126
|
>
|
|
125
|
-
<
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
127
|
+
<ScrollView>
|
|
128
|
+
<InternalCalendar
|
|
129
|
+
minDate={minDate}
|
|
130
|
+
maxDate={maxDate}
|
|
131
|
+
value={value}
|
|
132
|
+
onChange={setSelectingDate}
|
|
133
|
+
monthPickerConfirmLabel={monthPickerConfirmLabel}
|
|
134
|
+
monthPickerCancelLabel={monthPickerCancelLabel}
|
|
135
|
+
onToggleMonthPicker={(visible) => setMonthPickerVisible(visible)}
|
|
136
|
+
/>
|
|
137
|
+
</ScrollView>
|
|
134
138
|
</BottomSheet>
|
|
135
139
|
</TouchableOpacity>
|
|
136
140
|
);
|
|
@@ -26,6 +26,7 @@ const DatePickerIOS = ({
|
|
|
26
26
|
helpText,
|
|
27
27
|
style,
|
|
28
28
|
testID,
|
|
29
|
+
supportedOrientations = ['portrait'],
|
|
29
30
|
}: Omit<
|
|
30
31
|
DatePickerProps,
|
|
31
32
|
'variant' | 'monthPickerConfirmLabel' | 'monthPickerCancelLabel'
|
|
@@ -71,6 +72,7 @@ const DatePickerIOS = ({
|
|
|
71
72
|
}}
|
|
72
73
|
/>
|
|
73
74
|
}
|
|
75
|
+
supportedOrientations={supportedOrientations}
|
|
74
76
|
>
|
|
75
77
|
<StyledPickerWrapper>
|
|
76
78
|
<DateTimePicker
|
|
@@ -3,6 +3,7 @@ import React from 'react';
|
|
|
3
3
|
import type { ModalProps } from 'react-native';
|
|
4
4
|
import renderWithTheme from '../../../testHelpers/renderWithTheme';
|
|
5
5
|
import DatePickerCalendar from '../DatePickerCalendar';
|
|
6
|
+
import { setOrientation } from '../../../testHelpers/utils';
|
|
6
7
|
|
|
7
8
|
jest.mock('react-native/Libraries/Modal/Modal', () => {
|
|
8
9
|
const Modal = jest.requireActual('react-native/Libraries/Modal/Modal');
|
|
@@ -45,6 +46,42 @@ describe('DatePickerCalendar', () => {
|
|
|
45
46
|
expect(onChange).toBeCalledWith(new Date('1995-12-14T00:00:00.000Z'));
|
|
46
47
|
});
|
|
47
48
|
|
|
49
|
+
it('renders correctly in landscape mode', () => {
|
|
50
|
+
setOrientation('landscape');
|
|
51
|
+
const onChange = jest.fn();
|
|
52
|
+
const { getByText, queryByTestId } = renderWithTheme(
|
|
53
|
+
<DatePickerCalendar
|
|
54
|
+
value={new Date('1995-12-21T00:00:00.000Z')}
|
|
55
|
+
label="Start date"
|
|
56
|
+
confirmLabel="Confirm"
|
|
57
|
+
onChange={onChange}
|
|
58
|
+
supportedOrientations={['landscape']}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
expect(getByText('Start date')).toBeDefined();
|
|
63
|
+
expect(queryByTestId('text-input').props.value).toBe('21/12/1995');
|
|
64
|
+
expect(queryByTestId('calendar')).toBeNull();
|
|
65
|
+
|
|
66
|
+
// Open date picker
|
|
67
|
+
fireEvent.press(getByText('Start date'));
|
|
68
|
+
expect(queryByTestId('calendar')).toBeTruthy();
|
|
69
|
+
|
|
70
|
+
expect(getByText('December 1995')).toBeDefined();
|
|
71
|
+
expect(getByText('Mo')).toBeDefined();
|
|
72
|
+
expect(getByText('Tu')).toBeDefined();
|
|
73
|
+
expect(getByText('We')).toBeDefined();
|
|
74
|
+
expect(getByText('Th')).toBeDefined();
|
|
75
|
+
expect(getByText('Fr')).toBeDefined();
|
|
76
|
+
expect(getByText('Sa')).toBeDefined();
|
|
77
|
+
expect(getByText('Su')).toBeDefined();
|
|
78
|
+
// Change date
|
|
79
|
+
fireEvent.press(getByText('14'));
|
|
80
|
+
fireEvent.press(getByText('Confirm'));
|
|
81
|
+
|
|
82
|
+
expect(onChange).toBeCalledWith(new Date('1995-12-14T00:00:00.000Z'));
|
|
83
|
+
});
|
|
84
|
+
|
|
48
85
|
it('renders correct help text', () => {
|
|
49
86
|
const { getByText } = renderWithTheme(
|
|
50
87
|
<DatePickerCalendar
|
|
@@ -4,6 +4,7 @@ import type { ModalProps } from 'react-native';
|
|
|
4
4
|
import renderWithTheme from '../../../testHelpers/renderWithTheme';
|
|
5
5
|
import DatePickerIOS from '../DatePickerIOS';
|
|
6
6
|
import { getDateValue } from '../useCalculateDate';
|
|
7
|
+
import { setOrientation } from '../../../testHelpers/utils';
|
|
7
8
|
|
|
8
9
|
jest.mock('react-native/Libraries/Modal/Modal', () => {
|
|
9
10
|
const Modal = jest.requireActual('react-native/Libraries/Modal/Modal');
|
|
@@ -68,6 +69,39 @@ describe('DatePickerIOS', () => {
|
|
|
68
69
|
expect(onChange).toBeCalledWith(new Date('December 17, 1995'));
|
|
69
70
|
});
|
|
70
71
|
|
|
72
|
+
it('renders correctly in landscape mode', () => {
|
|
73
|
+
const onChange = jest.fn();
|
|
74
|
+
setOrientation('landscape');
|
|
75
|
+
const { getByText, queryByTestId } = renderWithTheme(
|
|
76
|
+
<DatePickerIOS
|
|
77
|
+
value={new Date('December 21, 1995')}
|
|
78
|
+
label="Start date"
|
|
79
|
+
confirmLabel="Confirm"
|
|
80
|
+
onChange={onChange}
|
|
81
|
+
supportedOrientations={['landscape']}
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
expect(getByText('Start date')).toBeDefined();
|
|
86
|
+
expect(queryByTestId('text-input').props.value).toBe('21/12/1995');
|
|
87
|
+
expect(queryByTestId('datePickerIOS')).toBeNull();
|
|
88
|
+
|
|
89
|
+
// Open date picker
|
|
90
|
+
fireEvent.press(getByText('Start date'));
|
|
91
|
+
expect(queryByTestId('datePickerIOS')).toBeTruthy();
|
|
92
|
+
|
|
93
|
+
// Change date
|
|
94
|
+
fireEvent(
|
|
95
|
+
queryByTestId('datePickerIOS'),
|
|
96
|
+
'onChange',
|
|
97
|
+
null,
|
|
98
|
+
new Date('December 17, 1995')
|
|
99
|
+
);
|
|
100
|
+
fireEvent.press(getByText('Confirm'));
|
|
101
|
+
|
|
102
|
+
expect(onChange).toBeCalledWith(new Date('December 17, 1995'));
|
|
103
|
+
});
|
|
104
|
+
|
|
71
105
|
it('renders correct help text', () => {
|
|
72
106
|
const { getByText } = renderWithTheme(
|
|
73
107
|
<DatePickerIOS
|
|
@@ -72,4 +72,8 @@ export interface DatePickerProps {
|
|
|
72
72
|
* Calendar variant prop. Label for the cancel button of the month picker, Android only.
|
|
73
73
|
*/
|
|
74
74
|
monthPickerCancelLabel?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Supported orientations for the DatePicker modal, iOS only.
|
|
77
|
+
*/
|
|
78
|
+
supportedOrientations?: ('portrait' | 'landscape')[];
|
|
75
79
|
}
|
|
@@ -1,39 +1,38 @@
|
|
|
1
1
|
import '@testing-library/jest-native/extend-expect';
|
|
2
2
|
import { fireEvent } from '@testing-library/react-native';
|
|
3
|
-
import React from 'react';
|
|
3
|
+
import React, { ComponentProps } from 'react';
|
|
4
4
|
import ActionGroup from '..';
|
|
5
5
|
import renderWithTheme from '../../../../testHelpers/renderWithTheme';
|
|
6
|
+
import { setOrientation } from '../../../../testHelpers/utils';
|
|
6
7
|
|
|
7
8
|
describe('ActionGroup', () => {
|
|
9
|
+
const items: ComponentProps<typeof ActionGroup>['items'] = [
|
|
10
|
+
{
|
|
11
|
+
icon: 'speaker',
|
|
12
|
+
title: 'Give shout out',
|
|
13
|
+
testID: 'speaker-action-item',
|
|
14
|
+
},
|
|
15
|
+
{ icon: 'target', title: 'Goal', testID: 'target-action-item' },
|
|
16
|
+
{
|
|
17
|
+
icon: 'plane',
|
|
18
|
+
title: 'Leave request',
|
|
19
|
+
testID: 'plane-action-item',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
icon: 'health-bag',
|
|
23
|
+
title: 'Safety incident',
|
|
24
|
+
testID: 'health-bag-action-item',
|
|
25
|
+
},
|
|
26
|
+
{ icon: 'clock', title: 'Timesheets', testID: 'clock-action-item' },
|
|
27
|
+
];
|
|
28
|
+
|
|
8
29
|
it.each`
|
|
9
30
|
active
|
|
10
31
|
${true}
|
|
11
32
|
${false}
|
|
12
33
|
`('has active $active', ({ active }) => {
|
|
13
34
|
const { toJSON, getByTestId, queryByTestId } = renderWithTheme(
|
|
14
|
-
<ActionGroup
|
|
15
|
-
fabTitle="Shout out"
|
|
16
|
-
active={active}
|
|
17
|
-
items={[
|
|
18
|
-
{
|
|
19
|
-
icon: 'speaker',
|
|
20
|
-
title: 'Give shout out',
|
|
21
|
-
testID: 'speaker-action-item',
|
|
22
|
-
},
|
|
23
|
-
{ icon: 'target', title: 'Goal', testID: 'target-action-item' },
|
|
24
|
-
{
|
|
25
|
-
icon: 'plane',
|
|
26
|
-
title: 'Leave request',
|
|
27
|
-
testID: 'plane-action-item',
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
icon: 'health-bag',
|
|
31
|
-
title: 'Safety incident',
|
|
32
|
-
testID: 'health-bag-action-item',
|
|
33
|
-
},
|
|
34
|
-
{ icon: 'clock', title: 'Timesheets', testID: 'clock-action-item' },
|
|
35
|
-
]}
|
|
36
|
-
/>
|
|
35
|
+
<ActionGroup fabTitle="Shout out" active={active} items={items} />
|
|
37
36
|
);
|
|
38
37
|
|
|
39
38
|
expect(toJSON()).toMatchSnapshot();
|
|
@@ -51,6 +50,28 @@ describe('ActionGroup', () => {
|
|
|
51
50
|
}
|
|
52
51
|
});
|
|
53
52
|
|
|
53
|
+
it.each`
|
|
54
|
+
orientation
|
|
55
|
+
${'portrait'}
|
|
56
|
+
${'landscape'}
|
|
57
|
+
`('renders correctly in $orientation mode', ({ orientation }) => {
|
|
58
|
+
setOrientation(orientation);
|
|
59
|
+
const { getByTestId, queryByTestId } = renderWithTheme(
|
|
60
|
+
<ActionGroup
|
|
61
|
+
active
|
|
62
|
+
fabTitle="Shout out"
|
|
63
|
+
items={items}
|
|
64
|
+
supportedOrientations={[orientation]}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(queryByTestId('back-drop')).toBeDefined();
|
|
69
|
+
expect(getByTestId('speaker-action-item')).toBeDefined();
|
|
70
|
+
expect(getByTestId('target-action-item')).toBeDefined();
|
|
71
|
+
expect(getByTestId('plane-action-item')).toBeDefined();
|
|
72
|
+
expect(getByTestId('health-bag-action-item')).toBeDefined();
|
|
73
|
+
});
|
|
74
|
+
|
|
54
75
|
describe('when user presses', () => {
|
|
55
76
|
it('calls onPress when active = false', () => {
|
|
56
77
|
const onPressSpy = jest.fn();
|
|
@@ -67,6 +67,10 @@ export interface ActionGroupProps {
|
|
|
67
67
|
* Testing id of the component.
|
|
68
68
|
*/
|
|
69
69
|
testID?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Supported orientations for the ActionGroup modal, iOS only.
|
|
72
|
+
*/
|
|
73
|
+
supportedOrientations?: ('portrait' | 'landscape')[];
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
const ActionGroup = forwardRef<ActionGroupHandles, ActionGroupProps>(
|
|
@@ -81,6 +85,7 @@ const ActionGroup = forwardRef<ActionGroupHandles, ActionGroupProps>(
|
|
|
81
85
|
fabTitle,
|
|
82
86
|
onBackdropPress,
|
|
83
87
|
fabIcon = 'add',
|
|
88
|
+
supportedOrientations = ['portrait'],
|
|
84
89
|
},
|
|
85
90
|
ref
|
|
86
91
|
) => {
|
|
@@ -143,6 +148,7 @@ const ActionGroup = forwardRef<ActionGroupHandles, ActionGroupProps>(
|
|
|
143
148
|
animationType="fade"
|
|
144
149
|
transparent
|
|
145
150
|
statusBarTranslucent
|
|
151
|
+
supportedOrientations={supportedOrientations}
|
|
146
152
|
>
|
|
147
153
|
<StyledContainerInModal testID={testID} style={[style]}>
|
|
148
154
|
<StyledBackdrop testID="back-drop" onPress={onBackdropPress} />
|
|
@@ -266,6 +266,11 @@ exports[`rendering allows custom renderer 1`] = `
|
|
|
266
266
|
<Modal
|
|
267
267
|
hardwareAccelerated={false}
|
|
268
268
|
onRequestClose={[Function]}
|
|
269
|
+
supportedOrientations={
|
|
270
|
+
[
|
|
271
|
+
"portrait",
|
|
272
|
+
]
|
|
273
|
+
}
|
|
269
274
|
transparent={true}
|
|
270
275
|
visible={true}
|
|
271
276
|
>
|
|
@@ -2084,6 +2089,11 @@ exports[`rendering renders correctly when bottom sheet is visible 1`] = `
|
|
|
2084
2089
|
<Modal
|
|
2085
2090
|
hardwareAccelerated={false}
|
|
2086
2091
|
onRequestClose={[Function]}
|
|
2092
|
+
supportedOrientations={
|
|
2093
|
+
[
|
|
2094
|
+
"portrait",
|
|
2095
|
+
]
|
|
2096
|
+
}
|
|
2087
2097
|
transparent={true}
|
|
2088
2098
|
visible={true}
|
|
2089
2099
|
>
|
|
@@ -4121,6 +4131,11 @@ exports[`rendering renders correctly when receives sections 1`] = `
|
|
|
4121
4131
|
<Modal
|
|
4122
4132
|
hardwareAccelerated={false}
|
|
4123
4133
|
onRequestClose={[Function]}
|
|
4134
|
+
supportedOrientations={
|
|
4135
|
+
[
|
|
4136
|
+
"portrait",
|
|
4137
|
+
]
|
|
4138
|
+
}
|
|
4124
4139
|
transparent={true}
|
|
4125
4140
|
visible={true}
|
|
4126
4141
|
>
|
|
@@ -5439,6 +5454,11 @@ exports[`rendering renders correctly when receives sections 2`] = `
|
|
|
5439
5454
|
<Modal
|
|
5440
5455
|
hardwareAccelerated={false}
|
|
5441
5456
|
onRequestClose={[Function]}
|
|
5457
|
+
supportedOrientations={
|
|
5458
|
+
[
|
|
5459
|
+
"portrait",
|
|
5460
|
+
]
|
|
5461
|
+
}
|
|
5442
5462
|
transparent={true}
|
|
5443
5463
|
visible={true}
|
|
5444
5464
|
>
|
|
@@ -9,6 +9,7 @@ import HeroDesignProvider from '../../../HeroDesignProvider';
|
|
|
9
9
|
import List from '../../../List';
|
|
10
10
|
import Typography from '../../../Typography';
|
|
11
11
|
import type { ListRenderOptionInfo } from '../../types';
|
|
12
|
+
import { setOrientation } from '../../../../testHelpers/utils';
|
|
12
13
|
|
|
13
14
|
const options = [
|
|
14
15
|
{ text: 'Monday', value: 'mon' },
|
|
@@ -113,6 +114,33 @@ describe('rendering', () => {
|
|
|
113
114
|
expect(getByText('Confirm')).toBeDefined();
|
|
114
115
|
});
|
|
115
116
|
|
|
117
|
+
it('renders correctly in landscape mode when bottom sheet is visible', () => {
|
|
118
|
+
setOrientation('landscape');
|
|
119
|
+
|
|
120
|
+
const { queryAllByText, getByText, getByTestId } = renderWithTheme(
|
|
121
|
+
<MultiSelect
|
|
122
|
+
label="Allow notifications"
|
|
123
|
+
footerLabel="Confirm"
|
|
124
|
+
options={options}
|
|
125
|
+
value={['mon', 'tue']}
|
|
126
|
+
onConfirm={jest.fn()}
|
|
127
|
+
supportedOrientations={['landscape']}
|
|
128
|
+
/>
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
fireEvent.press(getByTestId('text-input'));
|
|
132
|
+
|
|
133
|
+
expect(queryAllByText('Allow notifications')).toHaveLength(2);
|
|
134
|
+
expect(getByText('Monday')).toBeDefined();
|
|
135
|
+
expect(getByText('Tuesday')).toBeDefined();
|
|
136
|
+
expect(getByText('Wednesday')).toBeDefined();
|
|
137
|
+
expect(getByText('Thursday')).toBeDefined();
|
|
138
|
+
expect(getByText('Friday')).toBeDefined();
|
|
139
|
+
expect(getByText('Saturday')).toBeDefined();
|
|
140
|
+
expect(getByText('Sunday')).toBeDefined();
|
|
141
|
+
expect(getByText('Confirm')).toBeDefined();
|
|
142
|
+
});
|
|
143
|
+
|
|
116
144
|
it('renders correctly when input is loading', () => {
|
|
117
145
|
const { toJSON, getByTestId } = renderWithTheme(
|
|
118
146
|
<MultiSelect
|
|
@@ -47,6 +47,10 @@ export interface MultiSelectProps<V, T extends OptionType<V> = OptionType<V>>
|
|
|
47
47
|
selectedValue: V[],
|
|
48
48
|
inputProps: NativeTextInputProps
|
|
49
49
|
) => React.ReactNode;
|
|
50
|
+
/**
|
|
51
|
+
* Supported orientations for the MultiSelect modal, iOS only.
|
|
52
|
+
*/
|
|
53
|
+
supportedOrientations?: ('portrait' | 'landscape')[];
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
function MultiSelect<V, T extends OptionType<V>>({
|
|
@@ -69,6 +73,7 @@ function MultiSelect<V, T extends OptionType<V>>({
|
|
|
69
73
|
style,
|
|
70
74
|
testID,
|
|
71
75
|
value,
|
|
76
|
+
supportedOrientations = ['portrait'],
|
|
72
77
|
}: MultiSelectProps<V, T>) {
|
|
73
78
|
const { isKeyboardVisible, keyboardHeight } = useKeyboard();
|
|
74
79
|
const [open, setOpen] = useState(false);
|
|
@@ -154,6 +159,7 @@ function MultiSelect<V, T extends OptionType<V>>({
|
|
|
154
159
|
sectionListRef.current?.scrollToLocation(scrollParams);
|
|
155
160
|
}
|
|
156
161
|
}}
|
|
162
|
+
supportedOrientations={supportedOrientations}
|
|
157
163
|
>
|
|
158
164
|
{onQueryChange && (
|
|
159
165
|
<StyledSearchBar>
|
|
@@ -265,6 +265,11 @@ exports[`rendering allows custom renderer 1`] = `
|
|
|
265
265
|
<Modal
|
|
266
266
|
hardwareAccelerated={false}
|
|
267
267
|
onRequestClose={[Function]}
|
|
268
|
+
supportedOrientations={
|
|
269
|
+
[
|
|
270
|
+
"portrait",
|
|
271
|
+
]
|
|
272
|
+
}
|
|
268
273
|
transparent={true}
|
|
269
274
|
visible={true}
|
|
270
275
|
>
|
|
@@ -1999,6 +2004,11 @@ exports[`rendering renders correctly when bottom sheet is visible 1`] = `
|
|
|
1999
2004
|
<Modal
|
|
2000
2005
|
hardwareAccelerated={false}
|
|
2001
2006
|
onRequestClose={[Function]}
|
|
2007
|
+
supportedOrientations={
|
|
2008
|
+
[
|
|
2009
|
+
"portrait",
|
|
2010
|
+
]
|
|
2011
|
+
}
|
|
2002
2012
|
transparent={true}
|
|
2003
2013
|
visible={true}
|
|
2004
2014
|
>
|
|
@@ -3896,6 +3906,11 @@ exports[`rendering renders correctly when receives sections 1`] = `
|
|
|
3896
3906
|
<Modal
|
|
3897
3907
|
hardwareAccelerated={false}
|
|
3898
3908
|
onRequestClose={[Function]}
|
|
3909
|
+
supportedOrientations={
|
|
3910
|
+
[
|
|
3911
|
+
"portrait",
|
|
3912
|
+
]
|
|
3913
|
+
}
|
|
3899
3914
|
transparent={true}
|
|
3900
3915
|
visible={true}
|
|
3901
3916
|
>
|
|
@@ -5,6 +5,7 @@ import SingleSelect from '..';
|
|
|
5
5
|
import Typography from '../../../Typography';
|
|
6
6
|
import List from '../../../List';
|
|
7
7
|
import type { ListRenderOptionInfo } from '../../types';
|
|
8
|
+
import { setOrientation } from '../../../../testHelpers/utils';
|
|
8
9
|
|
|
9
10
|
const options = [
|
|
10
11
|
{ text: 'Monday', value: 'mon' },
|
|
@@ -105,6 +106,30 @@ describe('rendering', () => {
|
|
|
105
106
|
expect(getByText('Sunday')).toBeDefined();
|
|
106
107
|
});
|
|
107
108
|
|
|
109
|
+
it('renders correctly in landscape mode when bottom sheet is visible', () => {
|
|
110
|
+
setOrientation('landscape');
|
|
111
|
+
|
|
112
|
+
const { queryAllByText, getByText, getByTestId } = renderWithTheme(
|
|
113
|
+
<SingleSelect
|
|
114
|
+
label="Allow notifications"
|
|
115
|
+
options={options}
|
|
116
|
+
value="mon"
|
|
117
|
+
onConfirm={jest.fn()}
|
|
118
|
+
supportedOrientations={['landscape']}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
fireEvent.press(getByTestId('text-input'));
|
|
122
|
+
|
|
123
|
+
expect(queryAllByText('Allow notifications')).toHaveLength(2);
|
|
124
|
+
expect(getByText('Monday')).toBeDefined();
|
|
125
|
+
expect(getByText('Tuesday')).toBeDefined();
|
|
126
|
+
expect(getByText('Wednesday')).toBeDefined();
|
|
127
|
+
expect(getByText('Thursday')).toBeDefined();
|
|
128
|
+
expect(getByText('Friday')).toBeDefined();
|
|
129
|
+
expect(getByText('Saturday')).toBeDefined();
|
|
130
|
+
expect(getByText('Sunday')).toBeDefined();
|
|
131
|
+
});
|
|
132
|
+
|
|
108
133
|
it('renders correctly when input is loading', () => {
|
|
109
134
|
const { toJSON, getByTestId } = renderWithTheme(
|
|
110
135
|
<SingleSelect
|
|
@@ -33,6 +33,10 @@ export interface SingleSelectProps<V, T extends OptionType<V> = OptionType<V>>
|
|
|
33
33
|
selectedValue: V | null,
|
|
34
34
|
inputProps: NativeTextInputProps
|
|
35
35
|
) => React.ReactNode;
|
|
36
|
+
/**
|
|
37
|
+
* Supported orientations for the Select modal, iOS only.
|
|
38
|
+
*/
|
|
39
|
+
supportedOrientations?: ('portrait' | 'landscape')[];
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
const SingleSelect = <V, T extends OptionType<V>>({
|
|
@@ -54,6 +58,7 @@ const SingleSelect = <V, T extends OptionType<V>>({
|
|
|
54
58
|
style,
|
|
55
59
|
testID,
|
|
56
60
|
value,
|
|
61
|
+
supportedOrientations = ['portrait'],
|
|
57
62
|
}: SingleSelectProps<V, T>) => {
|
|
58
63
|
const { isKeyboardVisible, keyboardHeight } = useKeyboard();
|
|
59
64
|
const [open, setOpen] = useState(false);
|
|
@@ -113,6 +118,7 @@ const SingleSelect = <V, T extends OptionType<V>>({
|
|
|
113
118
|
sectionListRef.current?.scrollToLocation(scrollParams);
|
|
114
119
|
}
|
|
115
120
|
}}
|
|
121
|
+
supportedOrientations={supportedOrientations}
|
|
116
122
|
>
|
|
117
123
|
{onQueryChange && (
|
|
118
124
|
<StyledSearchBar>
|
|
@@ -24,6 +24,7 @@ const TimePickerIOS = ({
|
|
|
24
24
|
style,
|
|
25
25
|
testID,
|
|
26
26
|
showSuffix = true,
|
|
27
|
+
supportedOrientations = ['portrait'],
|
|
27
28
|
}: TimePickerProps) => {
|
|
28
29
|
const [selectingDate, setSelectingDate] = useState<Date>(value || new Date());
|
|
29
30
|
const [open, setOpen] = useState(false);
|
|
@@ -64,6 +65,7 @@ const TimePickerIOS = ({
|
|
|
64
65
|
}}
|
|
65
66
|
/>
|
|
66
67
|
}
|
|
68
|
+
supportedOrientations={supportedOrientations}
|
|
67
69
|
>
|
|
68
70
|
<StyledPickerWrapper>
|
|
69
71
|
<DateTimePicker
|