0.0.2 • Published 10 months ago

react-strong-password-input v0.0.2

Weekly downloads
-
License
ISC
Repository
github
Last release
10 months ago

react-strong-password-input

Base Interfaces

This are base props interfaces, that every implementation (correspondingly) receives

Bar

PropertyTypeDefaultDescription
currentLevelnumberundefinedcurrent level for bar to be filled
levelsnumberundefinedamount of levels

Condition

PropertyTypeDefaultDescription
namestringundefinedname of the condition (not label, label isn't neccesary in base interface, but as example it's present in default implementation)
satisfiedbooleanundefinedsimple flag

Container

Only children are required (optional, actually) for the container

Input

PropertyTypeDefaultDescription
valuestringundefinedvalue prop as in controlled input
onChangeReact.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>undefinedonChange event handler

StrongPasswordInput Interfaces

Condition

PropertyTypeDefaultDescription
namestringundefinedname prop
validatorstring => booleanundefinedvalidator function, receives password, returns flag
conditionComponentPropsOmit<ConditionComponentProp, keyof ConditionBaseProps>undefinednon-base props from the current ConditionComponentProp, that will be passed along with base props for this specific condition

SecurityLevel

PropertyTypeDefaultDescription
namestringundefinedname prop
conditionsRequirenumberundefinedhow many conditions are needed for this security level
barComponentPropsOmit<BarComponentProps, keyof BarBaseProps>undefinednon-base props from the current BarComponentProps, that will be passed along with base props for this specific security level

StrongPasswordChangeEvent

PropertyTypeDefaultDescription
securityLevelstringundefinedname of current security level
satisfiedConditionsstring[]undefinedarray of names of satisfied conditions

Main interface of the strong password input. Couldn't find a way to provide default values for the components -_-.

StrongPasswordInput

PropertyTypeDefaultDescription
valuestringundefinedvalue to be passed into input component
showStrengthBar?booleantrueflag to render strength bar
showConditions?booleantrueflag to render conditions
onChange?(event: StrongPasswordChangeEvent) => voidundefinedonChange handler with previously defined change even
securityLevelsSecurityLevel[]undefinedpossible security levels (like invalid, weak, normal, strong...)
conditionsCondition[]undefinedconditions that to be checked upon password change
InputComponentReact.ComponentTypeundefinedinput component to be rendered within compose input
BarComponentReact.ComponentTypeundefinedpassword strength bar component to be rendered within compose input
ConditionComponentReact.ComponentTypeundefinedcondition component to be rendered within conditions container component
ConditionContainerComponentReact.ComponentType<React.PropsWithChildren>undefinedcontainer component that will be used for conditions
StrongPasswordContainerComponentReact.ComponentType<React.PropsWithChildren>undefinedmain container of this compose input
conditionContainerComponentProps?ConditionContainerComponentPropsundefinedadditional props for conditions container
strongPasswordContainerComponentProps?StrongPasswordContainerComponentPropsundefinedadditional props for main container
inputComponentProps?Partial<Omit<InputComponentProps, keyof InputBaseProps>>undefinedadditional props for input component
barComponentProps?Partial<Omit<BarComponentProps, keyof BarBaseProps>>undefinedadditional props for strength bar component
conditionComponentProps?Partial<Omit<ConditionComponentProps, keyof ConditionBaseProps>undefinedadditional props for conditions component

Usage

Example with default components:

import React from "react";
import { BarDefault, InputDefault, ConditionDefault, ContainerDefault, StrongPasswordInput } from "react-strong-password-input";

function Default() {

    return (
        <StrongPasswordInput
            // Couldn't find a way to provide those components as default values
            InputComponent={InputDefault}
            BarComponent={BarDefault}
            ConditionComponent={ConditionDefault}
            ConditionContainerComponent={ContainerDefault}
            StrongPasswordContainerComponent={ContainerDefault}
            // 
            strongPasswordContainerComponentProps={{
                spacing: 1
            }}
            barComponentProps={{
                background: "#f0f0f0"
            }}
            securityLevels={[
                {
                    name: "invalid",
                    conditionsRequired: 0,
                    barComponentProps: {
                        barColor: "grey"
                    }
                },
                {
                    name: "tooWeak",
                    conditionsRequired: 1,
                    barComponentProps: {
                        barColor: "red",
                    }
                },
                {
                    name: "weak",
                    conditionsRequired: 2,
                    barComponentProps: {
                        barColor: "orange",
                    }
                },
                {
                    name: "good",
                    conditionsRequired: 3,
                    barComponentProps: {
                        barColor: "blue",
                    }
                },
                {
                    name: "strong",
                    conditionsRequired: 4,
                    barComponentProps: {
                        barColor: "green",
                    }
                }
            ]}
            conditions={[
                {
                    name: "length5",
                    validator: (password: string) => password.length >= 5,
                    conditionComponentProps: {
                        label: "Minimum length of 5 characters."
                    }
                },
                {
                    name: "1number",
                    validator: (password: string) => /.*[0-9].*/.test(password),
                    conditionComponentProps: {
                        label: "Contains at least 1 number."
                    }
                },
                {
                    name: "1uppercase",
                    validator: (password: string) => /.*[A-Z].*/.test(password),
                    conditionComponentProps: {
                        label: "Contains at least 1 uppercase letter."
                    }
                },
                {
                    name: "1lowercase",
                    validator: (password: string) => /.*[a-z].*/.test(password),
                    conditionComponentProps: {
                        label: "Contains at least 1 lowercase letter."
                    }
                }
            ]}
        />
    );
}

Result: default

Example with MUI

import { useState } from "react";
import { Circle, Done, Visibility, VisibilityOff } from "@mui/icons-material";
import { IconButton, LinearProgress, Stack, SxProps, TextField, TextFieldVariants, Theme, Typography } from "@mui/material";
import { green, grey, red } from "@mui/material/colors";
import { BarBaseProps, ConditionBaseProps, InputBaseProps, StrongPasswordInput } from "react-strong-password-input";

interface SimplePasswordInputProps extends InputBaseProps {
  sx?: SxProps<Theme>,
  variant?: TextFieldVariants,
}

function SimplePasswordInput({ value, onChange, sx, variant }: SimplePasswordInputProps) {
  const [hidden, setHidden] = useState(true);

  const hiddenHandler = () => setHidden(!hidden);

  return (
    <TextField
      value={value}
      onChange={onChange}
      sx={sx}
      variant={variant}
      type={hidden ? "password" : "text"}
      InputProps={{
        endAdornment: <IconButton onClick={hiddenHandler}>
          {hidden
            ? <Visibility />
            : <VisibilityOff />
          }
        </IconButton>
      }}
    />
  );
}

interface LinearBarProps extends BarBaseProps {
  barColor: string,
  background?: string
}

function LinearBar({ background, barColor, levels, currentLevel }: LinearBarProps) {
  const value = (currentLevel / levels) * 100;

  return (
    <Stack direction="row">
      <LinearProgress
        value={value}
        variant="determinate"
        sx={{
          width: "100%",
          background: background,
          "& .MuiLinearProgress-barColorPrimary": {
            backgroundColor: barColor,
          }
        }}
      />
    </Stack>
  );
}

interface SimpleConditionProp extends ConditionBaseProps {
  label: string | React.ReactElement
}

function SimpleCondition({ label, satisfied }: SimpleConditionProp) {
  return (
    <Stack direction="row" spacing={1}>
      {satisfied
        ? <Done fontSize="small" sx={{ color: green[300] }} />
        : <Circle fontSize="small" sx={{ color: red[300] }} />
      }
      {typeof label === "string"
        ? <Typography>{label}</Typography>
        : label
      }
    </Stack>
  );
}

function MUIStrongPassword() {

  return (
    <StrongPasswordInput
      InputComponent={SimplePasswordInput}
      BarComponent={LinearBar}
      ConditionComponent={SimpleCondition}
      ConditionContainerComponent={Stack}
      StrongPasswordContainerComponent={Stack}
      conditionContainerComponentProps={{
        spacing: 2,
        sx: {
          padding: 2,
          background: grey[200],
          borderRadius: 4
        }
      }}
      strongPasswordContainerComponentProps={{
        spacing: 2
      }}
      securityLevels={[
        {
          name: "invalid",
          conditionsRequired: 0,
          barComponentProps: {
            barColor: "grey"
          }
        },
        {
          name: "tooWeak",
          conditionsRequired: 1,
          barComponentProps: {
            barColor: "red"
          }
        },
        {
          name: "weak",
          conditionsRequired: 2,
          barComponentProps: {
            barColor: "orange"
          }
        },
        {
          name: "good",
          conditionsRequired: 3,
          barComponentProps: {
            barColor: "blue"
          }
        },
        {
          name: "strong",
          conditionsRequired: 4,
          barComponentProps: {
            barColor: "green"
          }
        }
      ]}
      conditions={[
        {
          name: "length5",
          validator: (password: string) => password.length >= 5,
          conditionComponentProps: {
            label: "Minimum length of 5 characters."
          }
        },
        {
          name: "1number",
          validator: (password: string) => /.*[0-9].*/.test(password),
          conditionComponentProps: {
            label: "Contains at least 1 number."
          }
        },
        {
          name: "1uppercase",
          validator: (password: string) => /.*[A-Z].*/.test(password),
          conditionComponentProps: {
            label: "Contains at least 1 uppercase letter."
          }
        },
        {
          name: "1lowercase",
          validator: (password: string) => /.*[a-z].*/.test(password),
          conditionComponentProps: {
            label: "Contains at least 1 lowercase letter."
          }
        }
      ]}
    />
  );
}

Result: MUI

0.0.2

10 months ago

0.0.1

10 months ago

1.0.0

11 months ago