// RN-Port von apps/rebreak/app/components/StarRating.vue // Unterstützt fractional values (z.B. 3.7) via width-clipping. import { View, Pressable } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { useState } from 'react'; export type StarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; const sizeMap: Record = { xs: 14, sm: 18, md: 20, lg: 28, xl: 40, }; export interface StarRatingProps { value?: number; max?: number; size?: StarSize; interactive?: boolean; filledColor?: string; emptyColor?: string; onChange?: (value: number) => void; } export function StarRating({ value = 0, max = 5, size = 'md', interactive = false, filledColor = '#facc15', emptyColor = '#e5e7eb', onChange, }: StarRatingProps) { const [hover, setHover] = useState(0); const px = sizeMap[size]; const display = interactive ? hover || value : value; const stars = []; for (let i = 1; i <= max; i++) { const filledRatio = Math.min(Math.max(display - (i - 1), 0), 1); const filledWidth = filledRatio * px; const star = ( {/* Empty star (background) */} {/* Filled star clipped to filledWidth */} {filledRatio > 0 ? ( ) : null} ); if (interactive) { stars.push( onChange?.(i)} onHoverIn={() => setHover(i)} onHoverOut={() => setHover(0)} hitSlop={4} > {star} ); } else { stars.push(star); } } return ( {stars} ); }