Skip to content
This repository has been archived by the owner on Jan 6, 2023. It is now read-only.

Commit

Permalink
slider implementation, update docs and tabs example
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Smith authored and Andrew Smith committed Sep 19, 2019
1 parent 11481a6 commit fd37e8d
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 86 deletions.
131 changes: 121 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

Fully controllable, high performance pager component w/ gesture support for React Native

<p align="center">
<img src="docs/assets/inline-cards.gif" />
<p align="center" style="display: flex; justify-content: center; align-items:center;">
<img src="docs/assets/inline-cards.gif" width="300px" style="margin: 0 10px"/>
<img src="docs/assets/paginated-tabs.gif" width="300px" style="margin: 0 10px"/>
</p>

# Installation
Expand All @@ -26,14 +27,14 @@ There are additional steps to setting these up:

_These examples were inspired by the docs of the awesome [react-native-snap-carousel library](https://github.com/archriss/react-native-snap-carousel)_

<p align="center">
<img src="docs/assets/kilter-cards.gif" />
<img src="docs/assets/swipe-cards.gif" />
<p align="center" style="display: flex; justify-content: center; align-items:center; flex-wrap: wrap;">
<img src="docs/assets/kilter-cards.gif" width="300px" style="margin: 0 10px" />
<img src="docs/assets/swipe-cards.gif" width="300px" style="margin: 0 10px" />
</p>

<p align="center">
<img src="docs/assets/stacked-cards.gif" />
<img src="docs/assets/inline-cards.gif" />
<p align="center" style="display: flex; justify-content: center; align-items:center; flex-wrap: wrap;">
<img src="docs/assets/stacked-cards.gif" width="300px" style="margin: 0 10px" />
<img src="docs/assets/inline-cards.gif" width="300px" style="margin: 0 10px" />
</p>

### Basic Pager
Expand Down Expand Up @@ -162,7 +163,7 @@ function Buttons({ activeIndex, onChange }) {
## Pager

```typescript
import { Pager } from 'react-native-pager-component'
import { Pager } from '@crowdlinker/react-native-pager'

Props
--------
Expand Down Expand Up @@ -191,6 +192,43 @@ clampDrag: {
}
```

## Pagination

```typescript
import { Pagination } from '@crowdlinker/react-native-pager'

Props
--------
children: React.ReactNode;
animatedIndex: Animated.Value<number>;
pageInterpolation: iPageInterpolation;
style?: ViewStyle;
```

## Slider

```typescript
import { Slider } from '@crowdlinker/react-native-pager'

Props
--------
numberOfScreens: number;
animatedIndex: Animated.Value<number>;
style: ViewStyle;
```

## Progress

```typescript
import { Progress } from '@crowdlinker/react-native-pager'

Props
--------
numberOfScreens: number;
animatedIndex: Animated.Value<number>;
style: ViewStyle;
```

## Tabs and Stack

Tab and Stack configurations are pretty straightforward to get setup:
Expand Down Expand Up @@ -367,6 +405,7 @@ const swipeCards = {
// you can pass a function as a transformer -- offset in this case will represent
// the distance a screen is from the active screen
// e.g -1 means 1 to the left, 4 means 4 to the right
// this will move cards downwards as they get further away from the activeIndex
translateY: (offset: Animated.Value<number>) =>
Animated.multiply(offset, 10),
},
Expand All @@ -380,11 +419,83 @@ const swipeCards = {
},
],

// any Animated[fn] can be used in these functions
// any Animated function can be used in these
zIndex: offset => floor(divide(offset, -1)),
};

<Pager clamp={{ next: 0 }} pageInterpolation={swipeCards}>
...
</Pager>;
```

## Pagination

<p align="center">
<img src="docs/assets/paginated-tabs.gif" />
</p>

There's a few components to display the current active tab. These require an `animatedIndex` prop that you can pass into the active pager component and share with these components:

```javascript

const animatedIndex = new Value(0)

function MyPager({ children }) {
<View>
<Pager animatedIndex={animatedIndex} {...}>
{children}
</Pager>

// e.g: render this somewhere
<Progress animatedIndex={animatedIndex} numberOfScreens={children.length}>
</View>
}
```

There are three right now: `<Pagination />`, `<Slider />` and `<Progress />`. The API for these might change as it would be nice to have less opinionated and configurable components here.

```javascript
// e.g emphasize active circle
const circleInterpolation = {
transform: [
{
scale: {
inputRange: [-2, -1, 0, 1, 2],
outputRange: [0.5, 0.5, 0.8, 0.5, 0.5],
},
},
],
};

// e.g - position circles vertically
<Pagination
animatedIndex={animatedIndex}
style={{ height: 200, width: 40, flexDirection: 'column' }}
pageInterpolation={circleInterpolation}
>
<Circle />
<Circle />
<Circle />
</Pagination>;
```

```javascript
<Slider
numberOfScreens={children.length}
animatedIndex={animatedIndex}
style={{
backgroundColor: activeColor,
}}
/>
```

```javascript
<Progress
numberOfScreens={3}
animatedIndex={animatedIndex}
style={{
backgroundColor: activeColor,
height: 4,
}}
/>
```
Binary file added docs/assets/paginated-tabs.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 1 addition & 4 deletions example/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,7 @@ const App = () => {
return (
<View style={{flex: 1, backgroundColor: 'white'}}>
<SafeAreaView style={{flex: 1, justifyContent: 'center'}}>
<Tabs activeIndex={activeIndex} onChange={onChange}>
{children}
</Tabs>
<Buttons activeIndex={activeIndex} onChange={onChange} />
<Tabs>{children}</Tabs>
</SafeAreaView>
</View>
);
Expand Down
157 changes: 92 additions & 65 deletions example/tabs-stack.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import React, {useState} from 'react';
import {StyleSheet, TouchableOpacity, View, Text} from 'react-native';
import {Pager, Pagination, Slider} from '@crowdlinker/react-native-pager';
import {
StyleSheet,
TouchableOpacity,
View,
Text,
ViewStyle,
} from 'react-native';
import {
Pager,
Pagination,
Slider,
Progress,
} from '@crowdlinker/react-native-pager';
import Animated from 'react-native-reanimated';

const {Value, multiply} = Animated;
Expand Down Expand Up @@ -63,7 +74,36 @@ function Stack({children}) {
);
}

const animatedIndex = new Value(0);
const circleInterpolation = {
transform: [
{
scale: {
inputRange: [-2, -1, 0, 1, 2],
outputRange: [0.5, 0.5, 0.8, 0.5, 0.5],
},
},
],
};

function Circles({children, onChange}) {
return (
<Pagination
pageInterpolation={circleInterpolation}
animatedIndex={animatedIndex}
style={circlesContainer}>
{React.Children.map(children, (_, i) => (
<Circle i={i} onPress={onChange} />
))}
</Pagination>
);
}

const circlesContainer: ViewStyle = {
height: 20,
width: '70%',
alignSelf: 'center',
transform: [{translateY: -30}],
};

function Circle({i, onPress}) {
return (
Expand All @@ -86,80 +126,67 @@ function Circle({i, onPress}) {
);
}

const circleInterpolation = {
transform: [
{
scale: {
inputRange: [-2, -1, 0, 1, 2],
outputRange: [0.5, 0.5, 0.8, 0.5, 0.5],
},
},
],
};
function Tabbar({children, onChange, activeIndex}) {
return (
<View style={{height: 40, flexDirection: 'row'}}>
{React.Children.map(children, (c, i) => (
<TouchableOpacity
onPress={() => onChange(i)}
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}>
<Text style={{color: activeIndex === i ? colors[i] : 'black'}}>
{i}
</Text>
</TouchableOpacity>
))}
</View>
);
}

function Tabs({
children,
activeIndex: parentActiveIndex,
onChange: parentOnChange,
...rest
}) {
const [_activeIndex, _onChange] = useState(0);
const animatedIndex = new Value(0);

const activeIndex =
parentActiveIndex !== undefined ? parentActiveIndex : _activeIndex;
const onChange = parentActiveIndex !== undefined ? parentOnChange : _onChange;
function Tabs({children}) {
const [activeIndex, onChange] = useState(0);
const activeColor = colors[activeIndex % colors.length];

return (
<View style={{height: 400, width: '100%', alignSelf: 'center'}}>
<View style={{height: 400, width: 300, alignSelf: 'center'}}>
<Pager
style={{flex: 1, paddingBottom: 50, overflow: 'hidden'}}
style={{flex: 1, overflow: 'hidden'}}
animatedIndex={animatedIndex}
activeIndex={activeIndex}
onChange={onChange}
{...rest}>
onChange={onChange}>
{children}
</Pager>

<Pagination
pageInterpolation={circleInterpolation}
<View style={{marginVertical: 30}} />

<Circles onChange={onChange}>{children}</Circles>

<View style={{marginVertical: 10}} />

<Progress
numberOfScreens={children.length}
animatedIndex={animatedIndex}
style={{
height: 20,
width: '50%',
alignSelf: 'center',
transform: [{translateY: -25}],
}}>
{React.Children.map(children, (c, i) => (
<Circle i={i} onPress={onChange} />
))}
</Pagination>

<View style={{backgroundColor: 'white'}}>
<View style={{height: 50, flexDirection: 'row'}}>
{React.Children.map(children, (c, i) => (
<TouchableOpacity
onPress={() => onChange(i)}
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}>
<Text style={{color: activeIndex === i ? colors[i] : 'black'}}>
{i}
</Text>
</TouchableOpacity>
))}
</View>

<Slider
numberOfScreens={children.length}
animatedIndex={animatedIndex}
style={{
backgroundColor: colors[activeIndex % colors.length],
height: 3,
}}
/>
</View>
backgroundColor: activeColor,
}}
/>

<Tabbar activeIndex={activeIndex} onChange={onChange}>
{children}
</Tabbar>

<Slider
numberOfScreens={children.length}
animatedIndex={animatedIndex}
style={{
backgroundColor: activeColor,
}}
/>
</View>
);
}
Expand Down
2 changes: 0 additions & 2 deletions src/pager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ const {
abs,
lessThan,
ceil,
interpolate,
concat,
// @ts-ignore
debug,
} = Animated;
Expand Down
Loading

0 comments on commit fd37e8d

Please sign in to comment.