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,
|
||||
},
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import React, {
|
||||
useState,
|
||||
} from "react";
|
||||
import {
|
||||
Animated,
|
||||
FlatList,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
@@ -15,6 +16,8 @@ import {
|
||||
import { ai } from "../../assets";
|
||||
import { getCreationStageStates } from "../../utils/projectStages";
|
||||
import PersonaCard from "../cards/PersonaCard/PersonaCard";
|
||||
import AnimatedPaginationDot from "../AnimatedPaginationDot/AnimatedPaginationDot";
|
||||
import { BlurView } from "expo-blur";
|
||||
|
||||
const STAGE_CARD_CONTENT = [
|
||||
{
|
||||
@@ -65,14 +68,14 @@ const FeatureCarousel = ({
|
||||
...item,
|
||||
isLocked: stageStates[index]?.isLocked ?? true,
|
||||
})),
|
||||
[stageStates]
|
||||
[stageStates],
|
||||
);
|
||||
|
||||
const { height: windowHeight } = useWindowDimensions();
|
||||
const isWeb = Platform.OS === "web";
|
||||
|
||||
const [viewportHeight, setViewportHeight] = useState(() =>
|
||||
Math.max(windowHeight, 1)
|
||||
Math.max(windowHeight, 1),
|
||||
);
|
||||
|
||||
const updateSnapHeight = useCallback((height) => {
|
||||
@@ -97,9 +100,10 @@ const FeatureCarousel = ({
|
||||
const pendingScrollRef = useRef(false);
|
||||
const alignTimeoutRef = useRef(null);
|
||||
const activeIndexRef = useRef(
|
||||
typeof activeIndex === "number" ? activeIndex : 0
|
||||
typeof activeIndex === "number" ? activeIndex : 0,
|
||||
);
|
||||
const onActiveIndexChangeRef = useRef(onActiveIndexChange);
|
||||
const scrollY = useRef(new Animated.Value(0)).current;
|
||||
|
||||
useEffect(() => {
|
||||
onActiveIndexChangeRef.current = onActiveIndexChange;
|
||||
@@ -124,7 +128,7 @@ const FeatureCarousel = ({
|
||||
}
|
||||
return index;
|
||||
},
|
||||
[carouselItems.length]
|
||||
[carouselItems.length],
|
||||
);
|
||||
|
||||
const clearPendingAlignment = useCallback(() => {
|
||||
@@ -169,7 +173,7 @@ const FeatureCarousel = ({
|
||||
pendingScrollRef.current = false;
|
||||
}
|
||||
},
|
||||
[clampIndex, isWeb, itemHeight, updateSnapHeight]
|
||||
[clampIndex, isWeb, itemHeight, updateSnapHeight],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -234,7 +238,7 @@ const FeatureCarousel = ({
|
||||
scrollToIndex(nextIndex, shouldAnimate, height);
|
||||
}
|
||||
},
|
||||
[clampIndex, isWeb, itemHeight, scrollToIndex, updateSnapHeight]
|
||||
[clampIndex, isWeb, itemHeight, scrollToIndex, updateSnapHeight],
|
||||
);
|
||||
|
||||
const handleScrollEnd = useCallback(
|
||||
@@ -244,7 +248,7 @@ const FeatureCarousel = ({
|
||||
const layoutHeight = event?.nativeEvent?.layoutMeasurement?.height;
|
||||
alignToOffset(offsetY, layoutHeight);
|
||||
},
|
||||
[alignToOffset, clearPendingAlignment]
|
||||
[alignToOffset, clearPendingAlignment],
|
||||
);
|
||||
|
||||
const handleScroll = useCallback(
|
||||
@@ -260,7 +264,16 @@ const FeatureCarousel = ({
|
||||
alignTimeoutRef.current = null;
|
||||
}, 80);
|
||||
},
|
||||
[alignToOffset, clearPendingAlignment, isWeb]
|
||||
[alignToOffset, clearPendingAlignment, isWeb],
|
||||
);
|
||||
|
||||
const animatedScrollHandler = useMemo(
|
||||
() =>
|
||||
Animated.event([{ nativeEvent: { contentOffset: { y: scrollY } } }], {
|
||||
useNativeDriver: false,
|
||||
listener: isWeb ? handleScroll : undefined,
|
||||
}),
|
||||
[handleScroll, isWeb, scrollY],
|
||||
);
|
||||
|
||||
const handleLayout = useCallback(
|
||||
@@ -270,7 +283,7 @@ const FeatureCarousel = ({
|
||||
updateSnapHeight(layoutHeight);
|
||||
}
|
||||
},
|
||||
[updateSnapHeight]
|
||||
[updateSnapHeight],
|
||||
);
|
||||
|
||||
const keyExtractor = useCallback((item) => item.key, []);
|
||||
@@ -284,7 +297,7 @@ const FeatureCarousel = ({
|
||||
height={itemHeight}
|
||||
/>
|
||||
),
|
||||
[itemHeight]
|
||||
[itemHeight],
|
||||
);
|
||||
|
||||
const getItemLayout = useCallback(
|
||||
@@ -293,7 +306,7 @@ const FeatureCarousel = ({
|
||||
offset: itemHeight * index,
|
||||
index,
|
||||
}),
|
||||
[itemHeight]
|
||||
[itemHeight],
|
||||
);
|
||||
|
||||
const viewabilityConfig = useRef({ viewAreaCoveragePercentThreshold: 60 });
|
||||
@@ -324,8 +337,20 @@ const FeatureCarousel = ({
|
||||
return carouselItems.map((_, index) => index * itemHeight);
|
||||
}, [carouselItems, isWeb, itemHeight]);
|
||||
|
||||
const blurIntensity = isWeb ? 80 : 30;
|
||||
const dotsWrapperStyle = useMemo(
|
||||
() => [
|
||||
styles.dotsWrapperBase,
|
||||
isWeb ? styles.dotsWrapperWeb : styles.dotsWrapperNative,
|
||||
],
|
||||
[isWeb],
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={[styles.container, style]} onLayout={handleLayout}>
|
||||
<View
|
||||
style={[styles.container, isWeb && styles.containerWeb, style]}
|
||||
onLayout={handleLayout}
|
||||
>
|
||||
<FlatList
|
||||
ref={listRef}
|
||||
data={carouselItems}
|
||||
@@ -348,10 +373,28 @@ const FeatureCarousel = ({
|
||||
disableIntervalMomentum={!isWeb}
|
||||
decelerationRate={!isWeb ? "fast" : undefined}
|
||||
style={styles.list}
|
||||
onScroll={isWeb ? handleScroll : undefined}
|
||||
onScroll={animatedScrollHandler}
|
||||
onMomentumScrollEnd={handleScrollEnd}
|
||||
onScrollEndDrag={isWeb ? handleScrollEnd : undefined}
|
||||
/>
|
||||
<BlurView
|
||||
intensity={blurIntensity}
|
||||
tint={Platform.OS === "web" ? undefined : "dark"}
|
||||
style={dotsWrapperStyle}
|
||||
pointerEvents="none"
|
||||
>
|
||||
<AnimatedPaginationDot
|
||||
data={carouselItems}
|
||||
scrollValue={scrollY}
|
||||
itemDimension={itemHeight}
|
||||
orientation={AnimatedPaginationDot.orientation.VERTICAL}
|
||||
expandingDotSize={24}
|
||||
inactiveDotOpacity={0.3}
|
||||
containerStyle={styles.dotsContainer}
|
||||
dotStyle={styles.dot}
|
||||
baseDotSize={8}
|
||||
/>
|
||||
</BlurView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -362,8 +405,44 @@ const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
width: "100%",
|
||||
flexDirection: "row",
|
||||
},
|
||||
containerWeb: {
|
||||
paddingRight: 56,
|
||||
},
|
||||
list: {
|
||||
flex: 1,
|
||||
},
|
||||
dotsWrapperBase: {
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
borderRadius: 16,
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 8,
|
||||
overflow: "hidden",
|
||||
backgroundColor: "rgba(18, 18, 18, 0.2)",
|
||||
},
|
||||
dotsWrapperWeb: {
|
||||
position: "absolute",
|
||||
right: 12,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
maxHeight: "75%",
|
||||
alignSelf: "center",
|
||||
},
|
||||
dotsWrapperNative: {
|
||||
marginLeft: 12,
|
||||
alignSelf: "center",
|
||||
},
|
||||
dotsContainer: {
|
||||
flexDirection: "column",
|
||||
},
|
||||
dot: {
|
||||
width: 8,
|
||||
height: 8,
|
||||
marginHorizontal: 0,
|
||||
marginVertical: 6,
|
||||
borderRadius: 999,
|
||||
backgroundColor: "rgba(255,255,255,0.4)",
|
||||
},
|
||||
});
|
||||
|
||||
+44
-68
@@ -9,6 +9,24 @@ import { Palette } from "../styles";
|
||||
import { FONT_FAMILY } from "../styles/Fonts";
|
||||
import { Portal } from "@gorhom/portal";
|
||||
|
||||
const MoreBtn = ({ onPress, children }) => (
|
||||
<Pressable onPress={onPress}>
|
||||
<BlurView
|
||||
intensity={Platform.OS !== "ios" ? 70 : 30}
|
||||
tint="dark"
|
||||
style={{
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 10,
|
||||
backgroundColor: Palette.glass,
|
||||
borderRadius: 12,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</BlurView>
|
||||
</Pressable>
|
||||
);
|
||||
|
||||
const MoreMenu = ({
|
||||
visible = false,
|
||||
top = 0,
|
||||
@@ -26,8 +44,8 @@ const MoreMenu = ({
|
||||
typeof position?.top === "number"
|
||||
? position.top
|
||||
: typeof top === "number"
|
||||
? top
|
||||
: 0;
|
||||
? top
|
||||
: 0;
|
||||
const resolvedRight =
|
||||
typeof position?.right === "number" ? Math.max(position.right, 0) : null;
|
||||
const resolvedLeft =
|
||||
@@ -108,47 +126,7 @@ const MoreMenu = ({
|
||||
>
|
||||
<View style={{ gap: 2 }}>
|
||||
{inPlaylist && (
|
||||
<Pressable onPress={removeFromPlaylist}>
|
||||
<BlurView
|
||||
intensity={Platform.OS !== "ios" ? 10 : 20}
|
||||
style={{
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 10,
|
||||
backgroundColor: Palette.glass,
|
||||
borderRadius: 12,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
// experimentalBlurMethod={
|
||||
// Platform.OS !== "ios" ? "dimezisBlurView" : "none"
|
||||
// }
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 14,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
}}
|
||||
>
|
||||
Supprimer de la playlist
|
||||
</Text>
|
||||
</BlurView>
|
||||
</Pressable>
|
||||
)}
|
||||
|
||||
<Pressable onPress={addToPlaylist}>
|
||||
<BlurView
|
||||
intensity={Platform.OS !== "ios" ? 10 : 20}
|
||||
style={{
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 10,
|
||||
backgroundColor: Palette.glass,
|
||||
borderRadius: 12,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
// experimentalBlurMethod={
|
||||
// Platform.OS !== "ios" ? "dimezisBlurView" : "none"
|
||||
// }
|
||||
>
|
||||
<MoreBtn onPress={removeFromPlaylist}>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 14,
|
||||
@@ -156,14 +134,26 @@ const MoreMenu = ({
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
}}
|
||||
>
|
||||
Ajouter à une playlist
|
||||
Supprimer de la playlist
|
||||
</Text>
|
||||
</BlurView>
|
||||
</Pressable>
|
||||
</MoreBtn>
|
||||
)}
|
||||
|
||||
<MoreBtn onPress={addToPlaylist}>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 14,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
}}
|
||||
>
|
||||
Ajouter à une playlist
|
||||
</Text>
|
||||
</MoreBtn>
|
||||
|
||||
{Array.isArray(extraItems) &&
|
||||
extraItems.map((item, idx) => (
|
||||
<Pressable
|
||||
<MoreBtn
|
||||
key={idx}
|
||||
onPress={() => {
|
||||
try {
|
||||
@@ -173,30 +163,16 @@ const MoreMenu = ({
|
||||
}
|
||||
}}
|
||||
>
|
||||
<BlurView
|
||||
intensity={Platform.OS !== "ios" ? 10 : 20}
|
||||
<Text
|
||||
style={{
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 10,
|
||||
backgroundColor: Palette.glass,
|
||||
borderRadius: 12,
|
||||
overflow: "hidden",
|
||||
fontSize: 14,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
}}
|
||||
// experimentalBlurMethod={
|
||||
// Platform.OS !== "ios" ? "dimezisBlurView" : "none"
|
||||
// }
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 14,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
}}
|
||||
>
|
||||
{item?.label || "Action"}
|
||||
</Text>
|
||||
</BlurView>
|
||||
</Pressable>
|
||||
{item?.label || "Action"}
|
||||
</Text>
|
||||
</MoreBtn>
|
||||
))}
|
||||
</View>
|
||||
</Animated.View>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import {
|
||||
Animated,
|
||||
Dimensions,
|
||||
Easing,
|
||||
FlatList,
|
||||
Image,
|
||||
@@ -88,9 +89,9 @@ const ProjectDropDown = ({
|
||||
);
|
||||
|
||||
const handleModify = useCallback(
|
||||
(project, topPosition) => {
|
||||
(project, anchor) => {
|
||||
if (!project?.id) return;
|
||||
onModifyProject?.(project, topPosition);
|
||||
onModifyProject?.(project, anchor);
|
||||
},
|
||||
[onModifyProject],
|
||||
);
|
||||
@@ -261,23 +262,37 @@ const ProjectRow = ({
|
||||
}) => {
|
||||
const rowRef = useRef(null);
|
||||
const [layout, setLayout] = useState(null);
|
||||
const [menuPos, setMenuPos] = useState(0);
|
||||
const [menuPos, setMenuPos] = useState({
|
||||
top: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!layout) return;
|
||||
const top = (layout?.y || 0) + 45;
|
||||
setMenuPos(top);
|
||||
const top = (layout?.y || 0) + (layout?.height || 45);
|
||||
setMenuPos((prev) => ({ ...prev, top }));
|
||||
}, [layout]);
|
||||
|
||||
const onPressMenu = () => {
|
||||
if (!project?.id) return;
|
||||
|
||||
const updateAnchor = (x = 0, y = 0, width = 0, height = 0) => {
|
||||
const windowWidth = Dimensions.get("window").width || 0;
|
||||
const top = (y || 0) + (height || 0) + 8;
|
||||
const left = Math.max(0, x || 0);
|
||||
const right = Math.max(0, windowWidth - (left + (width || 0)));
|
||||
const anchor = { top, right, left, width, height };
|
||||
setMenuPos(anchor);
|
||||
onModify?.(project, anchor);
|
||||
};
|
||||
|
||||
if (rowRef?.current?.measureInWindow) {
|
||||
try {
|
||||
rowRef.current.measureInWindow((x, y) => {
|
||||
const top = (y || 0) + 45;
|
||||
setMenuPos(top);
|
||||
onModify?.(project, top);
|
||||
rowRef.current.measureInWindow((x, y, width, height) => {
|
||||
updateAnchor(x, y, width, height);
|
||||
});
|
||||
return;
|
||||
} catch (_error) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Platform, Text, useWindowDimensions, View } from "react-native";
|
||||
import { Text, useWindowDimensions, View } from "react-native";
|
||||
import { Image } from "expo-image";
|
||||
import { BlurView } from "expo-blur";
|
||||
import { gutters, Palette } from "../../../styles";
|
||||
@@ -7,10 +7,10 @@ import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import FontAwesome from "@expo/vector-icons/FontAwesome";
|
||||
import palette from "../../../styles/Palette";
|
||||
|
||||
export default function PersonaCard({ item, isLock = false, height }) {
|
||||
export default function PersonaCard({ item, index, isLock = false, height }) {
|
||||
const isImageOnLeft = index % 2 === 0;
|
||||
const { height: windowHeight } = useWindowDimensions();
|
||||
const baseHeight = Math.max(height ?? windowHeight, 1);
|
||||
const cardHeight = Platform.OS === "web" ? Math.round(baseHeight) : baseHeight;
|
||||
const cardHeight = Math.max(height ?? windowHeight, 1);
|
||||
|
||||
return (
|
||||
<View
|
||||
@@ -38,6 +38,8 @@ export default function PersonaCard({ item, isLock = false, height }) {
|
||||
tint="dark"
|
||||
style={{
|
||||
borderRadius: 20,
|
||||
borderTopLeftRadius: isImageOnLeft ? 20 : 0,
|
||||
borderTopRightRadius: isImageOnLeft ? 0 : 20,
|
||||
paddingVertical: 20,
|
||||
paddingHorizontal: gutters,
|
||||
overflow: "hidden",
|
||||
@@ -74,6 +76,8 @@ export default function PersonaCard({ item, isLock = false, height }) {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
borderRadius: 20,
|
||||
borderTopLeftRadius: isImageOnLeft ? 20 : 0,
|
||||
borderTopRightRadius: isImageOnLeft ? 0 : 20,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
backgroundColor: "rgba(0,0,0,0.2)",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Text, useWindowDimensions, View } from "react-native";
|
||||
import { Text, useWindowDimensions, View, StyleSheet } from "react-native";
|
||||
import { Image } from "expo-image";
|
||||
import { BlurView } from "expo-blur";
|
||||
import { Palette } from "../../../styles";
|
||||
@@ -44,11 +44,23 @@ export default function PersonaCard({ item, index, isLock = true }) {
|
||||
tint="dark"
|
||||
style={{
|
||||
flex: 1,
|
||||
borderRadius: 20,
|
||||
borderTopLeftRadius: isImageOnLeft ? 0 : 20,
|
||||
borderTopRightRadius: isImageOnLeft ? 20 : 0,
|
||||
borderBottomLeftRadius: isImageOnLeft ? 0 : 20,
|
||||
borderBottomRightRadius: isImageOnLeft ? 20 : 0,
|
||||
paddingHorizontal: 18,
|
||||
paddingVertical: 16,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{isLock && (
|
||||
<View
|
||||
style={{
|
||||
...StyleSheet.absoluteFillObject,
|
||||
backgroundColor: "rgba(0,0,0,0.6)",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<View
|
||||
style={{
|
||||
minHeight: 100,
|
||||
|
||||
Reference in New Issue
Block a user