@heymarco/next-auth
Version:
A complete authentication solution for web applications.
176 lines (175 loc) • 7.43 kB
JavaScript
'use client';
// react:
import {
// react:
default as React,
// hooks:
useRef, } from 'react';
// reusable-ui core:
import {
// react helper hooks:
useEvent, useMergeEvents, } from '@reusable-ui/core'; // a set of reusable-ui packages which are responsible for building any component
// reusable-ui components:
import { ButtonIcon,
// layout-components:
CardBody,
// status-components:
Busy, ModalCard, useDialogMessage, } from '@reusable-ui/components'; // a set of official Reusable-UI components
// internal components:
import {
// react components:
ButtonWithBusy, } from './ButtonWithBusy.js';
import {
// react components:
ButtonWithSignIn, } from './ButtonWithSignIn.js';
import {
// react components:
AlternateSignInSeparator, } from './AlternateSignInSeparator.js';
import { FieldUsernameOrEmail, } from './FieldUsernameOrEmail.js';
import { FieldPassword, } from './FieldPassword.js';
// internals:
import {
// states:
useSignInState, } from './states/signInState.js';
import {
// handlers:
handlePreventSubmit, } from './utilities.js';
export const TabSignIn = (props) => {
// rest props:
const {
// auths:
providers = [],
// components:
signInTitleComponent = React.createElement("h1", null, "Sign In"), usernameOrEmailInputComponent, passwordInputComponent, signInButtonComponent = React.createElement(ButtonWithBusy, { busyType: 'credentials', buttonComponent: React.createElement(ButtonIcon, { icon: 'login' }) }), signInWithButtonComponent = ((oAuthProvider) => React.createElement(ButtonWithBusy, { busyType: oAuthProvider, buttonComponent: React.createElement(ButtonIcon, { icon: oAuthProvider }) })), alternateSignInSeparatorComponent = React.createElement(AlternateSignInSeparator, null), emailValidationDialogComponent = React.createElement(ModalCard, { theme: 'primary', backdropStyle: 'static', inheritEnabled: false }), } = props;
// states:
const {
// states:
isSignInSection, emailVerified,
// fields & validations:
formRef,
// actions:
doSignIn, doSignInWith,
// utilities:
resolveProviderName } = useSignInState();
// handlers:
const signInButtonHandleClickInternal = useEvent((event) => {
// conditions:
if (event.defaultPrevented)
return; // the event was already handled by user => nothing to do
event.preventDefault();
// actions:
doSignIn();
});
const signInButtonHandleClick = useMergeEvents(
// preserves the original `onClick` from `signInButtonComponent`:
signInButtonComponent.props.onClick,
// actions:
signInButtonHandleClickInternal);
// dialogs:
const { showDialog, } = useDialogMessage();
// effects:
const shouldEmailValidationDialogShown = (!!emailValidationDialogComponent // if no <Dialog> defined => nothing to display
&&
(emailVerified === null) // if already verified => no need to display the <Dialog>
);
const shownEmailValidationDialogRef = useRef(null); // initially no <Dialog> was shown
if ((!!shownEmailValidationDialogRef.current) !== shouldEmailValidationDialogShown) { // detect changes
// close prev shown <Dialog> (if any):
shownEmailValidationDialogRef.current?.closeDialog(null);
// show a new <Dialog> (if needed):
if (emailValidationDialogComponent && shouldEmailValidationDialogShown) {
shownEmailValidationDialogRef.current = showDialog(React.cloneElement(emailValidationDialogComponent,
// props:
{
// global stackable:
viewport: emailValidationDialogComponent.props.viewport ?? formRef,
},
// children:
(emailValidationDialogComponent.props.children ?? React.createElement(CardBody, null,
React.createElement("p", null,
React.createElement(Busy, null),
"\u00A0Validating email confirmation token...")))));
} // if
} // if
// jsx:
return (React.createElement("form", {
// refs:
ref: isSignInSection ? formRef : undefined,
// validations:
noValidate: true,
// handlers:
onSubmit: handlePreventSubmit },
React.cloneElement(signInTitleComponent,
// props:
{
// classes:
className: signInTitleComponent.props.className ?? 'signInTitle',
}),
React.createElement(FieldUsernameOrEmail
// states:
, {
// states:
isActiveSection: isSignInSection,
// components:
usernameOrEmailInputComponent: usernameOrEmailInputComponent }),
React.createElement(FieldPassword
// behaviors:
, {
// behaviors:
isPasswordEntry: false,
// states:
isActiveSection: isSignInSection, isActionApplied: false,
// components:
passwordInputComponent: passwordInputComponent, passwordTooltipComponent: null }),
React.cloneElement(signInButtonComponent,
// props:
{
// actions:
type: signInButtonComponent.props.type ?? 'submit',
// classes:
className: signInButtonComponent.props.className ?? 'doSignIn credentials',
// handlers:
onClick: signInButtonHandleClick,
},
// children:
signInButtonComponent.props.children ?? 'Sign In'),
!!providers.length && React.createElement(React.Fragment, null,
React.cloneElement(alternateSignInSeparatorComponent,
// props:
{
// classes:
className: alternateSignInSeparatorComponent.props.className ?? 'signinSeparator',
}),
React.createElement("div", { className: 'signinGroup' }, providers.map((providerType) => {
const signInWithProviderButtonComponent = ((typeof (signInWithButtonComponent) === 'function')
? signInWithButtonComponent(providerType)
: signInWithButtonComponent);
// jsx:
return (React.createElement(ButtonWithSignIn
// identifiers:
, {
// identifiers:
key: providerType,
// auths:
providerType: providerType,
// components:
buttonComponent:
/* <SignInWithProviderButton> */
React.cloneElement(signInWithProviderButtonComponent,
// props:
{
// identifiers:
key: providerType,
// actions:
type: signInWithProviderButtonComponent.props.type ?? 'submit',
// classes:
className: signInWithProviderButtonComponent.props.className ?? `doSignIn ${providerType}`,
},
// children:
signInWithProviderButtonComponent.props.children ?? React.createElement(React.Fragment, null,
"Sign In with ",
resolveProviderName(providerType))),
// handlers:
onSignInWith: doSignInWith }));
})))));
};