Skip to content

Commit

Permalink
feat: allow custom separator, optimise current one by @hirbod (#9) (#11)
Browse files Browse the repository at this point in the history
* chore: make separator memoized (#9)

* chore: allow to override ItemSeparatorComponent

* docs: updated readme file

* chore: added BasicCustomSeparator to example

Co-authored-by: Hirbod <Hirbod@users.noreply.github.com>
  • Loading branch information
gorhom and hirbod authored Jun 1, 2020
1 parent 14a7171 commit 7700731
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 16 deletions.
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,20 @@ export default App

## Props

| name | description | required | type | default |
| ---------------------------- | ------------------------------------------------------------------------------------------------- | -------- | --------------------------------------------------- | ------- |
| `itemWidth` | Item's width. | YES | number | |
| `itemHeight` | Item's height. | YES | number | |
| `separatorSize` | FlatList's separator width. | NO | number | 10 |
| `borderRadius` | Item & sticky border radius. | NO | number | 15 |
| `stickyItemActiveOpacity` | Sticky item's active opacity. | YES | number | 0.25 |
| `stickyItemWidth` | Sticky item's width. | YES | number | |
| `stickyItemHeight` | Sticky item's height. | YES | number | |
| `stickyItemBackgroundColors` | Sticky item's two background colors, one when sticky item is extended another when it's minimize. | YES | string[] | |
| `stickyItemContent` | Sticky item's content component. | YES | [`ReactNode`](./src/types.ts#L30) | |
| `isRTL` | FlatList' layout direction. | NO | boolean | false |
| `onStickyItemPress` | Callback when sticky item gets pressed. | NO | function | |
| `...FlatList Props` | React Native FlatList props. | NO | [`FlatList`](https://reactnative.dev/docs/flatlist) | |
| name | description | required | type | default |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------- | -------- | --------------------------------------------------- | ------- |
| `itemWidth` | Item's width. | YES | number | |
| `itemHeight` | Item's height. | YES | number | |
| `separatorSize` | FlatList's separator width, \* if you provide `ItemSeparatorComponent`, you will need to set `separatorSize`. | NO\* | number | 10 |
| `borderRadius` | Item & sticky border radius. | NO | number | 15 |
| `stickyItemActiveOpacity` | Sticky item's active opacity. | YES | number | 0.25 |
| `stickyItemWidth` | Sticky item's width. | YES | number | |
| `stickyItemHeight` | Sticky item's height. | YES | number | |
| `stickyItemBackgroundColors` | Sticky item's two background colors, one when sticky item is extended another when it's minimize. | YES | string[] | |
| `stickyItemContent` | Sticky item's content component. | YES | [`ReactNode`](./src/types.ts#L30) | |
| `isRTL` | FlatList' layout direction. | NO | boolean | false |
| `onStickyItemPress` | Callback when sticky item gets pressed. | NO | function | |
| `...FlatList Props` | React Native FlatList props. | NO | [`FlatList`](https://reactnative.dev/docs/flatlist) | |

## To Do

Expand Down
8 changes: 8 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { createStackNavigator } from '@react-navigation/stack';
import RootScreen from './screens/Root';
import BasicScreen from './screens/Basic';
import BasicRTLScreen from './screens/BasicRTL';
import BasicCustomSeparatorScreen from './screens/BasicCustomSeparator';
import FacebookStoriesScreen from './screens/FacebookStories';
import FacebookStoriesStyledScreen from './screens/FacebookStoriesStyled';
import FacebookStoriesRTLScreen from './screens/FacebookStoriesRTL';
Expand All @@ -29,6 +30,13 @@ export default function App() {
}}
component={BasicRTLScreen}
/>
<Stack.Screen
name="BasicCustomSeparator"
initialParams={{
title: 'Custom Separator',
}}
component={BasicCustomSeparatorScreen}
/>
<Stack.Screen
name="FacebookStories"
initialParams={{
Expand Down
118 changes: 118 additions & 0 deletions example/src/screens/BasicCustomSeparator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React from 'react';
import {
StyleSheet,
View,
SafeAreaView,
StatusBar,
Text,
Alert,
Platform,
ListRenderItemInfo,
} from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { useRoute } from '@react-navigation/native';
import StickyItemFlatList from '@gorhom/sticky-item';
import DummyItem from '../components/dummy-item';
import BasicSticky from '../components/basic-sticky';

const data = [...Array(20)]
.fill(0)
.map((_, index) => ({ id: `item-${index}` }));

export const STORY_WIDTH = 200;
export const STORY_HEIGHT = 100;
const SEPARATOR_SIZE = 10;
const BORDER_RADIUS = 0;

const BasicCustomSeparator = () => {
const { params } = useRoute();
// @ts-ignore
const { title } = params;

// styles
const containerStyle = {
paddingVertical: SEPARATOR_SIZE * 2,
backgroundColor: 'white',
};

// methods
const handleStickyItemPress = () => Alert.alert('Sticky Item Pressed');

// render
const renderItem = ({ index }: ListRenderItemInfo<{}>) => (
<TouchableOpacity onPress={() => Alert.alert(`Item ${index} Pressed`)}>
<DummyItem
index={index}
borderRadius={BORDER_RADIUS}
width={STORY_WIDTH}
height={STORY_HEIGHT}
backgroundColor={'#dfdfdf'}
/>
</TouchableOpacity>
);

const renderSeparator = ({ size }: { size: number }) => {
return (
<View style={{ width: size }}>
<View style={styles.separatorLine} />
</View>
);
};
return (
<SafeAreaView style={styles.root}>
<StatusBar barStyle="dark-content" />
<Text style={styles.text}>{title}</Text>
<View style={containerStyle}>
<StickyItemFlatList
itemWidth={STORY_WIDTH}
itemHeight={STORY_HEIGHT}
separatorSize={SEPARATOR_SIZE}
borderRadius={BORDER_RADIUS}
stickyItemWidth={36}
stickyItemHeight={36}
stickyItemBackgroundColors={['#F8F8FA', '#2d88ff']}
stickyItemContent={BasicSticky}
onStickyItemPress={handleStickyItemPress}
data={data}
renderItem={renderItem}
ItemSeparatorComponent={renderSeparator}
/>
</View>
</SafeAreaView>
);
};

const styles = StyleSheet.create({
root: {
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-start',
backgroundColor: '#CACACD',
},
text: {
marginHorizontal: SEPARATOR_SIZE * 2,
marginBottom: SEPARATOR_SIZE,
fontSize: 43,
fontWeight: Platform.OS === 'ios' ? '900' : 'bold',
textTransform: 'uppercase',
color: '#2d88ff',
},
buttons: {
marginTop: SEPARATOR_SIZE,
marginHorizontal: SEPARATOR_SIZE * 2,
flexDirection: 'row',
justifyContent: 'space-between',
alignContent: 'space-between',
},
separatorLine: {
position: 'absolute',
left: '50%',
top: '25%',
height: '50%',
width: 1,
opacity: 0.5,
backgroundColor: '#CACACD',
},
});

export default BasicCustomSeparator;
4 changes: 4 additions & 0 deletions example/src/screens/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ const examples = [
name: 'RTL',
slug: 'BasicRTL',
},
{
name: 'Custom Separator',
slug: 'BasicCustomSeparator',
},
],
},
{
Expand Down
21 changes: 19 additions & 2 deletions src/StickyItemFlatList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import React, {
Ref,
useImperativeHandle,
} from 'react';
import { View, Dimensions } from 'react-native';
import { Dimensions } from 'react-native';
import Animated, {
event,
useCode,
Expand All @@ -24,6 +24,7 @@ import {
} from 'react-native-gesture-handler';
import { useValues, useGestureHandler } from 'react-native-redash';
import StickyItem from './components/sticky-item';
import Separator from './components/separator';
import {
DEFAULT_SEPARATOR_SIZE,
DEFAULT_BORDER_RADIUS,
Expand Down Expand Up @@ -55,6 +56,7 @@ const StickyItemFlatList = forwardRef(
stickyItemContent,
onStickyItemPress,
isRTL = DEFAULT_IS_RTL,
ItemSeparatorComponent = Separator,
...rest
} = props;

Expand All @@ -67,6 +69,12 @@ const StickyItemFlatList = forwardRef(
itemWidth,
separatorSize,
]);
const separatorProps = useMemo(
() => ({
size: separatorSize,
}),
[separatorSize]
);
//#endregion

//#region styles
Expand Down Expand Up @@ -195,7 +203,16 @@ const StickyItemFlatList = forwardRef(
//#endregion

// render
const renderSeparator = () => <View style={{ width: separatorSize }} />;
const renderSeparator = useCallback(() => {
if (typeof ItemSeparatorComponent === 'function') {
// @ts-ignore
return ItemSeparatorComponent(separatorProps);
} else {
// @ts-ignore
return <ItemSeparatorComponent size={separatorProps.size} />;
}
}, [ItemSeparatorComponent, separatorProps]);

return (
<TapGestureHandler
ref={tapRef}
Expand Down
13 changes: 13 additions & 0 deletions src/components/separator/Separator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React, { memo } from 'react';
import { View } from 'react-native';
import { SeparatorConfig } from '../../types';

interface SeparatorProps extends SeparatorConfig {}

const SeparatorComponent = ({ size }: SeparatorProps) => {
return <View style={{ width: size }} />;
};

const Separator = memo(SeparatorComponent);

export default Separator;
1 change: 1 addition & 0 deletions src/components/separator/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Separator';
15 changes: 15 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ export interface StickyItemConfig {
isRTL?: boolean;
}

export interface SeparatorConfig {
/**
* FlatList's separator width
* @type {number}
* @default 10
*/
size: number;
}

export interface StickyItemFlatListProps<T>
extends FlatListProps<T>,
StickyItemConfig {
Expand All @@ -99,4 +108,10 @@ export interface StickyItemFlatListProps<T>
* @type {() => void}
*/
onStickyItemPress?: () => void;

/**
* Override `FlatList` prop, to add
* `SeparatorConfig` to `ItemSeparatorComponent`
*/
ItemSeparatorComponent?: React.ComponentType<SeparatorConfig>;
}

0 comments on commit 7700731

Please sign in to comment.