- 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>
95 lines
2.1 KiB
TypeScript
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;
|
|
}
|