Dependency Updates
Step 5: Carousel Migration
This step is required only for apps that use the Carousel component. If your app doesn't use Carousel, skip to Step 6: Testing Updates.
With RN 0.83, the Carousel component moved from the kepler-ui-components package to a separate package in @amazon-devices. If you use Carousel, you need to migrate the component to the new package.
5.1 Detect Carousel usage
grep -rn "import.*Carousel.*from.*kepler-ui-components" src/ --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js"
If no results, proceed to Step 6: Testing Updates.
5.2 Update dependencies
{
"dependencies": {
"@amazon-devices/vega-carousel": "~1.0.0"
}
}
- If Carousel is the only import from
kepler-ui-components, replace the dependency entirely. - If other components are also imported, keep
kepler-ui-componentsand addvega-carouselalongside it.
5.3 Update import statements
// ❌ BEFORE
import { Carousel } from '@amazon-devices/kepler-ui-components';
// ✅ AFTER
import { Carousel, CarouselRenderInfo } from '@amazon-devices/vega-carousel';
5.4 Migrate data access pattern
Carousel V2 replaces the simple data array prop with a dataAdapter pattern for better performance.
// ❌ BEFORE (V1) — simple data array
<Carousel
data={items}
keyProvider={(item, index) => `item-${item.id}`}
renderItem={({ item, index }) => <ItemCard item={item} />}
/>
// ✅ AFTER (V2) — dataAdapter pattern
const getItem = useCallback((index: number) => {
if (index >= 0 && index < items.length) {
return items[index];
}
return undefined;
}, [items]);
const getItemCount = useCallback(() => {
return items.length;
}, [items]);
const getItemKey = useCallback((info: CarouselRenderInfo) => {
return `item-${info.item.id}`;
}, []);
const notifyDataError = useCallback((error: CarouselDataError) => {
return false;
}, []);
<Carousel
dataAdapter={{
getItem,
getItemCount,
getItemKey,
notifyDataError,
}}
renderItem={({ item, index }) => <ItemCard item={item} />}
/>
5.5 Migrate props
Update prop names to the V2 Prop name in the table below.
| V1 Prop | V2 Prop | Notes |
|---|---|---|
data |
dataAdapter |
See Step 5.4 |
keyProvider |
dataAdapter.getItemKey |
Now takes CarouselRenderInfo instead of (item, index) |
rowId (number) |
uniqueId (string) |
Convert number to string |
maxToRenderPerBatch |
renderedItemsCount |
Same functionality, new name |
hasTVPreferredFocus |
hasPreferredFocus |
Now works on any device |
trapFocusOnAxis |
trapSelectionOnOrientation |
Same functionality, new name |
itemPadding |
itemStyle.itemPadding |
Moved into itemStyle object |
itemSelectionExpansion |
itemStyle.selectedItemScaleFactor |
Single uniform scale factor. V1 used separate widthScale and heightScale values, but V2 uses a single uniform scale factor. If your V1 implementation had different width/height scales, use heightScale as the starting point and visually test the result. |
itemScrollDelay |
animationDuration.itemScrollDuration |
Moved into animationDuration object |
focusIndicatorType |
selectionStrategy |
Value mapping: fixed→anchored, natural→natural, pinned→pinned |
pinnedFocusOffset |
pinnedSelectedItemOffset |
Also accepts "start", "center", "end" |
selectionBorderStrategy |
selectionBorder.borderStrategy |
Moved into selectionBorder object |
Remove these deprecated V1 props (no V2 equivalent)
itemDimensionsgetItemForIndexfirstItemOffsetselectionBorder.enabled
5.6 Migrate event handlers
If you used onFocus or onFocusUpdate for tracking the selected carousel item, migrate to onSelectionChanged.
// ❌ BEFORE (V1) — using onFocus to track selection
const [selectedIndex, setSelectedIndex] = useState(0);
<Carousel
onFocus={(index) => setSelectedIndex(index)}
/>
// ✅ AFTER (V2) — using onSelectionChanged
const onSelectionChanged = useCallback((event: CarouselSelectionChangeEvent) => {
const item = items[event.index];
// Your logic here
}, [items]);
<Carousel
onSelectionChanged={onSelectionChanged}
/>
5.7 Complete migration example
// ✅ Complete V2 Carousel implementation
import React, { useCallback } from 'react';
import { Carousel, CarouselRenderInfo, CarouselSelectionChangeEvent } from '@amazon-devices/vega-carousel';
interface MovieItem {
id: string;
title: string;
thumbnail: string;
}
function MovieCarousel({ movies }: { movies: MovieItem[] }) {
const getItem = useCallback((index: number) => {
return index >= 0 && index < movies.length ? movies[index] : undefined;
}, [movies]);
const getItemCount = useCallback(() => movies.length, [movies]);
const getItemKey = useCallback((info: CarouselRenderInfo) => {
return `movie-${info.item.id}`;
}, []);
const notifyDataError = useCallback(() => false, []);
const onSelectionChanged = useCallback((event: CarouselSelectionChangeEvent) => {
console.log('Selected movie:', movies[event.index]?.title);
}, [movies]);
return (
<Carousel
dataAdapter={{ getItem, getItemCount, getItemKey, notifyDataError }}
renderItem={({ item }) => <MovieCard movie={item} />}
uniqueId="movie-carousel"
renderedItemsCount={7}
hasPreferredFocus={true}
selectionStrategy="anchored"
onSelectionChanged={onSelectionChanged}
itemStyle={{
itemPadding: 16,
selectedItemScaleFactor: 1.1,
}}
animationDuration={{
itemScrollDuration: 0.3,
}}
/>
);
}
For the complete property mapping reference, see the Vega Carousel documentation.
Last updated: Jul 09, 2026

