feat: pouch
This commit is contained in:
+589
-60
@@ -1,9 +1,19 @@
|
||||
import { BlurView } from "expo-blur";
|
||||
import { Image as ExpoImage } from "expo-image";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { ActivityIndicator, Text, View } from "react-native";
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Image,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
View,
|
||||
} from "react-native";
|
||||
import useMinuit from "react-native-minuit/src/hooks/useMinuit.js";
|
||||
import { background, icons } from "../../assets";
|
||||
import alert from "../../components/Alert";
|
||||
import AppCheckbox from "../../components/AppCheckbox";
|
||||
import BorderGradientButton from "../../components/BorderGradientButton";
|
||||
import GradientButton from "../../components/GradientButton";
|
||||
import MusicLandHeader from "../../components/MusicLandHeader";
|
||||
@@ -15,27 +25,69 @@ import { Routes } from "../../navigation";
|
||||
import { goBack, navigate } from "../../navigation/NavigationService";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
import { gutters, Palette, Style } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import { getStageAction } from "../../utils/projectStages";
|
||||
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
|
||||
import CustomInput from "../Writing/components/CustomInput";
|
||||
|
||||
const COVER_STYLE_PRESETS = [
|
||||
"Néo-Néon / Cyberpunk",
|
||||
"Photographie Minimaliste & Éditoriale",
|
||||
"Illustration & Collage Surréaliste",
|
||||
"Anti-Design / Maximalisme (Tendance Actuelle)",
|
||||
];
|
||||
|
||||
const PouchReady = () => {
|
||||
const { selectedProjectId, selectedProject, updateProjectData } = useUser();
|
||||
const { setIsLoading } = useMinuit();
|
||||
const isGenerating = selectedProject?.coverStatus === "GENERATING";
|
||||
const coverOptions = Array.isArray(selectedProject?.cover?.options)
|
||||
? selectedProject.cover.options
|
||||
: [];
|
||||
const coverOptions = useMemo(() => {
|
||||
if (!Array.isArray(selectedProject?.cover?.options)) {
|
||||
return [];
|
||||
}
|
||||
return selectedProject.cover.options.filter(Boolean);
|
||||
}, [selectedProject?.cover?.options]);
|
||||
const hasGeneratedOptions = coverOptions.length > 0;
|
||||
const selectedOptionId = selectedProject?.cover?.selectedOptionId || null;
|
||||
const selectedOption = useMemo(() => {
|
||||
if (!coverOptions.length) {
|
||||
return null;
|
||||
}
|
||||
const found = coverOptions.find((option) => option?.id === selectedOptionId);
|
||||
return found || coverOptions[0] || null;
|
||||
}, [coverOptions, selectedOptionId]);
|
||||
const coverBackgroundMessage = isWeb
|
||||
? loaderMessages.pouchReadyGenerationWeb
|
||||
: "";
|
||||
|
||||
const [coverStyle, setCoverStyle] = useState(
|
||||
selectedProject?.coverStyle || ""
|
||||
const [styleMode, setStyleMode] = useState("preset");
|
||||
const [selectedPresetStyle, setSelectedPresetStyle] = useState(
|
||||
COVER_STYLE_PRESETS[0]
|
||||
);
|
||||
const [customStyle, setCustomStyle] = useState("");
|
||||
const [isPresetDropdownOpen, setIsPresetDropdownOpen] = useState(false);
|
||||
const [isSelecting, setIsSelecting] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setCoverStyle(selectedProject?.coverStyle || "");
|
||||
const projectStyle = (selectedProject?.coverStyle || "").trim();
|
||||
const isPresetStyle = COVER_STYLE_PRESETS.includes(projectStyle);
|
||||
|
||||
if (!projectStyle) {
|
||||
setStyleMode("preset");
|
||||
setSelectedPresetStyle(COVER_STYLE_PRESETS[0]);
|
||||
setCustomStyle("");
|
||||
setIsPresetDropdownOpen(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPresetStyle) {
|
||||
setStyleMode("preset");
|
||||
setSelectedPresetStyle(projectStyle);
|
||||
setCustomStyle("");
|
||||
} else {
|
||||
setStyleMode("custom");
|
||||
setCustomStyle(projectStyle);
|
||||
}
|
||||
setIsPresetDropdownOpen(false);
|
||||
}, [selectedProject?.coverStyle]);
|
||||
|
||||
const generateCover = useCallback(
|
||||
@@ -75,7 +127,9 @@ const PouchReady = () => {
|
||||
);
|
||||
|
||||
const requestCoverGeneration = useCallback(() => {
|
||||
const trimmedStyle = (coverStyle || "").trim();
|
||||
const selectedStyle =
|
||||
styleMode === "preset" ? selectedPresetStyle : customStyle;
|
||||
const trimmedStyle = (selectedStyle || "").trim();
|
||||
if (!trimmedStyle) {
|
||||
alert("Attention", "Merci de renseigner un style pour la pochette.", [
|
||||
{ text: "OK" },
|
||||
@@ -92,17 +146,16 @@ const PouchReady = () => {
|
||||
onPress: () => generateCover(trimmedStyle),
|
||||
},
|
||||
]);
|
||||
}, [coverStyle, generateCover]);
|
||||
|
||||
const validateCover = () => {
|
||||
navigate(Routes.ValidateCover);
|
||||
};
|
||||
}, [customStyle, generateCover, selectedPresetStyle, styleMode]);
|
||||
|
||||
const coverPreviewUrl =
|
||||
selectedProject?.cover?.result ||
|
||||
selectedProject?.cover?.generatedBackground ||
|
||||
null;
|
||||
|
||||
const shouldShowStylePanel =
|
||||
!isGenerating && !hasGeneratedOptions && !coverPreviewUrl;
|
||||
|
||||
const displayOptions = hasGeneratedOptions
|
||||
? coverOptions
|
||||
: coverPreviewUrl
|
||||
@@ -115,10 +168,120 @@ const PouchReady = () => {
|
||||
]
|
||||
: [];
|
||||
|
||||
const handleSelectOption = useCallback(
|
||||
async (option) => {
|
||||
if (
|
||||
!option ||
|
||||
option?.id === selectedOptionId ||
|
||||
isSelecting ||
|
||||
!option?.id
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const existingCover = selectedProject?.cover || {};
|
||||
const finalUrl = option.finalUrl || option.generatedUrl || null;
|
||||
setIsSelecting(true);
|
||||
try {
|
||||
await updateProjectData({
|
||||
cover: {
|
||||
...existingCover,
|
||||
options: coverOptions,
|
||||
selectedOptionId: option.id,
|
||||
result: finalUrl,
|
||||
generatedBackground: option.generatedUrl || option.finalUrl || null,
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("PouchReady: unable to select cover", e?.message);
|
||||
} finally {
|
||||
setIsSelecting(false);
|
||||
}
|
||||
},
|
||||
[
|
||||
coverOptions,
|
||||
isSelecting,
|
||||
selectedOptionId,
|
||||
selectedProject?.cover,
|
||||
updateProjectData,
|
||||
]
|
||||
);
|
||||
|
||||
const onValidatePicture = useCallback(async () => {
|
||||
if (!selectedOption) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await setIsLoading(true);
|
||||
const existingCover = selectedProject?.cover || {};
|
||||
const finalUrl =
|
||||
selectedOption.finalUrl || selectedOption.generatedUrl || null;
|
||||
const nextCoverData = {
|
||||
...existingCover,
|
||||
options: coverOptions,
|
||||
selectedOptionId: selectedOption.id,
|
||||
result: finalUrl,
|
||||
generatedBackground:
|
||||
selectedOption.generatedUrl || selectedOption.finalUrl || null,
|
||||
};
|
||||
await updateProjectData({
|
||||
cover: nextCoverData,
|
||||
coverUrl: finalUrl,
|
||||
});
|
||||
const projectForStage = {
|
||||
...selectedProject,
|
||||
cover: nextCoverData,
|
||||
coverUrl: finalUrl,
|
||||
};
|
||||
const playbackStage = getStageAction("director", projectForStage);
|
||||
await setIsLoading(false);
|
||||
alert(
|
||||
"Malik",
|
||||
"Super ! Ta pochette est validée. Tu peux retourner à l'accueil ou continuer avec John pour produire ton playback.",
|
||||
[
|
||||
{
|
||||
text: "Retour à l'accueil",
|
||||
style: "cancel",
|
||||
onPress: () => navigate(Routes.Home),
|
||||
},
|
||||
{
|
||||
text: "Continuer avec John",
|
||||
onPress: () => {
|
||||
const targetRoute = playbackStage?.route || Routes.Playback;
|
||||
const params =
|
||||
playbackStage?.params || { project: projectForStage };
|
||||
navigate(targetRoute, params);
|
||||
},
|
||||
},
|
||||
]
|
||||
);
|
||||
} catch (e) {
|
||||
console.log("PouchReady: unable to validate cover", e?.message);
|
||||
} finally {
|
||||
await setIsLoading(false);
|
||||
}
|
||||
}, [
|
||||
coverOptions,
|
||||
navigate,
|
||||
selectedOption,
|
||||
selectedProject,
|
||||
setIsLoading,
|
||||
updateProjectData,
|
||||
]);
|
||||
|
||||
const primaryActionTitle = hasGeneratedOptions
|
||||
? "Valider la pochette"
|
||||
: isGenerating
|
||||
? "Veuillez patienter..."
|
||||
: "En attente de la génération";
|
||||
|
||||
const isPrimaryActionDisabled =
|
||||
isGenerating ||
|
||||
(hasGeneratedOptions ? !selectedOption || isSelecting : true);
|
||||
|
||||
return (
|
||||
<Page backgroundImg={background.studioBG2} headerType="NONE">
|
||||
<MusicLandHeader onPressBack={goBack} progress={72} />
|
||||
<View style={{ flex: 1, marginTop: 16 }}>
|
||||
<View style={{ flex: 1, marginTop: 0 }}>
|
||||
<CreateLyricsHeader
|
||||
title={
|
||||
selectedProject?.cover?.backgroundGenerated
|
||||
@@ -143,14 +306,55 @@ const PouchReady = () => {
|
||||
const optionUri =
|
||||
option?.finalUrl || option?.generatedUrl || "";
|
||||
if (!optionUri) return null;
|
||||
if (hasGeneratedOptions) {
|
||||
const isSelected = option?.id === selectedOption?.id;
|
||||
const cardWidthStyle = isWeb
|
||||
? styles.coverOptionCardWeb
|
||||
: styles.coverOptionCardMobile;
|
||||
return (
|
||||
<Pressable
|
||||
key={option?.id || index}
|
||||
onPress={() => handleSelectOption(option)}
|
||||
disabled={isSelecting}
|
||||
style={[
|
||||
styles.coverOptionCard,
|
||||
cardWidthStyle,
|
||||
isSelected ? styles.coverOptionCardSelected : null,
|
||||
isSelecting ? styles.coverOptionCardDisabled : null,
|
||||
]}
|
||||
>
|
||||
<ExpoImage
|
||||
source={{ uri: optionUri }}
|
||||
cachePolicy="memory-disk"
|
||||
priority="high"
|
||||
contentFit="cover"
|
||||
transition={120}
|
||||
style={styles.coverOptionImage}
|
||||
/>
|
||||
<View style={styles.coverOptionBadge}>
|
||||
<Text style={styles.coverOptionBadgeLabel}>
|
||||
{`Option ${index + 1}`}
|
||||
</Text>
|
||||
</View>
|
||||
{isSelected && (
|
||||
<View style={styles.coverOptionSelectedBadge}>
|
||||
<Text style={styles.coverOptionSelectedLabel}>
|
||||
Sélectionnée
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<View
|
||||
key={option?.id || index}
|
||||
style={{
|
||||
width: isWeb ? 280 : "100%",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
}}
|
||||
style={[
|
||||
styles.coverPreviewCard,
|
||||
isWeb
|
||||
? styles.coverPreviewCardWeb
|
||||
: styles.coverPreviewCardMobile,
|
||||
]}
|
||||
>
|
||||
<ExpoImage
|
||||
source={{ uri: optionUri }}
|
||||
@@ -158,38 +362,36 @@ const PouchReady = () => {
|
||||
priority="high"
|
||||
contentFit="cover"
|
||||
transition={120}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: 260,
|
||||
borderRadius: 20,
|
||||
}}
|
||||
style={styles.coverPreviewImage}
|
||||
/>
|
||||
{hasGeneratedOptions && (
|
||||
<Text
|
||||
style={{
|
||||
color: Palette.white,
|
||||
opacity: 0.7,
|
||||
}}
|
||||
>
|
||||
Pochette {index + 1}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<View
|
||||
style={{
|
||||
width: isWeb ? 300 : "100%",
|
||||
height: 300,
|
||||
borderRadius: 20,
|
||||
backgroundColor: "#00000040",
|
||||
alignSelf: "center",
|
||||
...Style.containerCenter,
|
||||
}}
|
||||
>
|
||||
// <View
|
||||
// style={{
|
||||
// width: isWeb ? 300 : "100%",
|
||||
// height: 300,
|
||||
// borderRadius: 20,
|
||||
// backgroundColor: "#00000040",
|
||||
// alignSelf: "center",
|
||||
// ...Style.containerCenter,
|
||||
// }}
|
||||
// >
|
||||
<>
|
||||
{isGenerating && (
|
||||
<View style={{ alignItems: "center", gap: 8 }}>
|
||||
<View
|
||||
style={{
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
width: isWeb ? 300 : "100%",
|
||||
height: 300,
|
||||
borderRadius: 20,
|
||||
backgroundColor: "#00000040",
|
||||
alignSelf: "center",
|
||||
...Style.containerCenter,
|
||||
}}
|
||||
>
|
||||
<ActivityIndicator color={Palette.white} />
|
||||
{isWeb ? (
|
||||
coverBackgroundMessage ? (
|
||||
@@ -218,18 +420,138 @@ const PouchReady = () => {
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</>
|
||||
// </View>
|
||||
)}
|
||||
</View>
|
||||
<CustomInput
|
||||
label="Style de la pochette"
|
||||
placeholder="Exemple : Collage rétro futuriste lumineux"
|
||||
value={coverStyle}
|
||||
setValue={setCoverStyle}
|
||||
multiline={false}
|
||||
height={55}
|
||||
maxLength={120}
|
||||
/>
|
||||
{shouldShowStylePanel && (
|
||||
<BlurView
|
||||
tint="dark"
|
||||
intensity={isWeb ? 40 : 30}
|
||||
style={[styles.stylePanel, isWeb && styles.stylePanelWeb]}
|
||||
>
|
||||
<View style={styles.stylePanelHeader}>
|
||||
<Text style={styles.panelTitle}>Style de la pochette</Text>
|
||||
<Text style={styles.panelSubtitle}>
|
||||
Choisis une ambiance ou écris ton propre brief créatif.
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.modeContainer}>
|
||||
<View
|
||||
style={[
|
||||
styles.modeCard,
|
||||
styleMode === "preset" ? styles.modeCardActive : null,
|
||||
]}
|
||||
>
|
||||
<AppCheckbox
|
||||
label="Choisir un style prédéfini"
|
||||
selected={styleMode === "preset"}
|
||||
onPress={() => {
|
||||
setStyleMode("preset");
|
||||
setIsPresetDropdownOpen(false);
|
||||
if (!selectedPresetStyle) {
|
||||
setSelectedPresetStyle(COVER_STYLE_PRESETS[0]);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
{styleMode === "preset" && (
|
||||
<View style={styles.dropdownArea}>
|
||||
<Pressable
|
||||
style={styles.dropdownTrigger}
|
||||
onPress={() => setIsPresetDropdownOpen((prev) => !prev)}
|
||||
>
|
||||
<Text style={styles.dropdownTriggerLabel} numberOfLines={2}>
|
||||
{selectedPresetStyle}
|
||||
</Text>
|
||||
<Image
|
||||
source={icons.chevronDown}
|
||||
style={[
|
||||
styles.dropdownArrow,
|
||||
isPresetDropdownOpen ? styles.dropdownArrowOpen : null,
|
||||
]}
|
||||
/>
|
||||
</Pressable>
|
||||
{isPresetDropdownOpen && (
|
||||
<View style={styles.dropdownList}>
|
||||
{COVER_STYLE_PRESETS.map((styleOption, index) => {
|
||||
const isActive = selectedPresetStyle === styleOption;
|
||||
const isLast =
|
||||
index === COVER_STYLE_PRESETS.length - 1;
|
||||
return (
|
||||
<Pressable
|
||||
key={styleOption}
|
||||
style={[
|
||||
styles.dropdownOption,
|
||||
!isLast ? styles.dropdownOptionDivider : null,
|
||||
isActive ? styles.dropdownOptionActive : null,
|
||||
]}
|
||||
onPress={() => {
|
||||
setSelectedPresetStyle(styleOption);
|
||||
setIsPresetDropdownOpen(false);
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={[
|
||||
styles.dropdownOptionLabel,
|
||||
isActive
|
||||
? styles.dropdownOptionLabelActive
|
||||
: null,
|
||||
]}
|
||||
>
|
||||
{styleOption}
|
||||
</Text>
|
||||
{isActive && (
|
||||
<Image
|
||||
source={icons.check}
|
||||
style={styles.dropdownOptionIcon}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
)}
|
||||
</Pressable>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
<View style={styles.modeColumn}>
|
||||
<View
|
||||
style={[
|
||||
styles.modeCard,
|
||||
styleMode === "custom" ? styles.modeCardActive : null,
|
||||
]}
|
||||
>
|
||||
<AppCheckbox
|
||||
label="Style personnalisé"
|
||||
selected={styleMode === "custom"}
|
||||
onPress={() => {
|
||||
setStyleMode("custom");
|
||||
setIsPresetDropdownOpen(false);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
{styleMode === "custom" && (
|
||||
<View style={styles.customInputWrapper}>
|
||||
<TextInput
|
||||
placeholder="Exemple : Collage rétro futuriste lumineux"
|
||||
placeholderTextColor={Palette.grayMid}
|
||||
value={customStyle}
|
||||
onChangeText={setCustomStyle}
|
||||
style={styles.customInput}
|
||||
multiline={false}
|
||||
maxLength={120}
|
||||
textAlignVertical="center"
|
||||
autoCapitalize="sentences"
|
||||
autoCorrect
|
||||
selectionColor={Palette.primary}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</BlurView>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@@ -252,9 +574,9 @@ const PouchReady = () => {
|
||||
/>
|
||||
)}
|
||||
<GradientButton
|
||||
title={isGenerating ? "Veuillez patienter..." : "Valider"}
|
||||
disabled={isGenerating || !coverPreviewUrl}
|
||||
onPress={() => validateCover()}
|
||||
title={primaryActionTitle}
|
||||
disabled={isPrimaryActionDisabled}
|
||||
onPress={onValidatePicture}
|
||||
/>
|
||||
</View>
|
||||
</Page>
|
||||
@@ -262,3 +584,210 @@ const PouchReady = () => {
|
||||
};
|
||||
|
||||
export default PouchReady;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
coverOptionCard: {
|
||||
position: "relative",
|
||||
borderRadius: 20,
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.12)",
|
||||
overflow: "hidden",
|
||||
backgroundColor: "rgba(15,12,20,0.4)",
|
||||
},
|
||||
coverOptionCardWeb: {
|
||||
width: 280,
|
||||
maxWidth: 320,
|
||||
},
|
||||
coverOptionCardMobile: {
|
||||
width: "100%",
|
||||
},
|
||||
coverOptionCardSelected: {
|
||||
borderColor: Palette.primary,
|
||||
},
|
||||
coverOptionCardDisabled: {
|
||||
opacity: 0.85,
|
||||
},
|
||||
coverOptionImage: {
|
||||
width: "100%",
|
||||
aspectRatio: 1,
|
||||
},
|
||||
coverOptionBadge: {
|
||||
position: "absolute",
|
||||
top: 12,
|
||||
right: 12,
|
||||
backgroundColor: Palette.transparentBlack,
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 6,
|
||||
borderRadius: 12,
|
||||
},
|
||||
coverOptionBadgeLabel: {
|
||||
color: Palette.white,
|
||||
fontSize: 12,
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
},
|
||||
coverOptionSelectedBadge: {
|
||||
position: "absolute",
|
||||
bottom: 12,
|
||||
left: 12,
|
||||
backgroundColor: Palette.primary,
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 6,
|
||||
borderRadius: 12,
|
||||
},
|
||||
coverOptionSelectedLabel: {
|
||||
color: Palette.white,
|
||||
fontSize: 12,
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
},
|
||||
coverPreviewCard: {
|
||||
alignItems: "center",
|
||||
},
|
||||
coverPreviewCardWeb: {
|
||||
width: 300,
|
||||
},
|
||||
coverPreviewCardMobile: {
|
||||
width: "100%",
|
||||
},
|
||||
coverPreviewImage: {
|
||||
width: "100%",
|
||||
height: 260,
|
||||
borderRadius: 20,
|
||||
},
|
||||
stylePanel: {
|
||||
gap: 20,
|
||||
paddingHorizontal: 18,
|
||||
paddingVertical: 20,
|
||||
borderRadius: 24,
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.08)",
|
||||
backgroundColor: "rgba(15, 12, 20, 0.78)",
|
||||
overflow: "hidden",
|
||||
},
|
||||
stylePanelWeb: {
|
||||
paddingHorizontal: 26,
|
||||
},
|
||||
stylePanelHeader: {
|
||||
gap: 6,
|
||||
},
|
||||
panelTitle: {
|
||||
fontSize: 18,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
},
|
||||
panelSubtitle: {
|
||||
fontSize: 13,
|
||||
color: Palette.gray,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
lineHeight: 18,
|
||||
},
|
||||
modeContainer: {
|
||||
gap: 18,
|
||||
},
|
||||
modeCard: {
|
||||
alignSelf: "stretch",
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 12,
|
||||
borderRadius: 14,
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.1)",
|
||||
backgroundColor: "rgba(15,12,20,0.6)",
|
||||
},
|
||||
modeCardActive: {
|
||||
borderColor: Palette.primary,
|
||||
backgroundColor: "rgba(251,104,168,0.12)",
|
||||
},
|
||||
dropdownArea: {
|
||||
alignSelf: "stretch",
|
||||
gap: 12,
|
||||
},
|
||||
dropdownTrigger: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 14,
|
||||
borderRadius: 16,
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.1)",
|
||||
backgroundColor: "rgba(15,12,20,0.65)",
|
||||
},
|
||||
dropdownTriggerLabel: {
|
||||
flex: 1,
|
||||
fontSize: 15,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterMedium,
|
||||
},
|
||||
dropdownArrow: {
|
||||
width: 16,
|
||||
height: 16,
|
||||
tintColor: Palette.gray,
|
||||
marginLeft: 10,
|
||||
},
|
||||
dropdownArrowOpen: {
|
||||
transform: [
|
||||
{
|
||||
rotate: "180deg",
|
||||
},
|
||||
],
|
||||
},
|
||||
dropdownList: {
|
||||
borderRadius: 16,
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.08)",
|
||||
backgroundColor: "rgba(12,10,18,0.95)",
|
||||
overflow: "hidden",
|
||||
},
|
||||
dropdownOption: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 14,
|
||||
},
|
||||
dropdownOptionDivider: {
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "rgba(255,255,255,0.06)",
|
||||
},
|
||||
dropdownOptionActive: {
|
||||
backgroundColor: "rgba(251,104,168,0.12)",
|
||||
},
|
||||
dropdownOptionLabel: {
|
||||
flex: 1,
|
||||
fontSize: 15,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
},
|
||||
dropdownOptionLabelActive: {
|
||||
color: Palette.primary,
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
},
|
||||
dropdownOptionIcon: {
|
||||
width: 18,
|
||||
height: 18,
|
||||
tintColor: Palette.primary,
|
||||
marginLeft: 12,
|
||||
},
|
||||
modeColumn: {
|
||||
flex: 1,
|
||||
gap: 12,
|
||||
minWidth: 240,
|
||||
},
|
||||
customInputWrapper: {
|
||||
alignSelf: "stretch",
|
||||
borderRadius: 18,
|
||||
padding: 1,
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.1)",
|
||||
backgroundColor: "rgba(15,12,20,0.4)",
|
||||
},
|
||||
customInput: {
|
||||
minHeight: 55,
|
||||
borderRadius: 16,
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 12,
|
||||
fontSize: 15,
|
||||
color: Palette.white,
|
||||
backgroundColor: "rgba(15,12,20,0.85)",
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user