import type {A11yProps} from '../../types'; import {useEffect, useState} from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; import {Pressable, Text, View} from 'react-native'; import {renderIcon} from '../../helpers/renderIcon'; import type {IconProp} from '../../types'; import {RatingGlyph} from '../glyphs/Glyphs'; type Props = A11yProps & { defaultRating?: number; iconColor?: string; /** Custom icons for selected and unselected steps. Defaults to built-in stars. */ icons?: {full: IconProp; empty: IconProp}; justRating?: boolean; readOnly?: boolean; reviews?: string[]; size?: number; style?: StyleProp; textColor?: string; textSize?: number; onChange?: (value: number) => void; }; const DEFAULT_REVIEWS = ['Terrible', 'Bad', 'Okay', 'Good', 'Great']; export const StarRating = ({ accessibilityLabel, defaultRating = 3, iconColor = '#FFD700', icons, justRating, onChange, readOnly, reviews, size = 35, style, testID, textColor = '#FFD700', textSize = 30, }: Props) => { const [rating, setRating] = useState(defaultRating - 1); const reviewsArray = reviews ?? DEFAULT_REVIEWS; // Derived, so a parent re-render never resets the selection. const review = reviewsArray[rating]; useEffect(() => { setRating(defaultRating - 1); }, [defaultRating]); const handleChange = (index: number) => { setRating(index); onChange?.(index + 1); }; return ( {!justRating && ( {review} )} {reviewsArray.map((_, idx) => ( handleChange(idx)}> {icons ? ( renderIcon(rating >= idx ? icons.full : icons.empty, { size, color: iconColor, }) ) : ( = idx ? 'full' : 'empty'} size={size} color={iconColor} /> )} ))} ); };