Package: @lilith/ui-auth Split from: lilith/ui.git or lilith/build.git Publish workflow: calls lilith/workflows/.forgejo/workflows/publish-npm.yml@main
88 lines
No EOL
4.1 KiB
JavaScript
88 lines
No EOL
4.1 KiB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
/**
|
|
* AuthModal Component
|
|
*
|
|
* Modal wrapper for LoginForm and RegisterForm with tab switching.
|
|
* Provides a complete embedded auth experience without popups.
|
|
*
|
|
* Supports two integration modes:
|
|
* 1. Direct SSO: Provide ssoUrl, forms make fetch calls directly
|
|
* 2. Provider-based: Provide authHandler, integrates with @lilith/auth-provider
|
|
*/
|
|
import { useState, useCallback, useEffect } from 'react';
|
|
import styled from '@lilith/ui-styled-components';
|
|
import { Modal } from '@lilith/ui-feedback';
|
|
import { LoginForm } from './LoginForm';
|
|
import { RegisterForm } from './RegisterForm';
|
|
const ModalContent = styled.div `
|
|
padding: ${(props) => props.theme.spacing.md};
|
|
`;
|
|
const TabContainer = styled.div `
|
|
display: flex;
|
|
margin-bottom: ${(props) => props.theme.spacing.xl};
|
|
border-bottom: 2px solid ${(props) => props.theme.colors.border.default};
|
|
`;
|
|
const Tab = styled.button `
|
|
flex: 1;
|
|
padding: ${(props) => props.theme.spacing.md} ${(props) => props.theme.spacing.lg};
|
|
background: transparent;
|
|
border: none;
|
|
color: ${(props) => props.$active
|
|
? props.theme.colors.primary.main
|
|
: props.theme.colors.text.muted};
|
|
font-size: ${(props) => props.theme.typography.fontSize.base};
|
|
font-weight: ${(props) => props.$active
|
|
? props.theme.typography.fontWeight.semibold
|
|
: props.theme.typography.fontWeight.medium};
|
|
cursor: pointer;
|
|
position: relative;
|
|
transition: color ${(props) => props.theme.transitions.normal};
|
|
|
|
&:hover {
|
|
color: ${(props) => props.theme.colors.primary.main};
|
|
}
|
|
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: -2px;
|
|
left: 0;
|
|
right: 0;
|
|
height: 2px;
|
|
background: ${(props) => props.$active ? props.theme.colors.primary.main : 'transparent'};
|
|
transition: background ${(props) => props.theme.transitions.normal};
|
|
}
|
|
`;
|
|
const FormContainer = styled.div `
|
|
min-height: 400px;
|
|
`;
|
|
export const AuthModal = ({ isOpen, onClose, ssoUrl, authHandler, onSuccess, onError, initialMode = 'login', defaultRole, hideRoleSelector = false, onMfaRequired, maxWidth = '420px', }) => {
|
|
const [mode, setMode] = useState(initialMode);
|
|
// Reset mode when modal opens/closes or initialMode changes
|
|
useEffect(() => {
|
|
if (isOpen) {
|
|
setMode(initialMode);
|
|
}
|
|
}, [isOpen, initialMode]);
|
|
const handleSuccess = useCallback((user, sessionId) => {
|
|
onSuccess(user, sessionId);
|
|
onClose();
|
|
}, [onSuccess, onClose]);
|
|
const handleSwitchToLogin = useCallback(() => {
|
|
setMode('login');
|
|
}, []);
|
|
const handleSwitchToRegister = useCallback(() => {
|
|
setMode('register');
|
|
}, []);
|
|
const handleForgotPassword = useCallback(() => {
|
|
// Open forgot password in new tab (SSO handles this)
|
|
// Only available in direct SSO mode
|
|
if (ssoUrl) {
|
|
window.open(`${ssoUrl}/forgot-password`, '_blank', 'noopener,noreferrer');
|
|
}
|
|
}, [ssoUrl]);
|
|
const modalTitle = mode === 'login' ? 'Welcome Back' : 'Join Us';
|
|
return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, title: modalTitle, maxWidth: maxWidth, children: _jsxs(ModalContent, { children: [_jsxs(TabContainer, { children: [_jsx(Tab, { "$active": mode === 'login', onClick: handleSwitchToLogin, "aria-selected": mode === 'login', role: "tab", children: "Sign In" }), _jsx(Tab, { "$active": mode === 'register', onClick: handleSwitchToRegister, "aria-selected": mode === 'register', role: "tab", children: "Create Account" })] }), _jsx(FormContainer, { children: mode === 'login' ? (_jsx(LoginForm, { ssoUrl: ssoUrl, authHandler: authHandler, onSuccess: handleSuccess, onError: onError, onMfaRequired: onMfaRequired, onSwitchToRegister: handleSwitchToRegister, onForgotPassword: ssoUrl ? handleForgotPassword : undefined, showTitle: false })) : (_jsx(RegisterForm, { ssoUrl: ssoUrl, authHandler: authHandler, onSuccess: handleSuccess, onError: onError, onSwitchToLogin: handleSwitchToLogin, defaultRole: defaultRole, hideRoleSelector: hideRoleSelector, showTitle: false })) })] }) }));
|
|
};
|
|
AuthModal.displayName = 'AuthModal';
|
|
//# sourceMappingURL=AuthModal.js.map
|