animation, dots, dropdown, popover and design fixes
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
import React, { useMemo } from "react";
|
||||
import { Animated, StyleSheet, useWindowDimensions, View } from "react-native";
|
||||
import { Palette } from "../../styles";
|
||||
|
||||
const ORIENTATION = {
|
||||
HORIZONTAL: "horizontal",
|
||||
VERTICAL: "vertical",
|
||||
};
|
||||
|
||||
const AnimatedPaginationDot = ({
|
||||
data = [],
|
||||
scrollValue,
|
||||
itemDimension,
|
||||
containerStyle,
|
||||
dotStyle,
|
||||
orientation = ORIENTATION.HORIZONTAL,
|
||||
expandingDotSize = 20,
|
||||
inactiveDotOpacity = 0.4,
|
||||
inactiveDotColor = "rgba(255,255,255,0.4)",
|
||||
activeDotColor = Palette.white,
|
||||
baseDotSize = 10,
|
||||
}) => {
|
||||
const animatedValue = useMemo(
|
||||
() => scrollValue || new Animated.Value(0),
|
||||
[scrollValue],
|
||||
);
|
||||
|
||||
const { width, height } = useWindowDimensions();
|
||||
const distance = useMemo(() => {
|
||||
if (typeof itemDimension === "number" && itemDimension > 0) {
|
||||
return itemDimension;
|
||||
}
|
||||
if (orientation === ORIENTATION.VERTICAL) {
|
||||
return Math.max(height, 1);
|
||||
}
|
||||
return Math.max(width, 1);
|
||||
}, [height, itemDimension, orientation, width]);
|
||||
|
||||
const resolvedDotStyle = useMemo(() => StyleSheet.flatten(dotStyle) || {}, [dotStyle]);
|
||||
const defaultSize = Math.max(baseDotSize, 1);
|
||||
const baseWidth =
|
||||
typeof resolvedDotStyle?.width === "number"
|
||||
? resolvedDotStyle.width
|
||||
: defaultSize;
|
||||
const baseHeight =
|
||||
typeof resolvedDotStyle?.height === "number"
|
||||
? resolvedDotStyle.height
|
||||
: defaultSize;
|
||||
|
||||
const containerOrientationStyle =
|
||||
orientation === ORIENTATION.VERTICAL
|
||||
? styles.containerVertical
|
||||
: styles.containerHorizontal;
|
||||
|
||||
return (
|
||||
<View
|
||||
pointerEvents="none"
|
||||
style={[styles.containerBase, containerOrientationStyle, containerStyle]}
|
||||
>
|
||||
{data.map((_, index) => {
|
||||
const inputRange = [
|
||||
(index - 1) * distance,
|
||||
index * distance,
|
||||
(index + 1) * distance,
|
||||
];
|
||||
|
||||
const staticSizeStyle = {
|
||||
width: baseWidth,
|
||||
height: baseHeight,
|
||||
};
|
||||
|
||||
const color = animatedValue.interpolate({
|
||||
inputRange,
|
||||
outputRange: [inactiveDotColor, activeDotColor, inactiveDotColor],
|
||||
extrapolate: "clamp",
|
||||
});
|
||||
|
||||
const opacity = animatedValue.interpolate({
|
||||
inputRange,
|
||||
outputRange: [inactiveDotOpacity, 1, inactiveDotOpacity],
|
||||
extrapolate: "clamp",
|
||||
});
|
||||
|
||||
const primarySize = animatedValue.interpolate({
|
||||
inputRange,
|
||||
outputRange: [
|
||||
orientation === ORIENTATION.VERTICAL ? baseHeight : baseWidth,
|
||||
expandingDotSize,
|
||||
orientation === ORIENTATION.VERTICAL ? baseHeight : baseWidth,
|
||||
],
|
||||
extrapolate: "clamp",
|
||||
});
|
||||
|
||||
const animatedSizeStyle =
|
||||
orientation === ORIENTATION.VERTICAL
|
||||
? { height: primarySize }
|
||||
: { width: primarySize };
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
key={`pagination-dot-${index}`}
|
||||
style={[
|
||||
styles.dotBase,
|
||||
staticSizeStyle,
|
||||
dotStyle,
|
||||
animatedSizeStyle,
|
||||
{ backgroundColor: color, opacity },
|
||||
]}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
AnimatedPaginationDot.orientation = ORIENTATION;
|
||||
|
||||
export default AnimatedPaginationDot;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
containerBase: {
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
},
|
||||
containerHorizontal: {
|
||||
flexDirection: "row",
|
||||
},
|
||||
containerVertical: {
|
||||
flexDirection: "column",
|
||||
},
|
||||
dotBase: {
|
||||
borderRadius: 999,
|
||||
marginHorizontal: 4,
|
||||
marginVertical: 4,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user