'use client'; import type { ButtonProps, GroupProps, InputProps, StackProps } from '@chakra-ui/react'; import { Box, HStack, IconButton, Input, InputGroup, Stack, mergeRefs, useControllableState } from '@chakra-ui/react'; import * as React from 'react'; import { LuEye, LuEyeOff } from 'react-icons/lu'; export interface PasswordVisibilityProps { defaultVisible?: boolean; visible?: boolean; onVisibleChange?: (visible: boolean) => void; visibilityIcon?: { on: React.ReactNode; off: React.ReactNode }; } export interface PasswordInputProps extends InputProps, PasswordVisibilityProps { rootProps?: GroupProps; } export const PasswordInput = React.forwardRef( function PasswordInput(props, ref) { const { rootProps, defaultVisible, visible: visibleProp, onVisibleChange, visibilityIcon = { on: , off: }, ...rest } = props; const [visible, setVisible] = useControllableState({ value: visibleProp, defaultValue: defaultVisible || false, onChange: onVisibleChange }); const inputRef = React.useRef(null); return ( { if (rest.disabled) return; if (e.button !== 0) return; e.preventDefault(); setVisible(!visible); }} > {visible ? visibilityIcon.off : visibilityIcon.on} } {...rootProps} > ); } ); const VisibilityTrigger = React.forwardRef( function VisibilityTrigger(props, ref) { return ( ); } ); interface PasswordStrengthMeterProps extends StackProps { max?: number; value: number; } export const PasswordStrengthMeter = React.forwardRef( function PasswordStrengthMeter(props, ref) { const { max = 4, value, ...rest } = props; const percent = (value / max) * 100; const { label, colorPalette } = getColorPalette(percent); return ( {Array.from({ length: max }).map((_, index) => ( ))} {label && {label}} ); } ); function getColorPalette(percent: number) { switch (true) { case percent < 33: return { label: 'Low', colorPalette: 'red' }; case percent < 66: return { label: 'Medium', colorPalette: 'orange' }; default: return { label: 'High', colorPalette: 'green' }; } }