@hero-design/rn 8.55.1 → 8.56.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/CHANGELOG.md +12 -0
- package/es/index.js +5205 -4772
- package/lib/index.js +5211 -4775
- package/package.json +1 -1
- package/src/components/AnimatedScroller/AnimatedFAB.tsx +105 -0
- package/src/components/AnimatedScroller/AnimatedScrollable.tsx +55 -0
- package/src/components/AnimatedScroller/FlatListWithFAB.tsx +23 -0
- package/src/components/AnimatedScroller/ScrollViewWithFAB.tsx +21 -0
- package/src/components/AnimatedScroller/SectionListWithFAB.tsx +26 -0
- package/src/components/AnimatedScroller/__tests__/ScrollablesWithFAB.spec.tsx +172 -0
- package/src/components/AnimatedScroller/__tests__/__snapshots__/ScrollablesWithFAB.spec.tsx.snap +3435 -0
- package/src/components/AnimatedScroller/index.tsx +5 -0
- package/src/components/FAB/FAB.tsx +6 -6
- package/src/index.ts +8 -0
- package/types/components/Accordion/StyledAccordion.d.ts +5 -5
- package/types/components/Alert/StyledAlert.d.ts +5 -5
- package/types/components/AnimatedScroller/AnimatedFAB.d.ts +10 -0
- package/types/components/AnimatedScroller/AnimatedScrollable.d.ts +16 -0
- package/types/components/AnimatedScroller/FlatListWithFAB.d.ts +12 -0
- package/types/components/AnimatedScroller/ScrollViewWithFAB.d.ts +12 -0
- package/types/components/AnimatedScroller/SectionListWithFAB.d.ts +12 -0
- package/types/components/AnimatedScroller/index.d.ts +4 -0
- package/types/components/Attachment/StyledAttachment.d.ts +4 -4
- package/types/components/Avatar/AvatarStack/StyledAvatarStack.d.ts +3 -3
- package/types/components/Avatar/StyledAvatar.d.ts +4 -4
- package/types/components/Badge/StyledBadge.d.ts +3 -3
- package/types/components/BottomNavigation/StyledBottomNavigation.d.ts +7 -7
- package/types/components/BottomSheet/StyledBottomSheet.d.ts +8 -8
- package/types/components/Box/StyledBox.d.ts +1 -1
- package/types/components/Button/LoadingIndicator/StyledLoadingIndicator.d.ts +2 -2
- package/types/components/Button/StyledButton.d.ts +5 -5
- package/types/components/Button/UtilityButton/StyledUtilityButton.d.ts +3 -3
- package/types/components/Calendar/StyledCalendar.d.ts +9 -9
- package/types/components/Card/DataCard/StyledDataCard.d.ts +2 -2
- package/types/components/Card/StyledCard.d.ts +1 -1
- package/types/components/Carousel/StyledCardCarousel.d.ts +4 -4
- package/types/components/Carousel/StyledCarousel.d.ts +9 -9
- package/types/components/Checkbox/StyledCheckbox.d.ts +5 -5
- package/types/components/Chip/StyledChip.d.ts +4 -4
- package/types/components/Collapse/StyledCollapse.d.ts +3 -3
- package/types/components/ContentNavigator/StyledContentNavigator.d.ts +1 -1
- package/types/components/DatePicker/StyledDatePicker.d.ts +1 -1
- package/types/components/Divider/StyledDivider.d.ts +1 -1
- package/types/components/Drawer/StyledDrawer.d.ts +7 -7
- package/types/components/Empty/StyledEmpty.d.ts +3 -3
- package/types/components/Error/StyledError.d.ts +10 -10
- package/types/components/FAB/ActionGroup/StyledActionGroup.d.ts +5 -5
- package/types/components/FAB/ActionGroup/StyledActionItem.d.ts +3 -3
- package/types/components/FAB/StyledFAB.d.ts +4 -4
- package/types/components/Icon/HeroIcon/index.d.ts +1 -1
- package/types/components/List/StyledBasicListItem.d.ts +4 -4
- package/types/components/List/StyledListItem.d.ts +7 -7
- package/types/components/PageControl/StyledPageControl.d.ts +2 -2
- package/types/components/PinInput/StyledPinInput.d.ts +10 -10
- package/types/components/Progress/StyledProgressBar.d.ts +2 -2
- package/types/components/Progress/StyledProgressCircle.d.ts +6 -6
- package/types/components/Radio/StyledRadio.d.ts +3 -3
- package/types/components/Rate/StyledRate.d.ts +2 -2
- package/types/components/RichTextEditor/StyledRichTextEditor.d.ts +2 -2
- package/types/components/RichTextEditor/StyledToolbar.d.ts +3 -3
- package/types/components/SectionHeading/StyledHeading.d.ts +3 -3
- package/types/components/Select/StyledSelect.d.ts +3 -3
- package/types/components/Skeleton/StyledSkeleton.d.ts +2 -2
- package/types/components/Spinner/StyledSpinner.d.ts +4 -4
- package/types/components/Success/StyledSuccess.d.ts +9 -9
- package/types/components/Swipeable/StyledSwipeable.d.ts +1 -1
- package/types/components/Switch/SelectorSwitch/StyledSelectorSwitch.d.ts +4 -4
- package/types/components/Switch/StyledSwitch.d.ts +2 -2
- package/types/components/Tabs/StyledScrollableTabs.d.ts +8 -8
- package/types/components/Tabs/StyledTabs.d.ts +8 -8
- package/types/components/Tag/StyledTag.d.ts +2 -2
- package/types/components/TextInput/StyledTextInput.d.ts +13 -13
- package/types/components/TimePicker/StyledTimePicker.d.ts +1 -1
- package/types/components/Toast/StyledToast.d.ts +6 -6
- package/types/components/Toolbar/StyledToolbar.d.ts +5 -5
- package/types/components/Typography/Body/StyledBody.d.ts +1 -1
- package/types/components/Typography/Caption/StyledCaption.d.ts +1 -1
- package/types/components/Typography/Label/StyledLabel.d.ts +1 -1
- package/types/components/Typography/Text/StyledText.d.ts +1 -1
- package/types/components/Typography/Title/StyledTitle.d.ts +1 -1
- package/types/index.d.ts +2 -1
package/package.json
CHANGED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Animated } from 'react-native';
|
|
3
|
+
import FAB from '../FAB';
|
|
4
|
+
import ActionGroup, {
|
|
5
|
+
ActionGroupHandles,
|
|
6
|
+
ActionGroupProps,
|
|
7
|
+
} from '../FAB/ActionGroup';
|
|
8
|
+
import { FABHandles, FABProps } from '../FAB/FAB';
|
|
9
|
+
|
|
10
|
+
const COLLAPSE_BREAKPOINT = 10;
|
|
11
|
+
const SHOW_AND_HIDE_BREAKPOINT = 200;
|
|
12
|
+
const REF_ACTIONS_BY_COMPONENT = {
|
|
13
|
+
FAB: {
|
|
14
|
+
show: 'show',
|
|
15
|
+
hide: 'hide',
|
|
16
|
+
collapse: 'collapse',
|
|
17
|
+
},
|
|
18
|
+
ActionGroup: {
|
|
19
|
+
show: 'showFAB',
|
|
20
|
+
hide: 'hideFAB',
|
|
21
|
+
collapse: 'collapseFAB',
|
|
22
|
+
},
|
|
23
|
+
} as const;
|
|
24
|
+
|
|
25
|
+
interface AnimatedFABProps {
|
|
26
|
+
fabProps: FABProps | ActionGroupProps;
|
|
27
|
+
contentOffsetY: Animated.Value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const AnimatedFAB = ({ fabProps, contentOffsetY }: AnimatedFABProps) => {
|
|
31
|
+
const component = 'items' in fabProps ? 'ActionGroup' : 'FAB';
|
|
32
|
+
const [currentScrollDirection, setCurrentScrollDirection] = React.useState<
|
|
33
|
+
'up' | 'down'
|
|
34
|
+
>('down');
|
|
35
|
+
const [lastScrollY, setLastScrollY] = React.useState(0);
|
|
36
|
+
const [fabState, setFabState] = React.useState<'show' | 'hide' | 'collapse'>(
|
|
37
|
+
'show'
|
|
38
|
+
);
|
|
39
|
+
const [remainingScrollOffset, setRemainingScrollOffset] = React.useState(
|
|
40
|
+
SHOW_AND_HIDE_BREAKPOINT
|
|
41
|
+
);
|
|
42
|
+
const ref = React.useRef<FABHandles & ActionGroupHandles>(null);
|
|
43
|
+
|
|
44
|
+
const animateFab = React.useCallback(
|
|
45
|
+
(newState: 'show' | 'hide' | 'collapse') => {
|
|
46
|
+
if (fabState !== newState) {
|
|
47
|
+
if (newState === 'show') {
|
|
48
|
+
ref.current?.[REF_ACTIONS_BY_COMPONENT[component].show]();
|
|
49
|
+
} else if (newState === 'hide') {
|
|
50
|
+
ref.current?.[REF_ACTIONS_BY_COMPONENT[component].hide]();
|
|
51
|
+
} else {
|
|
52
|
+
ref.current?.[REF_ACTIONS_BY_COMPONENT[component].collapse]();
|
|
53
|
+
}
|
|
54
|
+
setFabState(newState);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
[fabState, component]
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
// Listen to ScrollView's contentOffsetY value
|
|
61
|
+
contentOffsetY.addListener(({ value }) => {
|
|
62
|
+
if (value < 0) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const newScrollDirection = value > lastScrollY ? 'down' : 'up';
|
|
67
|
+
const isScrollingDown = newScrollDirection === 'down';
|
|
68
|
+
|
|
69
|
+
if (newScrollDirection !== currentScrollDirection || lastScrollY === 0) {
|
|
70
|
+
setLastScrollY(value);
|
|
71
|
+
setCurrentScrollDirection(newScrollDirection);
|
|
72
|
+
}
|
|
73
|
+
const offsetFromLastDirection = Math.abs(value - lastScrollY);
|
|
74
|
+
const offsetDiff = Math.round(
|
|
75
|
+
Math.max(remainingScrollOffset - offsetFromLastDirection, 0)
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
if (remainingScrollOffset > 0) {
|
|
79
|
+
if (offsetDiff === SHOW_AND_HIDE_BREAKPOINT) {
|
|
80
|
+
animateFab(isScrollingDown ? 'show' : 'hide');
|
|
81
|
+
} else if (
|
|
82
|
+
offsetDiff <= SHOW_AND_HIDE_BREAKPOINT &&
|
|
83
|
+
offsetDiff > COLLAPSE_BREAKPOINT
|
|
84
|
+
) {
|
|
85
|
+
animateFab('collapse');
|
|
86
|
+
} else if (offsetDiff <= COLLAPSE_BREAKPOINT) {
|
|
87
|
+
animateFab(isScrollingDown ? 'hide' : 'show');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
setRemainingScrollOffset(offsetDiff);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
React.useEffect(() => {
|
|
95
|
+
setRemainingScrollOffset(SHOW_AND_HIDE_BREAKPOINT);
|
|
96
|
+
}, [currentScrollDirection]);
|
|
97
|
+
|
|
98
|
+
return component === 'FAB' ? (
|
|
99
|
+
<FAB ref={ref} {...(fabProps as FABProps)} />
|
|
100
|
+
) : (
|
|
101
|
+
<ActionGroup ref={ref} {...(fabProps as ActionGroupHandles)} />
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export default AnimatedFAB;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Animated,
|
|
4
|
+
FlatListProps,
|
|
5
|
+
ScrollViewProps as RnScrollViewProps,
|
|
6
|
+
SectionListProps,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
import { FABProps } from '../FAB/FAB';
|
|
9
|
+
import AnimatedFAB from './AnimatedFAB';
|
|
10
|
+
import { ActionGroupProps } from '../FAB/ActionGroup';
|
|
11
|
+
|
|
12
|
+
export interface AnimatedScrollerProps<T> {
|
|
13
|
+
/**
|
|
14
|
+
* Scroll component, it can be ScrollView, FlatList or SectionList.
|
|
15
|
+
*/
|
|
16
|
+
ScrollComponent: React.ReactElement<
|
|
17
|
+
RnScrollViewProps | FlatListProps<T> | SectionListProps<T>
|
|
18
|
+
>;
|
|
19
|
+
/**
|
|
20
|
+
* FAB or FAB.ActionGroup props.
|
|
21
|
+
*/
|
|
22
|
+
fabProps: FABProps | ActionGroupProps;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function AnimatedScroller<T>({
|
|
26
|
+
ScrollComponent,
|
|
27
|
+
fabProps,
|
|
28
|
+
}: AnimatedScrollerProps<T>) {
|
|
29
|
+
const contentOffsetY = React.useRef(new Animated.Value(0)).current;
|
|
30
|
+
|
|
31
|
+
// Common props for all ScrollView, FlatList and SectionList.
|
|
32
|
+
const { onScroll, scrollEventThrottle } = ScrollComponent.props;
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
{React.cloneElement(ScrollComponent, {
|
|
37
|
+
...ScrollComponent.props,
|
|
38
|
+
scrollEventThrottle: scrollEventThrottle || 100,
|
|
39
|
+
onScroll: Animated.event(
|
|
40
|
+
[{ nativeEvent: { contentOffset: { y: contentOffsetY } } }],
|
|
41
|
+
{
|
|
42
|
+
useNativeDriver: false,
|
|
43
|
+
listener: onScroll,
|
|
44
|
+
}
|
|
45
|
+
),
|
|
46
|
+
})}
|
|
47
|
+
|
|
48
|
+
{!!fabProps && (
|
|
49
|
+
<AnimatedFAB fabProps={fabProps} contentOffsetY={contentOffsetY} />
|
|
50
|
+
)}
|
|
51
|
+
</>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default AnimatedScroller;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FlatList, FlatListProps } from 'react-native';
|
|
3
|
+
import { FABProps } from '../FAB/FAB';
|
|
4
|
+
import AnimatedScroller from './AnimatedScrollable';
|
|
5
|
+
import { ActionGroupProps } from '../FAB/ActionGroup';
|
|
6
|
+
|
|
7
|
+
export interface FlatListWithFABProps<T> extends FlatListProps<T> {
|
|
8
|
+
/**
|
|
9
|
+
* FAB or FAB.ActionGroup props props.
|
|
10
|
+
*/
|
|
11
|
+
fabProps: FABProps | ActionGroupProps;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function FlatListWithFAB<T>({ fabProps, ...props }: FlatListWithFABProps<T>) {
|
|
15
|
+
return (
|
|
16
|
+
<AnimatedScroller
|
|
17
|
+
ScrollComponent={<FlatList {...props} />}
|
|
18
|
+
fabProps={fabProps}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default FlatListWithFAB;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ScrollView, ScrollViewProps } from 'react-native';
|
|
3
|
+
import AnimatedScroller from './AnimatedScrollable';
|
|
4
|
+
import { ActionGroupProps } from '../FAB/ActionGroup';
|
|
5
|
+
import { FABProps } from '../FAB/FAB';
|
|
6
|
+
|
|
7
|
+
export interface ScrollViewWithFABProps extends ScrollViewProps {
|
|
8
|
+
/**
|
|
9
|
+
* FAB or FAB.ActionGroup props props.
|
|
10
|
+
*/
|
|
11
|
+
fabProps: FABProps | ActionGroupProps;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const ScrollViewWithFAB = ({ fabProps, ...props }: ScrollViewWithFABProps) => (
|
|
15
|
+
<AnimatedScroller
|
|
16
|
+
ScrollComponent={<ScrollView {...props} />}
|
|
17
|
+
fabProps={fabProps}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export default ScrollViewWithFAB;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SectionList, SectionListProps } from 'react-native';
|
|
3
|
+
import AnimatedScroller from './AnimatedScrollable';
|
|
4
|
+
import { ActionGroupProps } from '../FAB/ActionGroup';
|
|
5
|
+
import { FABProps } from '../FAB/FAB';
|
|
6
|
+
|
|
7
|
+
export interface SectionListWithFABProps<T> extends SectionListProps<T> {
|
|
8
|
+
/**
|
|
9
|
+
* FAB or FAB.ActionGroup props props.
|
|
10
|
+
*/
|
|
11
|
+
fabProps: FABProps | ActionGroupProps;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function SectionListWithFAB<T>({
|
|
15
|
+
fabProps,
|
|
16
|
+
...props
|
|
17
|
+
}: SectionListWithFABProps<T>) {
|
|
18
|
+
return (
|
|
19
|
+
<AnimatedScroller
|
|
20
|
+
ScrollComponent={<SectionList {...props} />}
|
|
21
|
+
fabProps={fabProps}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default SectionListWithFAB;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTheme } from '@emotion/react';
|
|
3
|
+
import { fireEvent } from '@testing-library/react-native';
|
|
4
|
+
import renderWithTheme from '../../../testHelpers/renderWithTheme';
|
|
5
|
+
import { FlatListWithFAB, ScrollViewWithFAB, SectionListWithFAB } from '..';
|
|
6
|
+
import Box from '../../Box';
|
|
7
|
+
import { ActionGroupProps } from '../../FAB/ActionGroup';
|
|
8
|
+
import { FABProps } from '../../FAB/FAB';
|
|
9
|
+
import Typography from '../../Typography';
|
|
10
|
+
import { ScrollViewWithFABProps } from '../ScrollViewWithFAB';
|
|
11
|
+
import { FlatListWithFABProps } from '../FlatListWithFAB';
|
|
12
|
+
import SectionHeading from '../../SectionHeading';
|
|
13
|
+
|
|
14
|
+
const ExampleScrollViewWithFAB = ({ fabProps }: ScrollViewWithFABProps) => (
|
|
15
|
+
<ScrollViewWithFAB fabProps={fabProps} testID="scrollable-with-fab">
|
|
16
|
+
<Box style={{ height: 2000 }} justifyContent="space-between">
|
|
17
|
+
<Typography.Body>Content 1</Typography.Body>
|
|
18
|
+
<Typography.Body>Content 2</Typography.Body>
|
|
19
|
+
<Typography.Body>Content 3</Typography.Body>
|
|
20
|
+
</Box>
|
|
21
|
+
</ScrollViewWithFAB>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
function ExampleFlatListWithFAB<T>({ fabProps }: FlatListWithFABProps<T>) {
|
|
25
|
+
return (
|
|
26
|
+
<FlatListWithFAB
|
|
27
|
+
testID="scrollable-with-fab"
|
|
28
|
+
fabProps={fabProps}
|
|
29
|
+
data={Array.from({ length: 30 }, (_, i) => ({
|
|
30
|
+
id: i,
|
|
31
|
+
title: `Content ${i}`,
|
|
32
|
+
}))}
|
|
33
|
+
renderItem={({ item }) => (
|
|
34
|
+
<Box marginBottom="xxxxlarge">
|
|
35
|
+
<Typography.Title level="h5">{item.title}</Typography.Title>
|
|
36
|
+
<Typography.Body>Item {item.id}</Typography.Body>
|
|
37
|
+
</Box>
|
|
38
|
+
)}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function ExampleSectionListWithFAB<T>({ fabProps }: FlatListWithFABProps<T>) {
|
|
44
|
+
const theme = useTheme();
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<SectionListWithFAB
|
|
48
|
+
testID="scrollable-with-fab"
|
|
49
|
+
fabProps={fabProps}
|
|
50
|
+
sections={[
|
|
51
|
+
{
|
|
52
|
+
title: 'Title 1',
|
|
53
|
+
data: ['Content 1', 'Content 2', 'Content 3', 'Content 4'],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
title: 'Title 2',
|
|
57
|
+
data: ['Content 5', 'Content 6', 'Content 7'],
|
|
58
|
+
},
|
|
59
|
+
]}
|
|
60
|
+
renderSectionHeader={({ section: { title } }) => (
|
|
61
|
+
<SectionHeading text={title} />
|
|
62
|
+
)}
|
|
63
|
+
renderItem={({ item }) => (
|
|
64
|
+
<Typography.Title style={{ marginBottom: theme.space.xxxxlarge }}>
|
|
65
|
+
{item}
|
|
66
|
+
</Typography.Title>
|
|
67
|
+
)}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const defaultFabProps: FABProps = {
|
|
73
|
+
icon: 'speaker',
|
|
74
|
+
title: 'Shout out',
|
|
75
|
+
animated: true,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const defaultActionGroupProps: ActionGroupProps = {
|
|
79
|
+
fabTitle: 'Shout out',
|
|
80
|
+
items: [
|
|
81
|
+
{ icon: 'speaker', title: 'Announcements' },
|
|
82
|
+
{ icon: 'target', title: 'Goal' },
|
|
83
|
+
],
|
|
84
|
+
active: false,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
describe('Scrollables With FAB', () => {
|
|
88
|
+
it.each`
|
|
89
|
+
fabComponent | ScrollComponent
|
|
90
|
+
${'FAB'} | ${ExampleScrollViewWithFAB}
|
|
91
|
+
${'ActionGroup'} | ${ExampleScrollViewWithFAB}
|
|
92
|
+
${'FAB'} | ${ExampleFlatListWithFAB}
|
|
93
|
+
${'ActionGroup'} | ${ExampleFlatListWithFAB}
|
|
94
|
+
${'FAB'} | ${ExampleSectionListWithFAB}
|
|
95
|
+
${'ActionGroup'} | ${ExampleSectionListWithFAB}
|
|
96
|
+
`(
|
|
97
|
+
'$ScrollComponent renders $fabComponent correctly',
|
|
98
|
+
({ fabComponent, ScrollComponent }) => {
|
|
99
|
+
const fabProps =
|
|
100
|
+
fabComponent === 'FAB' ? defaultFabProps : defaultActionGroupProps;
|
|
101
|
+
|
|
102
|
+
const { getByText, toJSON } = renderWithTheme(
|
|
103
|
+
<ScrollComponent fabProps={fabProps} />
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
expect(toJSON()).toMatchSnapshot();
|
|
107
|
+
expect(getByText('Content 1')).toBeDefined();
|
|
108
|
+
expect(getByText('Content 2')).toBeDefined();
|
|
109
|
+
expect(getByText('Content 3')).toBeDefined();
|
|
110
|
+
expect(getByText('Shout out')).toBeDefined();
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
it.each`
|
|
115
|
+
fabComponent | ScrollComponent
|
|
116
|
+
${'FAB'} | ${ExampleScrollViewWithFAB}
|
|
117
|
+
${'ActionGroup'} | ${ExampleScrollViewWithFAB}
|
|
118
|
+
${'FAB'} | ${ExampleFlatListWithFAB}
|
|
119
|
+
${'ActionGroup'} | ${ExampleFlatListWithFAB}
|
|
120
|
+
${'FAB'} | ${ExampleSectionListWithFAB}
|
|
121
|
+
${'ActionGroup'} | ${ExampleSectionListWithFAB}
|
|
122
|
+
`(
|
|
123
|
+
'$ScrollComponent animates $fabComponent correctly',
|
|
124
|
+
({ fabComponent, ScrollComponent }) => {
|
|
125
|
+
const fabProps =
|
|
126
|
+
fabComponent === 'FAB' ? defaultFabProps : defaultActionGroupProps;
|
|
127
|
+
|
|
128
|
+
const { getByText, queryByText, getByTestId, queryByTestId } =
|
|
129
|
+
renderWithTheme(<ScrollComponent fabProps={fabProps} />);
|
|
130
|
+
|
|
131
|
+
// Scrolling down
|
|
132
|
+
expect(getByText('Shout out')).toBeDefined();
|
|
133
|
+
|
|
134
|
+
fireEvent.scroll(getByTestId('scrollable-with-fab'), {
|
|
135
|
+
nativeEvent: {
|
|
136
|
+
contentSize: { height: 1000 },
|
|
137
|
+
contentOffset: { y: 10 },
|
|
138
|
+
layoutMeasurement: { height: 2000, width: 400 },
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Collapsed
|
|
143
|
+
expect(queryByText('Shout out')).toBeNull();
|
|
144
|
+
expect(getByTestId('animated-fab-icon')).toBeDefined();
|
|
145
|
+
|
|
146
|
+
fireEvent.scroll(getByTestId('scrollable-with-fab'), {
|
|
147
|
+
nativeEvent: {
|
|
148
|
+
contentSize: { height: 1000 },
|
|
149
|
+
contentOffset: { y: 400 },
|
|
150
|
+
layoutMeasurement: { height: 2000, width: 400 },
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Hidden
|
|
155
|
+
expect(queryByText('Shout out')).toBeNull();
|
|
156
|
+
expect(queryByTestId('styled-fab-icon')).toBeNull();
|
|
157
|
+
|
|
158
|
+
// Scrolling up
|
|
159
|
+
fireEvent.scroll(getByTestId('scrollable-with-fab'), {
|
|
160
|
+
nativeEvent: {
|
|
161
|
+
contentSize: { height: 1000 },
|
|
162
|
+
contentOffset: { y: -10 },
|
|
163
|
+
layoutMeasurement: { height: 2000, width: 400 },
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Collapsed
|
|
168
|
+
expect(queryByText('Shout out')).toBeNull();
|
|
169
|
+
expect(getByTestId('animated-fab-icon')).toBeDefined();
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
});
|