@heymarco/next-auth
Version:
A complete authentication solution for web applications.
127 lines (126 loc) • 5.63 kB
JavaScript
'use client';
// react:
import {
// react:
default as React, } from 'react';
// reusable-ui core:
import {
// react helper hooks:
useMergeRefs, } from '@reusable-ui/core'; // a set of reusable-ui packages which are responsible for building any component
// reusable-ui components:
import { Icon, PasswordInput, ListItem, List, Tooltip, } from '@reusable-ui/components'; // a set of official Reusable-UI components
// internal components:
import {
// react components:
InputWithLabel, } from './InputWithLabel.js';
// internals:
import {
// states:
useSignInState, } from './states/signInState.js';
import {
// utilities:
getValidityTheme, getValidityIcon, } from './utilities.js';
export const FieldPassword = (props) => {
// rest props:
const {
// behaviors:
isPasswordEntry = true,
// states:
isActiveSection, isActionApplied,
// components:
passwordInputComponent = React.createElement(InputWithLabel, { icon: 'lock', inputComponent: React.createElement(PasswordInput, null) }), passwordTooltipComponent = React.createElement(Tooltip, { theme: 'warning', floatingPlacement: 'top' }), passwordValidationListComponent = React.createElement(List, { listStyle: 'flat' }), passwordValidationListItemComponent = React.createElement(ListItem, { size: 'sm', outlined: true }), passwordValidationIconComponent = React.createElement(Icon, { size: 'sm', icon: undefined }), } = props;
// states:
const {
// constraints:
passwordMinLength, passwordMaxLength, passwordHasUppercase, passwordHasLowercase, passwordProhibitedHint,
// states:
isBusy,
// fields & validations:
userInteracted, passwordRef, password, passwordHandlers, passwordFocused, passwordValid, passwordValidLength, passwordValidUppercase, passwordValidLowercase, passwordValidNotProhibited, } = useSignInState();
const specificValidations = {
passwordValidLength,
passwordValidUppercase,
passwordValidLowercase,
passwordValidNotProhibited,
};
// validations:
const passwordValidationMap = {
Length: React.createElement(React.Fragment, null,
"Must be ",
passwordMinLength,
"-",
passwordMaxLength,
" characters."),
Uppercase: !!passwordHasUppercase && React.createElement(React.Fragment, null, "At least one capital letter."),
Lowercase: !!passwordHasLowercase && React.createElement(React.Fragment, null, "At least one non-capital letter."),
// Match : <>Exact match to previous password.</>,
NotProhibited: passwordProhibitedHint,
};
// refs:
const mergedPasswordInputRef = useMergeRefs(
// preserves the original `elmRef` from `passwordInputComponent`:
passwordInputComponent.props.elmRef, (isActiveSection ? passwordRef : undefined));
// jsx:
return (React.createElement(React.Fragment, null,
React.cloneElement(passwordInputComponent,
// props:
{
// refs:
elmRef: mergedPasswordInputRef,
// classes:
className: passwordInputComponent.props.className ?? 'password',
// accessibilities:
placeholder: passwordInputComponent.props.placeholder ?? (isPasswordEntry ? 'New Password' : 'Password'),
// values:
value: passwordInputComponent.props.value ?? password,
// validations:
isValid: passwordInputComponent.props.isValid ?? (passwordValid === true),
required: passwordInputComponent.props.required ?? true,
// formats:
autoComplete: passwordInputComponent.props.autoComplete ?? (isPasswordEntry ? 'new-password' : 'password'),
// handlers:
...passwordHandlers,
}),
!!passwordTooltipComponent && React.cloneElement(passwordTooltipComponent,
// props:
{
// states:
expanded: passwordTooltipComponent.props.expanded ?? (passwordFocused && userInteracted && !isBusy && isActiveSection && !isActionApplied),
// floatable:
floatingOn: passwordTooltipComponent.props.floatingOn ?? passwordRef,
},
// children:
/* <List> */
React.cloneElement(passwordValidationListComponent,
// props:
undefined,
// children:
(passwordValidationListComponent.props.children ?? Object.entries(passwordValidationMap).map(([validationType, text], index) => {
// conditions:
if (!text)
return null; // disabled => ignore
// fn props:
const isValid = specificValidations?.[`passwordValid${validationType}`];
if (isValid === undefined)
return null;
// jsx:
return React.cloneElement(passwordValidationListItemComponent,
// props:
{
// identifiers:
key: passwordValidationListItemComponent.key ?? index,
// variants:
theme: passwordValidationListItemComponent.props.theme ?? getValidityTheme(isValid),
},
// children:
passwordValidationListItemComponent.props.children ?? React.createElement(React.Fragment, null,
React.cloneElement(passwordValidationIconComponent,
// props:
{
// appearances:
icon: passwordValidationIconComponent.props.icon ?? getValidityIcon(isValid),
}),
"\u00A0",
text));
}))))));
};