From 0dc0056b77cedb168a134ad03c0a85e0d943caea Mon Sep 17 00:00:00 2001 From: Jakub Biesiada Date: Sun, 5 Jun 2022 17:48:25 +0200 Subject: [PATCH] Remove extra React imports --- src/components/FactoryList.tsx | 66 ++++++++++++++++++++++++++++++ src/components/FlatList.tsx | 41 +++++++++++++++++++ src/components/ScrollView.tsx | 43 +++++++++++++++++++ src/components/SectionList.tsx | 38 +++++++++++++++++ src/index.tsx | 75 ++-------------------------------- src/types.ts | 3 ++ src/useSmartScroll.ts | 59 ++++++++++++++++++++++++++ 7 files changed, 254 insertions(+), 71 deletions(-) create mode 100644 src/components/FactoryList.tsx create mode 100755 src/components/FlatList.tsx create mode 100755 src/components/ScrollView.tsx create mode 100755 src/components/SectionList.tsx create mode 100644 src/types.ts create mode 100755 src/useSmartScroll.ts diff --git a/src/components/FactoryList.tsx b/src/components/FactoryList.tsx new file mode 100644 index 0000000..bdf1349 --- /dev/null +++ b/src/components/FactoryList.tsx @@ -0,0 +1,66 @@ +import React from 'react' +import { + FlatList, + ScrollView, + SectionList, + SectionListProps, +} from 'react-native' + +import type { Params } from '../types' + +import { useSmartScroll } from '../useSmartScroll' + +// TODO generic type +interface Props extends SectionListProps, Params { + readonly children: React.ReactNode +} + +export const listFactory = ( + ListComponent: typeof FlatList | typeof SectionList | typeof ScrollView +) => { + const ListFactory = ({ + children, + scrollEnabled, + onLayout, + onContentSizeChange, + horizontal, + onSmartScrollStatusChange, + ...props + }: Props) => { + // let Component: typeof FlatList | typeof SectionList | typeof ScrollView + + // switch (ListComponent) { + // case 'FlatList': + // Component = FlatList + // break + + // case 'SectionList': + // Component = SectionList + // break + + // default: + // Component = ScrollView + // break + // } + + const { handleContentSizeChange, handleLayout, isScrollEnabled } = + useSmartScroll({ + horizontal, + onSmartScrollStatusChange, + onLayout, + onContentSizeChange, + }) + + return ( + + ) + } + + return ListFactory +} diff --git a/src/components/FlatList.tsx b/src/components/FlatList.tsx new file mode 100755 index 0000000..795cd99 --- /dev/null +++ b/src/components/FlatList.tsx @@ -0,0 +1,41 @@ +import React from 'react' +import { FlatList as BaseFlatList, FlatListProps } from 'react-native' +import { listFactory } from './FactoryList' + +// import type { Params } from '../types' + +// import { useSmartScroll } from '../useSmartScroll' + +// interface Props extends FlatListProps, Params { +// readonly children: React.ReactNode +// } + +// export const FlatList = ({ +// children, +// scrollEnabled, +// onLayout, +// onContentSizeChange, +// horizontal, +// onSmartScrollStatusChange, +// ...props +// }: Props) => { +// const { handleContentSizeChange, handleLayout, isScrollEnabled } = +// useSmartScroll({ +// horizontal, +// onSmartScrollStatusChange, +// onLayout, +// onContentSizeChange, +// }) + +// return ( +// +// ) +// } + +export const FlatList = listFactory>(BaseFlatList) diff --git a/src/components/ScrollView.tsx b/src/components/ScrollView.tsx new file mode 100755 index 0000000..b00f16e --- /dev/null +++ b/src/components/ScrollView.tsx @@ -0,0 +1,43 @@ +import React from 'react' +import { ScrollView as BaseScrollView, ScrollViewProps } from 'react-native' + +import type { Params } from '../types' + +import { useSmartScroll } from '../useSmartScroll' +import { listFactory } from './FactoryList' + +interface Props extends ScrollViewProps, Params { + readonly children: React.ReactNode +} + +// export const ScrollView = ({ +// children, +// scrollEnabled, +// onLayout, +// onContentSizeChange, +// horizontal, +// onSmartScrollStatusChange, +// ...props +// }: Props) => { +// const { handleContentSizeChange, handleLayout, isScrollEnabled } = +// useSmartScroll({ +// horizontal, +// onSmartScrollStatusChange, +// onLayout, +// onContentSizeChange, +// }) + +// return ( +// +// {children} +// +// ) +// } + +export const ScrollView = listFactory(BaseScrollView) diff --git a/src/components/SectionList.tsx b/src/components/SectionList.tsx new file mode 100755 index 0000000..d16857e --- /dev/null +++ b/src/components/SectionList.tsx @@ -0,0 +1,38 @@ +import React from 'react' +import { SectionList as BaseSectionList, SectionListProps } from 'react-native' + +import type { Params } from '../types' + +import { useSmartScroll } from '../useSmartScroll' + +interface Props extends SectionListProps, Params { + readonly children: React.ReactNode +} + +export const SectionList = ({ + children, + scrollEnabled, + onLayout, + onContentSizeChange, + horizontal, + onSmartScrollStatusChange, + ...props +}: Props) => { + const { handleContentSizeChange, handleLayout, isScrollEnabled } = + useSmartScroll({ + horizontal, + onSmartScrollStatusChange, + onLayout, + onContentSizeChange, + }) + + return ( + + ) +} diff --git a/src/index.tsx b/src/index.tsx index d7c7846..6d1323a 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,72 +1,5 @@ -import React, { useCallback, useMemo, useState, useEffect } from 'react' -import { ScrollViewProps, ScrollView } from 'react-native' +export { FlatList } from './components/FlatList' +export { ScrollView } from './components/ScrollView' +export { SectionList } from './components/SectionList' -interface Props extends ScrollViewProps { - readonly children: React.ReactNode - onSmartScrollStatusChange?: (isScrollEnabled: boolean) => void -} - -type HandleLayoutCallback = NonNullable -type HandleContentSizeChangeCallback = NonNullable< - ScrollViewProps['onContentSizeChange'] -> - -const SmartScrollContainer = ({ - children, - scrollEnabled, - onLayout, - onContentSizeChange, - horizontal, - onSmartScrollStatusChange, - ...props -}: Props) => { - const [wrapperWidth, setWrapperWidth] = useState(0) - const [wrapperHeight, setWrapperHeight] = useState(0) - const [contentSize, setContentSize] = useState(0) - - const isScrollEnabled = useMemo( - () => - scrollEnabled || - (horizontal ? wrapperWidth : wrapperHeight) < contentSize, - [contentSize, horizontal, scrollEnabled, wrapperHeight, wrapperWidth] - ) - - useEffect(() => { - onSmartScrollStatusChange?.(isScrollEnabled) - }, [isScrollEnabled, onSmartScrollStatusChange]) - - const handleLayout = useCallback( - (e) => { - const { width, height } = e.nativeEvent.layout - - setWrapperWidth(width) - setWrapperHeight(height) - - onLayout?.(e) - }, - [onLayout] - ) - - const handleContentSizeChange = useCallback( - (w, h) => { - setContentSize(horizontal ? w : h) - - onContentSizeChange?.(w, h) - }, - [horizontal, onContentSizeChange] - ) - - return ( - - {children} - - ) -} - -export default SmartScrollContainer +export { useSmartScroll } from './useSmartScroll' diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..f1bfe6c --- /dev/null +++ b/src/types.ts @@ -0,0 +1,3 @@ +export interface Params { + onSmartScrollStatusChange?: (isScrollEnabled: boolean) => void +} diff --git a/src/useSmartScroll.ts b/src/useSmartScroll.ts new file mode 100755 index 0000000..9ff2f4d --- /dev/null +++ b/src/useSmartScroll.ts @@ -0,0 +1,59 @@ +import { useCallback, useMemo, useState, useEffect } from 'react' +import { ScrollViewProps, VirtualizedListProps } from 'react-native' + +// type Params = Pick< +// VirtualizedListProps, +// 'horizontnal' | 'onLayout' | 'onContentSizeChange' +// > & + +type HandleLayoutCallback = NonNullable +type HandleContentSizeChangeCallback = NonNullable< + ScrollViewProps['onContentSizeChange'] +> + +export const useSmartScroll = ({ + horizontal, + onSmartScrollStatusChange, + onLayout, + onContentSizeChange, +}: Params) => { + const [wrapperWidth, setWrapperWidth] = useState(0) + const [wrapperHeight, setWrapperHeight] = useState(0) + const [contentSize, setContentSize] = useState(0) + + const isScrollEnabled = useMemo( + () => (horizontal ? wrapperWidth : wrapperHeight) < contentSize, + [contentSize, horizontal, wrapperHeight, wrapperWidth] + ) + + useEffect(() => { + onSmartScrollStatusChange?.(isScrollEnabled) + }, [isScrollEnabled, onSmartScrollStatusChange]) + + const handleLayout = useCallback( + (e) => { + const { width, height } = e.nativeEvent.layout + + setWrapperWidth(width) + setWrapperHeight(height) + + onLayout?.(e) + }, + [onLayout] + ) + + const handleContentSizeChange = useCallback( + (w, h) => { + setContentSize(horizontal ? w : h) + + onContentSizeChange?.(w, h) + }, + [horizontal, onContentSizeChange] + ) + + return { + handleLayout, + handleContentSizeChange, + isScrollEnabled, + } +}