Skip to content

Commit

Permalink
refactor: updated footer api
Browse files Browse the repository at this point in the history
  • Loading branch information
gorhom committed Aug 11, 2021
1 parent 18a32e5 commit 2cf7289
Show file tree
Hide file tree
Showing 17 changed files with 329 additions and 181 deletions.
12 changes: 10 additions & 2 deletions example/src/components/contactList/ContactList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useMemo, useCallback } from 'react';
import React, { useMemo, useCallback, ComponentProps } from 'react';
import { StyleSheet, Text, Platform, View, ViewStyle } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useFocusEffect } from '@react-navigation/native';
Expand All @@ -15,7 +15,11 @@ import {
} from '../../utilities';
import ContactItem from '../contactItem';

export interface ContactListProps {
export interface ContactListProps
extends Pick<
ComponentProps<typeof BottomSheetFlatList>,
'enableFooterMarginAdjustment'
> {
type: 'FlatList' | 'SectionList' | 'ScrollView' | 'View' | 'VirtualizedList';
count?: number;
style?: ViewStyle;
Expand Down Expand Up @@ -99,6 +103,7 @@ const ContactList = ({
if (type === 'FlatList') {
return (
<BottomSheetFlatList
{...rest}
data={data}
refreshing={false}
onRefresh={onRefresh}
Expand All @@ -117,6 +122,7 @@ const ContactList = ({
} else if (type === 'VirtualizedList') {
return (
<BottomSheetVirtualizedList
{...rest}
data={data}
keyExtractor={keyExtractor}
initialNumToRender={5}
Expand All @@ -135,6 +141,7 @@ const ContactList = ({
} else if (type === 'ScrollView') {
return (
<BottomSheetScrollView
{...rest}
style={styles.container}
contentContainerStyle={contentContainerStyle}
bounces={true}
Expand All @@ -146,6 +153,7 @@ const ContactList = ({
} else if (type === 'SectionList') {
return (
<BottomSheetSectionList
{...rest}
style={styles.container}
contentContainerStyle={contentContainerStyle}
stickySectionHeadersEnabled
Expand Down
109 changes: 109 additions & 0 deletions example/src/components/customFooter/CustomFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React, { useCallback, useMemo } from 'react';
import { StyleSheet } from 'react-native';
import {
BottomSheetFooter,
BottomSheetFooterProps,
useBottomSheet,
} from '@gorhom/bottom-sheet';
import { RectButton } from 'react-native-gesture-handler';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Animated, {
Extrapolate,
interpolate,
useAnimatedStyle,
} from 'react-native-reanimated';
import { toRad } from 'react-native-redash';

const AnimatedRectButton = Animated.createAnimatedComponent(RectButton);

interface CustomFooterProps extends BottomSheetFooterProps {}

const CustomFooter = ({ animatedFooterPosition }: CustomFooterProps) => {
//#region hooks
const { bottom: bottomSafeArea } = useSafeAreaInsets();
const { expand, collapse, animatedIndex } = useBottomSheet();
//#endregion

//#region styles
const arrowAnimatedStyle = useAnimatedStyle(() => {
const arrowRotate = interpolate(
animatedIndex.value,
[0, 1],
[toRad(0), toRad(-180)],
Extrapolate.CLAMP
);
return {
transform: [{ rotate: `${arrowRotate}rad` }],
};
}, []);
const arrowStyle = useMemo(
() => [arrowAnimatedStyle, styles.arrow],
[arrowAnimatedStyle]
);
const containerAnimatedStyle = useAnimatedStyle(
() => ({
opacity: interpolate(
animatedIndex.value,
[-0.85, 0],
[0, 1],
Extrapolate.CLAMP
),
}),
[animatedIndex]
);
const containerStyle = useMemo(
() => [containerAnimatedStyle, styles.container],
[containerAnimatedStyle]
);
//#endregion

const handleArrowPress = useCallback(() => {
if (animatedIndex.value === 0) {
expand();
} else {
collapse();
}
}, [expand, collapse, animatedIndex]);

return (
<BottomSheetFooter
bottomInset={bottomSafeArea}
animatedFooterPosition={animatedFooterPosition}
>
<AnimatedRectButton style={containerStyle} onPress={handleArrowPress}>
<Animated.Text style={arrowStyle}></Animated.Text>
</AnimatedRectButton>
</BottomSheetFooter>
);
};

const styles = StyleSheet.create({
container: {
alignSelf: 'flex-end',
justifyContent: 'center',
alignItems: 'center',
marginHorizontal: 24,
marginBottom: 12,
width: 50,
height: 50,
borderRadius: 25,
backgroundColor: '#80f',
shadowOffset: {
width: 0,
height: 12,
},
shadowOpacity: 0.25,
shadowRadius: 8.0,

elevation: 8,
},
arrow: {
fontSize: 20,
height: 20,
textAlignVertical: 'center',
fontWeight: '900',
color: '#fff',
},
});

export default CustomFooter;
1 change: 1 addition & 0 deletions example/src/components/customFooter/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './CustomFooter';
78 changes: 27 additions & 51 deletions example/src/screens/advanced/FooterExample.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,19 @@
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import BottomSheet, { BottomSheetFooter } from '@gorhom/bottom-sheet';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import SearchHandle from '../../components/searchHandle';
import React, { useCallback, useMemo, useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import BottomSheet from '@gorhom/bottom-sheet';
import Button from '../../components/button';
import ContactList from '../../components/contactList';
import customFooter from '../../components/customFooter';
import searchHandle from '../../components/searchHandle';

const FooterExample = () => {
// state
const [fadeBehavior, setFadeBehavior] = useState<'none' | 'fade'>('none');
const [slideBehavior, setSlideBehavior] = useState<'none' | 'slide'>('none');
const [scaleBehavior, setScaleBehavior] = useState<'none' | 'scale'>('none');

// hooks
const bottomSheetRef = useRef<BottomSheet>(null);
const { bottom: bottomSafeArea } = useSafeAreaInsets();

// variables
const snapPoints = useMemo(() => [80, 250], []);
const appearanceBehavior = useMemo(
() => [fadeBehavior, slideBehavior, scaleBehavior],
[fadeBehavior, slideBehavior, scaleBehavior]
);
const snapPoints = useMemo(() => ['25%', '50%'], []);

// callbacks
const handleFadeBehavior = useCallback(() => {
setFadeBehavior(state => (state === 'none' ? 'fade' : 'none'));
}, []);
const handleScaleBehavior = useCallback(() => {
setScaleBehavior(state => (state === 'none' ? 'scale' : 'none'));
}, []);
const handleSlideBehavior = useCallback(() => {
setSlideBehavior(state => (state === 'none' ? 'slide' : 'none'));
}, []);
const handleExpandPress = useCallback(() => {
bottomSheetRef.current?.expand();
}, []);
Expand All @@ -46,18 +27,6 @@ const FooterExample = () => {
// renders
return (
<View style={styles.container}>
<Button
label={`Toggle Fade Behavior: ${fadeBehavior}`}
onPress={handleFadeBehavior}
/>
<Button
label={`Toggle Scale Behavior: ${scaleBehavior}`}
onPress={handleScaleBehavior}
/>
<Button
label={`Toggle Slide Behavior: ${slideBehavior}`}
onPress={handleSlideBehavior}
/>
<Button label="Expand" onPress={handleExpandPress} />
<Button label="Collapse" onPress={handleCollapsePress} />
<Button label="Close" onPress={handleClosePress} />
Expand All @@ -66,17 +35,15 @@ const FooterExample = () => {
snapPoints={snapPoints}
keyboardBehavior="interactive"
keyboardBlurBehavior="restore"
handleComponent={SearchHandle}
enablePanDownToClose={true}
handleComponent={searchHandle}
footerComponent={customFooter}
>
<ContactList count={10} type="FlatList" />
<BottomSheetFooter
bottomInset={bottomSafeArea}
appearanceBehavior={appearanceBehavior}
>
<View style={styles.footer}>
<Text style={styles.footerText}>this is a footer!</Text>
</View>
</BottomSheetFooter>
<ContactList
count={10}
type="FlatList"
enableFooterMarginAdjustment={false}
/>
</BottomSheet>
</View>
);
Expand All @@ -88,13 +55,22 @@ const styles = StyleSheet.create({
padding: 24,
},
footer: {
alignSelf: 'flex-end',
justifyContent: 'center',
alignItems: 'center',
marginHorizontal: 12,
padding: 12,
marginBottom: 12,
borderRadius: 24,
marginHorizontal: 24,
width: 50,
height: 50,
borderRadius: 25,
backgroundColor: '#80f',
shadowOffset: {
width: 0,
height: 12,
},
shadowOpacity: 0.25,
shadowRadius: 8.0,

elevation: 24,
},
footerText: {
fontSize: 16,
Expand Down
16 changes: 11 additions & 5 deletions example/src/screens/modal/DetachedExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ const DetachedExample = () => {
),
[]
);
const renderFooter = useCallback(
props => (
<BottomSheetFooter {...props}>
<View style={styles.footer}>
<Text style={styles.footerText}>this is a footer!</Text>
</View>
</BottomSheetFooter>
),
[]
);
return (
<View style={styles.container}>
<Button label="Present" onPress={handlePresentPress} />
Expand All @@ -70,6 +80,7 @@ const DetachedExample = () => {
enablePanDownToClose={true}
style={styles.sheetContainer}
backgroundComponent={null}
footerComponent={renderFooter}
handleComponent={renderHeaderHandle}
detached={true}
>
Expand All @@ -78,11 +89,6 @@ const DetachedExample = () => {
onLayout={handleContentLayout}
>
{data.map(renderItem)}
<BottomSheetFooter>
<View style={styles.footer}>
<Text style={styles.footerText}>this is a footer!</Text>
</View>
</BottomSheetFooter>
</BottomSheetView>
</BottomSheetModal>
</View>
Expand Down
8 changes: 8 additions & 0 deletions src/components/bottomSheet/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import BottomSheetGestureHandlersProvider from '../bottomSheetGestureHandlersPro
import BottomSheetBackdropContainer from '../bottomSheetBackdropContainer';
import BottomSheetHandleContainer from '../bottomSheetHandleContainer';
import BottomSheetBackgroundContainer from '../bottomSheetBackgroundContainer';
import BottomSheetFooterContainer from '../bottomSheetFooterContainer/BottomSheetFooterContainer';
import BottomSheetDraggableView from '../bottomSheetDraggableView';
// import BottomSheetDebugView from '../bottomSheetDebugView';
import {
Expand Down Expand Up @@ -143,6 +144,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
handleComponent,
backdropComponent,
backgroundComponent,
footerComponent,
children,
} = props;
//#endregion
Expand Down Expand Up @@ -1462,6 +1464,12 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
{typeof children === 'function'
? (children as Function)()
: children}

{footerComponent && (
<BottomSheetFooterContainer
footerComponent={footerComponent}
/>
)}
</BottomSheetDraggableView>
</Animated.View>
<BottomSheetHandleContainer
Expand Down
8 changes: 8 additions & 0 deletions src/components/bottomSheet/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import type { PanGestureHandlerProps } from 'react-native-gesture-handler';
import type { BottomSheetHandleProps } from '../bottomSheetHandle';
import type { BottomSheetBackdropProps } from '../bottomSheetBackdrop';
import type { BottomSheetBackgroundProps } from '../bottomSheetBackground';
import type { BottomSheetFooterProps } from '../bottomSheetFooter';
import type {
ANIMATION_SOURCE,
KEYBOARD_BEHAVIOR,
KEYBOARD_BLUR_BEHAVIOR,
KEYBOARD_INPUT_MODE,
Expand Down Expand Up @@ -231,6 +233,12 @@ export interface BottomSheetProps
* @type React.FC\<BottomSheetBackgroundProps\>
*/
backgroundComponent?: React.FC<BottomSheetBackgroundProps> | null;
/**
* Component to be placed as a footer.
* @see {BottomSheetFooterProps}
* @type React.FC\<BottomSheetFooterProps\>
*/
footerComponent?: React.FC<BottomSheetFooterProps>;
/**
* A scrollable node or normal view.
* @type React.ReactNode[] | React.ReactNode
Expand Down
Loading

0 comments on commit 2cf7289

Please sign in to comment.