selected project slide and create

This commit is contained in:
Thomas Demirdjian
2025-10-01 11:12:59 +02:00
parent 167e62fcfc
commit 75375942b7
4 changed files with 105 additions and 39 deletions
@@ -9,38 +9,41 @@ const STAGE_CARD_CONTENT = [
key: "songwriter",
title: "Nathalie",
description: "Lets write lyrics together !",
image: ai.nathalie,
image: ai.leftIcon,
},
{
key: "beatmaker",
title: "Theo",
description: "Come back, when you'll have lyrics!",
image: ai.theo,
image: ai.rightIcon,
},
{
key: "designer",
title: "Bena",
description: "Come back when you want to generate cover!",
image: ai.bena,
image: ai.leftIcon,
},
{
key: "director",
title: "John",
description: "Come back when your audio is ready!",
image: ai.john,
image: ai.rightIcon,
},
];
const FeatureCarousel = ({
style,
selectedProject,
stageStates: stageStatesProp,
activeIndex,
onActiveIndexChange,
}) => {
const stageStates = useMemo(
() => getCreationStageStates(selectedProject),
[selectedProject],
);
const stageStates = useMemo(() => {
if (stageStatesProp) {
return stageStatesProp;
}
return getCreationStageStates(selectedProject);
}, [stageStatesProp, selectedProject]);
const carouselItems = useMemo(
() =>
@@ -54,11 +57,24 @@ const FeatureCarousel = ({
const itemHeight = Math.max(windowHeight, 1);
const listRef = useRef(null);
const pendingScrollRef = useRef(false);
const activeIndexRef = useRef(activeIndex);
const onActiveIndexChangeRef = useRef(onActiveIndexChange);
useEffect(() => {
activeIndexRef.current = activeIndex;
}, [activeIndex]);
useEffect(() => {
onActiveIndexChangeRef.current = onActiveIndexChange;
}, [onActiveIndexChange]);
const keyExtractor = useCallback((item) => item.key, []);
const renderItem = useCallback(
({ item }) => <PersonaCard item={item} isLock={item.isLocked} />,
({ item, index }) => (
<PersonaCard item={item} index={index} isLock={item.isLocked} />
),
[],
);
@@ -73,18 +89,24 @@ const FeatureCarousel = ({
const viewabilityConfig = useRef({ viewAreaCoveragePercentThreshold: 60 });
const handleViewableItemsChanged = useCallback(
({ viewableItems }) => {
if (!onActiveIndexChange) {
const handleViewableItemsChangedRef = useRef();
if (!handleViewableItemsChangedRef.current) {
handleViewableItemsChangedRef.current = ({ viewableItems }) => {
if (!viewableItems?.length) return;
const firstVisible = viewableItems.find((item) => item?.isViewable);
if (!firstVisible || firstVisible.index == null) return;
if (pendingScrollRef.current) {
if (firstVisible.index === activeIndexRef.current) {
pendingScrollRef.current = false;
}
return;
}
const firstVisible = viewableItems?.[0];
if (firstVisible?.index != null) {
onActiveIndexChange(firstVisible.index);
const callback = onActiveIndexChangeRef.current;
if (callback && firstVisible.index !== activeIndexRef.current) {
callback(firstVisible.index);
}
},
[onActiveIndexChange],
);
};
}
useEffect(() => {
if (
@@ -96,8 +118,10 @@ const FeatureCarousel = ({
return;
}
try {
pendingScrollRef.current = true;
listRef.current.scrollToIndex({ index: activeIndex, animated: true });
} catch (_error) {
pendingScrollRef.current = false;
// Ignore scroll errors when list is not ready yet.
}
}, [activeIndex, carouselItems.length]);
@@ -109,7 +133,7 @@ const FeatureCarousel = ({
data={carouselItems}
keyExtractor={keyExtractor}
renderItem={renderItem}
onViewableItemsChanged={handleViewableItemsChanged}
onViewableItemsChanged={handleViewableItemsChangedRef.current}
viewabilityConfig={viewabilityConfig.current}
getItemLayout={getItemLayout}
showsVerticalScrollIndicator={false}