lightswind
Version:
A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.
88 lines • 5.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PasswordStrengthIndicator = PasswordStrengthIndicator;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const utils_1 = require("@/components/lib/utils");
const input_1 = require("./input");
const label_1 = require("./label");
const lucide_react_1 = require("lucide-react");
// Password strength calculation based on common rules
const calculateStrength = (password) => {
if (!password)
return { score: 0, level: "empty" };
let score = 0;
// Length check
if (password.length > 5)
score += 1;
if (password.length > 8)
score += 1;
// Character variety checks
if (/[A-Z]/.test(password))
score += 1;
if (/[a-z]/.test(password))
score += 1;
if (/[0-9]/.test(password))
score += 1;
if (/[^A-Za-z0-9]/.test(password))
score += 1;
// Determine level based on score
let level = "empty";
if (score === 0)
level = "empty";
else if (score <= 2)
level = "weak";
else if (score <= 4)
level = "medium";
else if (score <= 5)
level = "strong";
else
level = "very-strong";
return { score, level };
};
// Colors for different strength levels
const strengthColors = {
empty: "bg-gray-200",
weak: "bg-red-500",
medium: "bg-orange-500",
strong: "bg-green-500",
"very-strong": "bg-emerald-500",
};
// Text labels for different strength levels
const strengthLabels = {
empty: "Empty",
weak: "Weak",
medium: "Medium",
strong: "Strong",
"very-strong": "Very Strong",
};
function PasswordStrengthIndicator({ value, className, label = "Password", showScore = true, showScoreNumber = false, onChange, onStrengthChange, placeholder = "Enter your password", showVisibilityToggle = true, inputProps, }) {
const [password, setPassword] = (0, react_1.useState)(value || "");
const [showPassword, setShowPassword] = (0, react_1.useState)(false);
const { score, level } = calculateStrength(password);
const inputRef = (0, react_1.useRef)(null);
(0, react_1.useEffect)(() => {
if (onStrengthChange) {
onStrengthChange(level);
}
}, [level, onStrengthChange]);
const handleChange = (e) => {
const newValue = e.target.value;
setPassword(newValue);
if (onChange)
onChange(newValue);
};
const toggleVisibility = () => {
setShowPassword(!showPassword);
// Focus back on input after toggling visibility
setTimeout(() => {
if (inputRef.current)
inputRef.current.focus();
}, 0);
};
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)("space-y-2", className), children: [label && ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center", children: [(0, jsx_runtime_1.jsx)(label_1.Label, { htmlFor: "password", children: label }), showScoreNumber && ((0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-muted-foreground", children: [Math.floor((score / 6) * 10), "/10"] }))] })), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)(input_1.Input, { ref: inputRef, id: "password", type: showPassword ? "text" : "password", value: password, onChange: handleChange, placeholder: placeholder, className: "pr-10", ...inputProps }), showVisibilityToggle && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: toggleVisibility, className: "absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors", "aria-label": showPassword ? "Hide password" : "Show password", children: showPassword ? ((0, jsx_runtime_1.jsx)(lucide_react_1.EyeOff, { className: "h-5 w-5" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.Eye, { className: "h-5 w-5" })) })), password && ((0, jsx_runtime_1.jsx)("div", { className: "absolute right-10 top-1/2 -translate-y-1/2", children: (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("w-6 h-6 rounded-full flex items-center justify-center", level === "weak" ? "bg-red-500" : level === "medium" ? "bg-orange-500" : "bg-green-500"), children: level === "weak" ? ((0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "h-4 w-4 text-white" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "h-4 w-4 text-white" })) }) }))] }), (0, jsx_runtime_1.jsx)("div", { className: "h-1.5 w-full bg-gray-100 rounded-full overflow-hidden flex gap-0.5", children: Array.from({ length: 4 }).map((_, i) => ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("h-full flex-1 rounded-full transition-all duration-300", i < Math.min(Math.ceil(score / 1.5), 4) ? strengthColors[level] : "bg-gray-200") }, i))) }), showScore && level !== "empty" && ((0, jsx_runtime_1.jsx)("p", { className: (0, utils_1.cn)("text-xs transition-colors", level === "weak" ? "text-red-500" :
level === "medium" ? "text-orange-500" :
level === "strong" ? "text-green-500" :
"text-emerald-500"), children: strengthLabels[level] }))] }));
}
//# sourceMappingURL=password-strength-indicator.js.map