Skip to content

Commit

Permalink
feat: adds Pagination component
Browse files Browse the repository at this point in the history
closes #267, closes #304, closes #329, closes #164
  • Loading branch information
dohooo committed May 5, 2024
1 parent 6893388 commit 0d2b930
Show file tree
Hide file tree
Showing 16 changed files with 422 additions and 179 deletions.
5 changes: 5 additions & 0 deletions .changeset/lazy-ties-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-native-reanimated-carousel": patch
---

Adds Pagination Component
6 changes: 1 addition & 5 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ module.exports = {
"quotes": "off",
"@typescript-eslint/quotes": "error",
"operator-linebreak": "off",
"@stylistic/js/operator-linebreak": ["error", "before"],
},
plugins: [
"jest",
"@stylistic/js",
],
plugins: ["jest"],
};
2 changes: 1 addition & 1 deletion example/app/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"rules": {
"@typescript-eslint/no-use-before-define": "off",
"no-console": "off"
}
},
}
2 changes: 1 addition & 1 deletion example/app/src/__snapshots__/snapshots.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ exports[`<Carousel /> renders animTabBar correctly 1`] = `
}
}
>
周一
Mon
</Text>
</View>
</View>
Expand Down
2 changes: 1 addition & 1 deletion example/app/src/pages/anim-tab-bar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { useToggleButton } from "../../hooks/useToggleButton";

const PAGE_WIDTH = 60;
const PAGE_HEIGHT = 40;
const DATA = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
const DATA = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];

function Index() {
const r = React.useRef<ICarouselInstance>(null);
Expand Down
238 changes: 127 additions & 111 deletions example/app/src/pages/parallax/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import * as React from "react";
import { View } from "react-native";
import Animated, {
Extrapolate,
interpolate,
useAnimatedStyle,
useSharedValue,
} from "react-native-reanimated";
import Carousel from "react-native-reanimated-carousel";
import { useSharedValue } from "react-native-reanimated";
import Carousel, {
ICarouselInstance,
Pagination,
} from "react-native-reanimated-carousel";

import { SBItem } from "../../components/SBItem";
import SButton from "../../components/SButton";
Expand All @@ -27,18 +25,31 @@ function Index() {
const [autoPlay, setAutoPlay] = React.useState(false);
const [pagingEnabled, setPagingEnabled] = React.useState<boolean>(true);
const [snapEnabled, setSnapEnabled] = React.useState<boolean>(true);
const progressValue = useSharedValue<number>(0);
const progress = useSharedValue<number>(0);
const baseOptions = isVertical
? ({
vertical: true,
width: PAGE_WIDTH * 0.86,
height: PAGE_WIDTH * 0.6,
} as const)
vertical: true,
width: PAGE_WIDTH * 0.86,
height: PAGE_WIDTH * 0.6,
} as const)
: ({
vertical: false,
width: PAGE_WIDTH,
height: PAGE_WIDTH * 0.6,
} as const);
vertical: false,
width: PAGE_WIDTH,
height: PAGE_WIDTH * 0.6,
} as const);

const ref = React.useRef<ICarouselInstance>(null);

const onPressPagination = (index: number) => {
ref.current?.scrollTo({
/**
* Calculate the difference between the current index and the target index
* to ensure that the carousel scrolls to the nearest index
*/
count: index - progress.value,
animated: true,
});
};

return (
<View
Expand All @@ -47,18 +58,17 @@ function Index() {
}}
>
<Carousel
ref={ref}
{...baseOptions}
style={{
width: PAGE_WIDTH,
width: PAGE_WIDTH,
}}
loop
pagingEnabled={pagingEnabled}
snapEnabled={snapEnabled}
autoPlay={autoPlay}
autoPlayInterval={1500}
onProgressChange={(_, absoluteProgress) =>
(progressValue.value = absoluteProgress)
}
onProgressChange={progress}
mode="parallax"
modeConfig={{
parallaxScrollingScale: 0.9,
Expand All @@ -67,41 +77,108 @@ function Index() {
data={colors}
renderItem={({ index }) => <SBItem index={index} />}
/>
{!!progressValue && (
<View
style={
isVertical
? {
flexDirection: "column",
justifyContent: "space-between",
width: 10,
alignSelf: "center",

<Pagination.Basic
progress={progress}
data={colors}
dotStyle={{ backgroundColor: "rgba(0,0,0,0.2)" }}
containerStyle={{ gap: 5, marginBottom: 10 }}
onPress={onPressPagination}
/>

<Pagination.Basic<{ color: string }>
progress={progress}
data={colors.map((color) => ({ color }))}
dotStyle={{
width: 25,
height: 4,
backgroundColor: "rgba(0,0,0,0.2)",
}}
activeDotStyle={{
overflow: "hidden",
}}
containerStyle={[
isVertical
? {
position: "absolute",
width: 25,
right: 5,
top: 40,
}
: {
flexDirection: "row",
justifyContent: "space-between",
width: 100,
alignSelf: "center",
: undefined,
{
gap: 10,
marginBottom: 10,
},
]}
horizontal={!isVertical}
onPress={onPressPagination}
/>

<Pagination.Basic<{ color: string }>
progress={progress}
data={colors.map((color) => ({ color }))}
size={20}
dotStyle={{
borderRadius: 100,
backgroundColor: "rgba(0,0,0,0.2)",
}}
activeDotStyle={{
borderRadius: 100,
overflow: "hidden",
}}
containerStyle={[
isVertical
? {
position: "absolute",
width: 20,
right: 5,
top: 40,
}
}
>
{colors.map((backgroundColor, index) => {
return (
<PaginationItem
backgroundColor={backgroundColor}
animValue={progressValue}
index={index}
key={index}
isRotate={isVertical}
length={colors.length}
/>
);
})}
</View>
)}
: undefined,
{
gap: 5,
marginBottom: 10,
},
]}
horizontal={!isVertical}
onPress={onPressPagination}
/>

<Pagination.Basic<{ color: string }>
progress={progress}
data={colors.map((color) => ({ color }))}
size={20}
dotStyle={{
borderRadius: 100,
backgroundColor: "rgba(0,0,0,0.2)",
}}
activeDotStyle={{
borderRadius: 100,
overflow: "hidden",
}}
containerStyle={[
isVertical
? {
position: "absolute",
width: 20,
right: 5,
top: 40,
}
: undefined,
]}
horizontal={!isVertical}
renderItem={(item) => (
<View
style={{
backgroundColor: item.color,
flex: 1,
}}
/>
)}
onPress={onPressPagination}
/>

<SButton
onPress={() => setAutoPlay(!autoPlay)}
>{`${ElementsText.AUTOPLAY}:${autoPlay}`}</SButton>
Expand Down Expand Up @@ -130,65 +207,4 @@ function Index() {
);
}

const PaginationItem: React.FC<{
index: number
backgroundColor: string
length: number
animValue: Animated.SharedValue<number>
isRotate?: boolean
}> = (props) => {
const { animValue, index, length, backgroundColor, isRotate } = props;
const width = 10;

const animStyle = useAnimatedStyle(() => {
let inputRange = [index - 1, index, index + 1];
let outputRange = [-width, 0, width];

if (index === 0 && animValue?.value > length - 1) {
inputRange = [length - 1, length, length + 1];
outputRange = [-width, 0, width];
}

return {
transform: [
{
translateX: interpolate(
animValue?.value,
inputRange,
outputRange,
Extrapolate.CLAMP,
),
},
],
};
}, [animValue, index, length]);
return (
<View
style={{
backgroundColor: "white",
width,
height: width,
borderRadius: 50,
overflow: "hidden",
transform: [
{
rotateZ: isRotate ? "90deg" : "0deg",
},
],
}}
>
<Animated.View
style={[
{
borderRadius: 50,
backgroundColor,
flex: 1,
},
animStyle,
]}
/>
</View>
);
};

export default Index;
2 changes: 1 addition & 1 deletion example/website/pages/Examples/anim-tab-bar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ import { useToggleButton } from "../../hooks/useToggleButton";

const PAGE_WIDTH = 60;
const PAGE_HEIGHT = 40;
const DATA = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
const DATA = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];

function Index() {
const r = React.useRef<ICarouselInstance>(null);
Expand Down
3 changes: 2 additions & 1 deletion example/website/pages/props.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ The maximum number of items that can respond to pan gesture events, `0` means al

### `onProgressChange`

On progress change. `offsetProgress`:Total of offset distance \(0 390 780 ...\); `absoluteProgress`:Convert to index \(0 1 2 ...\)
This callback is called when the carousel is scrolled. If you want to update a shared value automatically, you can use the shared value as a parameter directly.
The callback provides two parameters: `offsetProgress`:Total of offset distance \(0 390 780 ...\); `absoluteProgress`:Convert to index \(0 1 2 ...\)

| type | default | required |
| ------ | ------- | -------- |
Expand Down
Loading

0 comments on commit 0d2b930

Please sign in to comment.