Files
claudemesh/packages/ui/mobile/src/components/progress.tsx
Alejandro Gutiérrez d3163a5bff feat(db): mesh data model — meshes, members, invites, audit log
- pgSchema "mesh" with 4 tables isolating the peer mesh domain
- Enums: visibility, transport, tier, role
- audit_log is metadata-only (E2E encryption enforced at broker/client)
- Cascade on mesh delete, soft-delete via archivedAt/revokedAt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 21:19:32 +01:00

95 lines
2.1 KiB
TypeScript

import * as ProgressPrimitive from "@rn-primitives/progress";
import { Platform, View } from "react-native";
import Animated, {
Extrapolation,
interpolate,
useAnimatedStyle,
useDerivedValue,
withSpring,
} from "react-native-reanimated";
import { cn } from "@turbostarter/ui";
function Progress({
className,
value,
indicatorClassName,
...props
}: ProgressPrimitive.RootProps &
React.RefAttributes<ProgressPrimitive.RootRef> & {
indicatorClassName?: string;
}) {
return (
<ProgressPrimitive.Root
className={cn(
"bg-primary/20 relative h-2 w-full overflow-hidden rounded-full",
className,
)}
{...props}
>
<Indicator value={value} className={indicatorClassName} />
</ProgressPrimitive.Root>
);
}
export { Progress };
const Indicator = Platform.select({
web: WebIndicator,
native: NativeIndicator,
default: NullIndicator,
});
interface IndicatorProps {
value: number | undefined | null;
className?: string;
}
function WebIndicator({ value, className }: IndicatorProps) {
if (Platform.OS !== "web") {
return null;
}
return (
<View
className={cn(
"bg-primary h-full w-full flex-1 transition-all",
className,
)}
style={{ transform: `translateX(-${100 - (value ?? 0)}%)` }}
>
<ProgressPrimitive.Indicator className={cn("h-full w-full", className)} />
</View>
);
}
function NativeIndicator({ value, className }: IndicatorProps) {
const progress = useDerivedValue(() => value ?? 0);
const indicator = useAnimatedStyle(() => {
return {
width: withSpring(
`${interpolate(progress.value, [0, 100], [1, 100], Extrapolation.CLAMP)}%`,
{ overshootClamping: true },
),
};
}, [value]);
if (Platform.OS === "web") {
return null;
}
return (
<ProgressPrimitive.Indicator asChild>
<Animated.View
style={indicator}
className={cn("bg-primary h-full", className)}
/>
</ProgressPrimitive.Indicator>
);
}
function NullIndicator(_props: IndicatorProps) {
return null;
}