From 2d4d69d8881a3cbe452f5e46157e2b9702528206 Mon Sep 17 00:00:00 2001 From: Mo Gorhom Date: Thu, 27 May 2021 22:37:49 +0100 Subject: [PATCH] feat: added pre-integrated VirtualizedList component --- .../components/contactList/ContactList.tsx | 26 ++++++++++++-- example/src/screens/basic/BasicExamples.tsx | 7 +++- example/src/screens/screens.ts | 6 ++++ .../BottomSheetVirtualizedList.tsx | 29 +++++++++++++++ .../createBottomSheetScrollableComponent.tsx | 2 +- src/components/bottomSheetScrollable/index.ts | 2 ++ .../bottomSheetScrollable/types.d.ts | 36 +++++++++++++++++++ src/index.ts | 2 ++ 8 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 src/components/bottomSheetScrollable/BottomSheetVirtualizedList.tsx diff --git a/example/src/components/contactList/ContactList.tsx b/example/src/components/contactList/ContactList.tsx index 19be98d92..7ab6f2751 100644 --- a/example/src/components/contactList/ContactList.tsx +++ b/example/src/components/contactList/ContactList.tsx @@ -6,6 +6,7 @@ import { BottomSheetFlatList, BottomSheetScrollView, BottomSheetSectionList, + BottomSheetVirtualizedList, BottomSheetView, } from '@gorhom/bottom-sheet'; import { @@ -15,13 +16,15 @@ import { import ContactItem from '../contactItem'; export interface ContactListProps { - type: 'FlatList' | 'SectionList' | 'ScrollView' | 'View'; + type: 'FlatList' | 'SectionList' | 'ScrollView' | 'View' | 'VirtualizedList'; count?: number; style?: ViewStyle; onItemPress?: () => void; } const keyExtractor = (item: any, index: number) => `${item.name}.${index}`; +const handleGetItem = (data: any[], index: number) => data[index]; +const handleGetCount = (data: any[]) => data.length; const ContactList = ({ type, @@ -32,9 +35,10 @@ const ContactList = ({ // hooks const { bottom: bottomSafeArea } = useSafeAreaInsets(); - // variables + //#region variables const sections = useMemo(() => createContactSectionsMockData(count), [count]); const data = useMemo(() => createContactListMockData(count), [count]); + //#endregion // styles const contentContainerStyle = useMemo( @@ -105,6 +109,24 @@ const ContactList = ({ focusHook={useFocusEffect} /> ); + } else if (type === 'VirtualizedList') { + return ( + + ); } else if (type === 'ScrollView') { return ( require('./basic/BasicExamples').SectionListExampleScreen, }, + { + name: 'VirtualizedList', + slug: 'Basic/VirtualizedListExample', + getScreen: () => + require('./basic/BasicExamples').VirtualizedListExampleScreen, + }, ], }, { diff --git a/src/components/bottomSheetScrollable/BottomSheetVirtualizedList.tsx b/src/components/bottomSheetScrollable/BottomSheetVirtualizedList.tsx new file mode 100644 index 000000000..a39871f83 --- /dev/null +++ b/src/components/bottomSheetScrollable/BottomSheetVirtualizedList.tsx @@ -0,0 +1,29 @@ +import { memo } from 'react'; +import { + VirtualizedList as RNVirtualizedList, + VirtualizedListProps as RNVirtualizedListProps, +} from 'react-native'; +import Animated from 'react-native-reanimated'; +import { createBottomSheetScrollableComponent } from './createBottomSheetScrollableComponent'; +import type { + BottomSheetVirtualizedListMethods, + BottomSheetVirtualizedListProps, +} from './types'; + +const AnimatedVirtualizedList = + Animated.createAnimatedComponent>( + RNVirtualizedList + ); + +const BottomSheetVirtualizedListComponent = + createBottomSheetScrollableComponent< + BottomSheetVirtualizedListMethods, + BottomSheetVirtualizedListProps + >(AnimatedVirtualizedList); + +const BottomSheetVirtualizedList = memo(BottomSheetVirtualizedListComponent); +BottomSheetVirtualizedList.displayName = 'BottomSheetVirtualizedList'; + +export default BottomSheetVirtualizedList as ( + props: BottomSheetVirtualizedListProps +) => ReturnType; diff --git a/src/components/bottomSheetScrollable/createBottomSheetScrollableComponent.tsx b/src/components/bottomSheetScrollable/createBottomSheetScrollableComponent.tsx index 5cc572234..ac5841780 100644 --- a/src/components/bottomSheetScrollable/createBottomSheetScrollableComponent.tsx +++ b/src/components/bottomSheetScrollable/createBottomSheetScrollableComponent.tsx @@ -43,7 +43,7 @@ export function createBottomSheetScrollableComponent( marginBottom: animatedFooterHeight.value, })); const containerStyle = useMemo( - () => [style, containerAnimatedStyle], + () => [...('length' in style ? style : [style]), containerAnimatedStyle], [style, containerAnimatedStyle] ); //#endregion diff --git a/src/components/bottomSheetScrollable/index.ts b/src/components/bottomSheetScrollable/index.ts index 41f2c18f2..cc719be80 100644 --- a/src/components/bottomSheetScrollable/index.ts +++ b/src/components/bottomSheetScrollable/index.ts @@ -1,9 +1,11 @@ export { default as BottomSheetSectionList } from './BottomSheetSectionList'; export { default as BottomSheetFlatList } from './BottomSheetFlatList'; export { default as BottomSheetScrollView } from './BottomSheetScrollView'; +export { default as BottomSheetVirtualizedList } from './BottomSheetVirtualizedList'; export type { BottomSheetFlatListMethods, BottomSheetScrollViewMethods, BottomSheetSectionListMethods, + BottomSheetVirtualizedListMethods, } from './types'; diff --git a/src/components/bottomSheetScrollable/types.d.ts b/src/components/bottomSheetScrollable/types.d.ts index f435ef230..4afd70a16 100644 --- a/src/components/bottomSheetScrollable/types.d.ts +++ b/src/components/bottomSheetScrollable/types.d.ts @@ -1,5 +1,6 @@ import type { ReactNode, Ref } from 'react'; import type { + VirtualizedListProps, ScrollViewProps, FlatListProps, SectionListProps, @@ -210,3 +211,38 @@ export interface BottomSheetSectionListMethods { getScrollableNode(): NodeHandle | undefined; } //#endregion + +//#region +export type BottomSheetVirtualizedListProps = Omit< + Animated.AnimateProps>, + 'decelerationRate' | 'onScrollBeginDrag' | 'scrollEventThrottle' +> & + BottomSheetScrollableProps & { + ref?: Ref; + }; + +export interface BottomSheetVirtualizedListMethods { + scrollToEnd: (params?: { animated?: boolean }) => void; + scrollToIndex: (params: { + animated?: boolean; + index: number; + viewOffset?: number; + viewPosition?: number; + }) => void; + scrollToItem: (params: { + animated?: boolean; + item: ItemT; + viewPosition?: number; + }) => void; + + /** + * Scroll to a specific content pixel offset in the list. + * Param `offset` expects the offset to scroll to. In case of horizontal is true, the + * offset is the x-value, in any other case the offset is the y-value. + * Param `animated` (true by default) defines whether the list should do an animation while scrolling. + */ + scrollToOffset: (params: { animated?: boolean; offset: number }) => void; + + recordInteraction: () => void; +} +//#endregion diff --git a/src/index.ts b/src/index.ts index 4d5896f50..aa70442e0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,6 +17,7 @@ export { BottomSheetScrollView, BottomSheetSectionList, BottomSheetFlatList, + BottomSheetVirtualizedList, } from './components/bottomSheetScrollable'; export { default as BottomSheetDraggableView } from './components/bottomSheetDraggableView'; export { default as BottomSheetView } from './components/view'; @@ -43,6 +44,7 @@ export type { BottomSheetFlatListMethods, BottomSheetScrollViewMethods, BottomSheetSectionListMethods, + BottomSheetVirtualizedListMethods, } from './components/bottomSheetScrollable'; //#endregion