Your music, beautifully tracked. All yours. (coming soon)
teal.fm
teal-fm
atproto
1import * as React from "react";
2import { Platform, View } from "react-native";
3import Animated, {
4 Extrapolation,
5 interpolate,
6 useAnimatedStyle,
7 useDerivedValue,
8 withSpring,
9} from "react-native-reanimated";
10import * as ProgressPrimitive from "@rn-primitives/progress";
11
12import { cn } from "../../lib/utils";
13
14const Progress = React.forwardRef<
15 ProgressPrimitive.RootRef,
16 ProgressPrimitive.RootProps & {
17 indicatorClassName?: string;
18 }
19>(({ className, value, indicatorClassName, ...props }, ref) => {
20 return (
21 <ProgressPrimitive.Root
22 ref={ref}
23 className={cn(
24 "relative h-4 w-full overflow-hidden rounded-full bg-secondary",
25 className,
26 )}
27 {...props}
28 >
29 <Indicator value={value} className={indicatorClassName} />
30 </ProgressPrimitive.Root>
31 );
32});
33Progress.displayName = ProgressPrimitive.Root.displayName;
34
35export { Progress };
36
37function Indicator({
38 value,
39 className,
40}: {
41 value: number | undefined | null;
42 className?: string;
43}) {
44 const progress = useDerivedValue(() => value ?? 0);
45
46 const indicator = useAnimatedStyle(() => {
47 return {
48 width: withSpring(
49 `${interpolate(progress.value, [0, 100], [1, 100], Extrapolation.CLAMP)}%`,
50 { overshootClamping: true },
51 ),
52 };
53 });
54
55 if (Platform.OS === "web") {
56 return (
57 <View
58 className={cn(
59 "h-full w-full flex-1 bg-primary web:transition-all",
60 className,
61 )}
62 style={{ transform: `translateX(-${100 - (value ?? 0)}%)` }}
63 >
64 <ProgressPrimitive.Indicator
65 className={cn("h-full w-full", className)}
66 />
67 </View>
68 );
69 }
70
71 return (
72 <ProgressPrimitive.Indicator asChild>
73 <Animated.View
74 style={indicator}
75 className={cn("h-full bg-foreground", className)}
76 />
77 </ProgressPrimitive.Indicator>
78 );
79}