import React from "react";
import { ActivityIndicator, Pressable, View } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { useColorScheme } from "nativewind";
import Slider from "@react-native-community/slider";
import { Text } from "./text";
import { usePasswordGenerator } from "../hooks/usePasswordGenerator";
export interface PasswordGeneratorProps {
/** Called when the user taps "Use Password" (only shown when `onSelect` is provided). */
onSelect?: (password: string) => void;
/** Hide the copy button (useful in embedded / inline mode). */
hideCopy?: boolean;
}
/**
* UI shell over `utils/password.generatePassword`. Owns length slider,
* character-set toggles, copy-to-clipboard (via shared util with auto-
* clear), and a coarse strength indicator.
*/
export const PasswordGenerator = React.memo(function PasswordGenerator({
onSelect,
hideCopy,
}: PasswordGeneratorProps) {
const {
password,
length,
setLength,
includeUppercase,
setIncludeUppercase,
includeLowercase,
setIncludeLowercase,
includeNumbers,
setIncludeNumbers,
includeSymbols,
setIncludeSymbols,
excludeSimilar,
setExcludeSimilar,
breach,
strength: passwordStrength,
handleGenerate,
handleCopy,
} = usePasswordGenerator();
const { colorScheme } = useColorScheme();
const isDark = colorScheme === "dark";
return (
<>
Generated Password
{passwordStrength.label}
{password || "Press generate to create a password"}
{/* HIBP breach-check status. Fixed height so the layout never shifts. */}
{breach === "checking" ? (
<>
Checking breach database…
>
) : breach === "safe" ? (
<>
Not found in any known breach
>
) : breach === "unverified" ? (
<>
Couldn't check breaches (offline)
>
) : null}
Generate
{!hideCopy && (
Copy
)}
{onSelect && (
onSelect(password)}
disabled={!password}
className="active:scale-98 rounded-lg bg-secondary dark:bg-neutral-800 px-4 py-3"
accessibilityRole="button"
accessibilityLabel="Use password"
accessibilityState={{ disabled: !password }}
>
Use
)}
Options
Password Length
{length}
8
128
setIncludeUppercase((v) => !v)}
isDark={isDark}
/>
setIncludeLowercase((v) => !v)}
isDark={isDark}
/>
setIncludeNumbers((v) => !v)}
isDark={isDark}
/>
setIncludeSymbols((v) => !v)}
isDark={isDark}
/>
setExcludeSimilar((v) => !v)}
isDark={isDark}
/>
>
);
});
export default PasswordGenerator;
interface CharsetCheckboxProps {
label: string;
checked: boolean;
onToggle: () => void;
isDark: boolean;
}
function CharsetCheckbox({ label, checked, onToggle, isDark }: CharsetCheckboxProps) {
return (
{checked && }
{label}
);
}