import React from "react"; import PropTypes from "prop-types"; import equal from "fast-deep-equal/react"; import InputBlock from "../input-block"; import Link from "../link"; import Text from "../text"; import Tooltip from "../tooltip"; import { PasswordProgress, StyledInput, TooltipStyle, StyledTooltipContainer, StyledTooltipItem, } from "./styled-password-input"; class PasswordInput extends React.Component { constructor(props) { super(props); const { inputValue, inputType, clipActionResource, emailInputName } = props; this.ref = React.createRef(); this.refTooltip = React.createRef(); this.state = { type: inputType, inputValue: inputValue, copyLabel: clipActionResource, disableCopyAction: emailInputName ? false : true, displayTooltip: false, validLength: false, validDigits: false, validCapital: false, validSpecial: false, }; } hideTooltip = () => { this.hideTooltip && this.refTooltip.current.hideTooltip(); }; onBlur = (e) => { e.persist(); this.hideTooltip(); if (this.props.onBlur) this.props.onBlur(e); }; onKeyDown = (e) => { e.persist(); if (this.props.onKeyDown) this.props.onKeyDown(e); }; changeInputType = () => { this.hideTooltip(); const newType = this.state.type === "text" ? "password" : "text"; this.setState({ type: newType, }); }; testStrength = (value) => { const { generatorSpecial, passwordSettings } = this.props; const specSymbols = new RegExp("[" + generatorSpecial + "]"); let capital; let digits; let special; passwordSettings.upperCase ? (capital = /[A-Z]/.test(value)) : (capital = true); passwordSettings.digits ? (digits = /\d/.test(value)) : (digits = true); passwordSettings.specSymbols ? (special = specSymbols.test(value)) : (special = true); return { digits: digits, capital: capital, special: special, length: value.trim().length >= passwordSettings.minLength, }; }; checkPassword = (value) => { const passwordValidation = this.testStrength(value); const progressScore = passwordValidation.digits && passwordValidation.capital && passwordValidation.special && passwordValidation.length; this.props.onValidateInput && this.props.onValidateInput(progressScore, passwordValidation); this.setState({ inputValue: value, validLength: passwordValidation.length, validDigits: passwordValidation.digits, validCapital: passwordValidation.capital, validSpecial: passwordValidation.special, }); }; onChangeAction = (e) => { this.props.onChange && this.props.onChange(e); if (this.props.simpleView) { this.setState({ inputValue: e.target.value, }); return; } this.checkPassword(e.target.value); }; onGeneratePassword = (e) => { if (this.props.isDisabled) return e.preventDefault(); const newPassword = this.getNewPassword(); if (this.state.type !== "text") { this.setState({ type: "text", }); } this.checkPassword(newPassword); this.props.onChange && this.props.onChange({ target: { value: newPassword } }); }; getNewPassword = () => { const { passwordSettings, generatorSpecial } = this.props; const length = passwordSettings.minLength; const string = "abcdefghijklmnopqrstuvwxyz"; const numeric = "0123456789"; const special = generatorSpecial; let password = ""; let character = ""; while (password.length < length) { const a = Math.ceil(string.length * Math.random() * Math.random()); const b = Math.ceil(numeric.length * Math.random() * Math.random()); const c = Math.ceil(special.length * Math.random() * Math.random()); let hold = string.charAt(a); if (passwordSettings.upperCase) { hold = password.length % 2 == 0 ? hold.toUpperCase() : hold; } character += hold; if (passwordSettings.digits) { character += numeric.charAt(b); } if (passwordSettings.specSymbols) { character += special.charAt(c); } password = character; } password = password .split("") .sort(() => 0.5 - Math.random()) .join(""); return password.substr(0, length); }; copyToClipboard = (emailInputName) => { const { clipEmailResource, clipPasswordResource, clipActionResource, clipCopiedResource, isDisabled, onCopyToClipboard, } = this.props; const { disableCopyAction, inputValue } = this.state; if (isDisabled || disableCopyAction) return event.preventDefault(); this.setState({ disableCopyAction: true, copyLabel: clipCopiedResource, }); const textField = document.createElement("textarea"); const emailValue = document.getElementsByName(emailInputName)[0].value; const formattedText = clipEmailResource + emailValue + " | " + clipPasswordResource + inputValue; textField.innerText = formattedText; document.body.appendChild(textField); textField.select(); document.execCommand("copy"); textField.remove(); onCopyToClipboard && onCopyToClipboard(formattedText); setTimeout(() => { this.setState({ disableCopyAction: false, copyLabel: clipActionResource, }); }, 2000); }; shouldComponentUpdate(nextProps, nextState) { return !equal(this.props, nextProps) || !equal(this.state, nextState); } componentDidUpdate(prevProps, prevState) { if ( prevProps.clipActionResource !== this.props.clipActionResource && this.state.copyLabel !== this.props.clipCopiedResource ) { this.setState({ copyLabel: this.props.clipActionResource }); } } renderTextTooltip = (settings, length, digits, capital, special) => { return ( <>