@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
1 lines • 29.6 kB
Source Map (JSON)
{"version":3,"file":"magic-link.cjs","sources":["../../../../../src/components/auth/common/magic-link.tsx"],"sourcesContent":["/**\n * @frank-auth/react - Magic Link Component\n *\n * Passwordless authentication component using magic links sent via email.\n * Supports organization customization and various UI states.\n */\n\n\"use client\";\n\nimport { Button, Card, CardBody } from \"@/components/ui\";\nimport type { RadiusT, SizeT } from \"@/types\";\nimport { motion } from \"framer-motion\";\nimport React from \"react\";\nimport { useConfig } from \"../../../hooks/use-config\";\nimport { useMagicLink } from \"../../../hooks/use-magic-link\";\nimport { EmailField } from \"../../forms/email-field\";\nimport { FormWrapper } from \"../../forms/form-wrapper\";\nimport { LoadingSpinner } from \"./loading-spinner\";\n\n// ============================================================================\n// Magic Link Types\n// ============================================================================\n\nexport interface MagicLinkProps {\n\t/**\n\t * Component variant\n\t */\n\tvariant?: \"form\" | \"button\" | \"card\" | \"inline\";\n\n\t/**\n\t * Magic link type\n\t */\n\ttype?: \"sign-in\" | \"sign-up\" | \"verify-email\" | \"password-reset\";\n\n\t/**\n\t * Initial email value\n\t */\n\temail?: string;\n\n\t/**\n\t * Redirect URL after successful authentication\n\t */\n\tredirectUrl?: string;\n\n\t/**\n\t * Organization ID\n\t */\n\torganizationId?: string;\n\n\t/**\n\t * Success callback\n\t */\n\tonSuccess?: (result: any) => void;\n\n\t/**\n\t * Error callback\n\t */\n\tonError?: (error: Error) => void;\n\n\t/**\n\t * Email sent callback\n\t */\n\tonEmailSent?: (email: string) => void;\n\n\t/**\n\t * Custom title\n\t */\n\ttitle?: string;\n\n\t/**\n\t * Custom subtitle\n\t */\n\tsubtitle?: string;\n\n\t/**\n\t * Custom button text\n\t */\n\tbuttonText?: string;\n\n\t/**\n\t * Whether to show form validation\n\t */\n\tshowValidation?: boolean;\n\n\t/**\n\t * Whether to show resend functionality\n\t */\n\tshowResend?: boolean;\n\n\t/**\n\t * Custom className\n\t */\n\tclassName?: string;\n\n\t/**\n\t * Disabled state\n\t */\n\tdisabled?: boolean;\n\n\t/**\n\t * Size variant\n\t */\n\tsize?: SizeT;\n\tradius?: RadiusT;\n\n\t/**\n\t * Card props (for card variant)\n\t */\n\tcardProps?: any;\n\n\t/**\n\t * Button props (for button variant)\n\t */\n\tbuttonProps?: any;\n}\n\n// ============================================================================\n// Magic Link Form Component\n// ============================================================================\n\nfunction MagicLinkForm({\n\ttype = \"sign-in\",\n\temail: initialEmail = \"\",\n\tredirectUrl,\n\torganizationId,\n\tonSuccess,\n\tonError,\n\tonEmailSent,\n\ttitle,\n\tsubtitle,\n\tbuttonText,\n\tshowValidation = true,\n\tshowResend = true,\n\tclassName = \"\",\n\tdisabled = false,\n\tsize = \"md\",\n\tradius = \"md\",\n}: Omit<MagicLinkProps, \"variant\">) {\n\tconst {\n\t\tsendMagicLink,\n\t\tisLoading,\n\t\terror,\n\t\tlastSentEmail,\n\t\tcanResend,\n\t\tresendMagicLink,\n\t\tisValidEmail,\n\t\tclearState,\n\t} = useMagicLink();\n\n\tconst { organizationSettings } = useConfig();\n\tconst [email, setEmail] = React.useState(initialEmail);\n\tconst [emailSent, setEmailSent] = React.useState(false);\n\n\t// Generate default content based on type\n\tconst getDefaultContent = () => {\n\t\tswitch (type) {\n\t\t\tcase \"sign-up\":\n\t\t\t\treturn {\n\t\t\t\t\ttitle: \"Create your account\",\n\t\t\t\t\tsubtitle: \"Enter your email to get started with a magic link\",\n\t\t\t\t\tbuttonText: \"Send magic link\",\n\t\t\t\t};\n\t\t\tcase \"verify-email\":\n\t\t\t\treturn {\n\t\t\t\t\ttitle: \"Verify your email\",\n\t\t\t\t\tsubtitle: \"Click the link in your email to verify your account\",\n\t\t\t\t\tbuttonText: \"Send verification link\",\n\t\t\t\t};\n\t\t\tcase \"password-reset\":\n\t\t\t\treturn {\n\t\t\t\t\ttitle: \"Reset your password\",\n\t\t\t\t\tsubtitle: \"Enter your email to receive a password reset link\",\n\t\t\t\t\tbuttonText: \"Send reset link\",\n\t\t\t\t};\n\t\t\tcase \"sign-in\":\n\t\t\tdefault:\n\t\t\t\treturn {\n\t\t\t\t\ttitle: \"Sign in with magic link\",\n\t\t\t\t\tsubtitle: \"Enter your email to receive a secure sign-in link\",\n\t\t\t\t\tbuttonText: \"Send magic link\",\n\t\t\t\t};\n\t\t}\n\t};\n\n\tconst defaultContent = getDefaultContent();\n\tconst finalTitle = title || defaultContent.title;\n\tconst finalSubtitle = subtitle || defaultContent.subtitle;\n\tconst finalButtonText = buttonText || defaultContent.buttonText;\n\n\t// Handle form submission\n\tconst handleSubmit = React.useCallback(\n\t\tasync (e: React.FormEvent) => {\n\t\t\te.preventDefault();\n\n\t\t\tif (!email || !isValidEmail(email)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await sendMagicLink(email, {\n\t\t\t\t\tredirectUrl,\n\t\t\t\t\torganizationId,\n\t\t\t\t\ttemplate: type,\n\t\t\t\t});\n\n\t\t\t\tif (result.success) {\n\t\t\t\t\tsetEmailSent(true);\n\t\t\t\t\tonEmailSent?.(email);\n\t\t\t\t\tonSuccess?.(result);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconst error =\n\t\t\t\t\terr instanceof Error ? err : new Error(\"Failed to send magic link\");\n\t\t\t\tonError?.(error);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\temail,\n\t\t\tisValidEmail,\n\t\t\tsendMagicLink,\n\t\t\tredirectUrl,\n\t\t\torganizationId,\n\t\t\ttype,\n\t\t\tonEmailSent,\n\t\t\tonSuccess,\n\t\t\tonError,\n\t\t],\n\t);\n\n\t// Handle resend\n\tconst handleResend = React.useCallback(async () => {\n\t\ttry {\n\t\t\tconst result = await resendMagicLink();\n\t\t\tif (result.success) {\n\t\t\t\tonEmailSent?.(email);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst error =\n\t\t\t\terr instanceof Error ? err : new Error(\"Failed to resend magic link\");\n\t\t\tonError?.(error);\n\t\t}\n\t}, [resendMagicLink, email, onEmailSent, onError]);\n\n\t// Handle back to form\n\tconst handleBackToForm = React.useCallback(() => {\n\t\tsetEmailSent(false);\n\t\tclearState();\n\t}, [clearState]);\n\n\t// Email sent state\n\tif (emailSent) {\n\t\treturn (\n\t\t\t<motion.div\n\t\t\t\tinitial={{ opacity: 0, scale: 0.95 }}\n\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\n\t\t\t\tclassName={`text-center space-y-4 ${className}`}\n\t\t\t>\n\t\t\t\t{/* Success Icon */}\n\t\t\t\t<div className=\"mx-auto w-16 h-16 bg-success-100 dark:bg-success-900/30 rounded-full flex items-center justify-center\">\n\t\t\t\t\t<svg\n\t\t\t\t\t\tclassName=\"w-8 h-8 text-success-600 dark:text-success-400\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\td=\"M12 19l9 2-9-18-9 18 9-2zm0 0v-8\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Title */}\n\t\t\t\t<div>\n\t\t\t\t\t<h3 className=\"text-xl font-semibold text-foreground mb-2\">\n\t\t\t\t\t\tCheck your email\n\t\t\t\t\t</h3>\n\t\t\t\t\t<p className=\"text-default-500 text-sm\">\n\t\t\t\t\t\tWe sent a magic link to <strong>{lastSentEmail || email}</strong>\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Instructions */}\n\t\t\t\t<div className=\"bg-default-100 dark:bg-default-800 rounded-lg p-4\">\n\t\t\t\t\t<p className=\"text-sm text-default-600 dark:text-default-400\">\n\t\t\t\t\t\tClick the link in your email to{\" \"}\n\t\t\t\t\t\t{type === \"sign-up\" ? \"create your account\" : \"sign in\"}. The link\n\t\t\t\t\t\twill expire in 15 minutes.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Actions */}\n\t\t\t\t<div className=\"space-y-3\">\n\t\t\t\t\t{showResend && (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t{canResend ? (\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"light\"\n\t\t\t\t\t\t\t\t\tcolor=\"primary\"\n\t\t\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\t\t\tradius={radius}\n\t\t\t\t\t\t\t\t\tonPress={handleResend}\n\t\t\t\t\t\t\t\t\tisLoading={isLoading}\n\t\t\t\t\t\t\t\t\tisDisabled={disabled}\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tResend magic link\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<p className=\"text-sm text-default-500\">\n\t\t\t\t\t\t\t\t\tYou can resend the link in a few seconds\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"light\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tradius={radius}\n\t\t\t\t\t\tonPress={handleBackToForm}\n\t\t\t\t\t\tisDisabled={isLoading}\n\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t>\n\t\t\t\t\t\tUse a different email\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Error Display */}\n\t\t\t\t{error && (\n\t\t\t\t\t<div className=\"text-danger-600 text-sm bg-danger-50 dark:bg-danger-900/20 rounded-lg p-3\">\n\t\t\t\t\t\t{error.message}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</motion.div>\n\t\t);\n\t}\n\n\t// Form state\n\treturn (\n\t\t<form onSubmit={handleSubmit} className={`space-y-4 ${className}`}>\n\t\t\t{/* Header */}\n\t\t\t<div className=\"text-center space-y-2\">\n\t\t\t\t{finalTitle && (\n\t\t\t\t\t<h3 className=\"text-xl font-semibold text-foreground\">\n\t\t\t\t\t\t{finalTitle}\n\t\t\t\t\t</h3>\n\t\t\t\t)}\n\t\t\t\t{finalSubtitle && (\n\t\t\t\t\t<p className=\"text-default-500 text-sm\">{finalSubtitle}</p>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Email Field */}\n\t\t\t<EmailField\n\t\t\t\tname=\"email\"\n\t\t\t\tlabel=\"Email address\"\n\t\t\t\tplaceholder=\"Enter your email\"\n\t\t\t\tvalue={email}\n\t\t\t\tonChange={setEmail}\n\t\t\t\trequired\n\t\t\t\tdisabled={disabled || isLoading}\n\t\t\t\tvalidateFormat={showValidation}\n\t\t\t\tsize={size}\n\t\t\t\tradius={radius}\n\t\t\t\tautoFocus\n\t\t\t/>\n\n\t\t\t{/* Submit Button */}\n\t\t\t<Button\n\t\t\t\ttype=\"submit\"\n\t\t\t\tcolor=\"primary\"\n\t\t\t\tsize={size}\n\t\t\t\tradius={radius}\n\t\t\t\tclassName=\"w-full\"\n\t\t\t\tisLoading={isLoading}\n\t\t\t\tisDisabled={\n\t\t\t\t\tdisabled || !email || (showValidation && !isValidEmail(email))\n\t\t\t\t}\n\t\t\t\tdisabled={\n\t\t\t\t\tdisabled || !email || (showValidation && !isValidEmail(email))\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t{isLoading ? \"Sending...\" : finalButtonText}\n\t\t\t</Button>\n\n\t\t\t{/* Error Display */}\n\t\t\t{error && (\n\t\t\t\t<div className=\"text-danger-600 text-sm bg-danger-50 dark:bg-danger-900/20 rounded-lg p-3\">\n\t\t\t\t\t{error.message}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</form>\n\t);\n}\n\n// ============================================================================\n// Magic Link Button Component\n// ============================================================================\n\nfunction MagicLinkButton({\n\ttype = \"sign-in\",\n\temail: initialEmail = \"\",\n\tredirectUrl,\n\torganizationId,\n\tonSuccess,\n\tonError,\n\tonEmailSent,\n\tbuttonText,\n\tclassName = \"\",\n\tdisabled = false,\n\tsize = \"md\",\n\tradius = \"md\",\n\tbuttonProps = {},\n}: Omit<MagicLinkProps, \"variant\">) {\n\tconst { sendMagicLink, isLoading } = useMagicLink();\n\tconst [showEmailInput, setShowEmailInput] = React.useState(!initialEmail);\n\tconst [email, setEmail] = React.useState(initialEmail);\n\n\tconst getDefaultButtonText = () => {\n\t\tswitch (type) {\n\t\t\tcase \"sign-up\":\n\t\t\t\treturn \"Sign up with magic link\";\n\t\t\tcase \"verify-email\":\n\t\t\t\treturn \"Send verification link\";\n\t\t\tcase \"password-reset\":\n\t\t\t\treturn \"Send reset link\";\n\t\t\tdefault:\n\t\t\t\treturn \"Sign in with magic link\";\n\t\t}\n\t};\n\n\tconst finalButtonText = buttonText || getDefaultButtonText();\n\n\tconst handleClick = React.useCallback(async () => {\n\t\tif (!email) {\n\t\t\tsetShowEmailInput(true);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await sendMagicLink(email, {\n\t\t\t\tredirectUrl,\n\t\t\t\torganizationId,\n\t\t\t\ttemplate: type,\n\t\t\t});\n\n\t\t\tif (result.success) {\n\t\t\t\tonEmailSent?.(email);\n\t\t\t\tonSuccess?.(result);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst error =\n\t\t\t\terr instanceof Error ? err : new Error(\"Failed to send magic link\");\n\t\t\tonError?.(error);\n\t\t}\n\t}, [\n\t\temail,\n\t\tsendMagicLink,\n\t\tredirectUrl,\n\t\torganizationId,\n\t\ttype,\n\t\tonEmailSent,\n\t\tonSuccess,\n\t\tonError,\n\t]);\n\n\tif (showEmailInput && !initialEmail) {\n\t\treturn (\n\t\t\t<div className={`space-y-3 ${className}`}>\n\t\t\t\t<EmailField\n\t\t\t\t\tname=\"email\"\n\t\t\t\t\tlabel=\"Email address\"\n\t\t\t\t\tplaceholder=\"Enter your email\"\n\t\t\t\t\tvalue={email}\n\t\t\t\t\tonChange={setEmail}\n\t\t\t\t\trequired\n\t\t\t\t\tdisabled={disabled || isLoading}\n\t\t\t\t\tsize={size}\n\t\t\t\t\tradius={radius}\n\t\t\t\t\tautoFocus\n\t\t\t\t/>\n\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tcolor=\"primary\"\n\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\tradius={radius}\n\t\t\t\t\t\tonPress={handleClick}\n\t\t\t\t\t\tisLoading={isLoading}\n\t\t\t\t\t\tisDisabled={disabled || !email}\n\t\t\t\t\t\tdisabled={disabled || !email}\n\t\t\t\t\t\tclassName=\"flex-1\"\n\t\t\t\t\t\t{...buttonProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isLoading ? \"Sending...\" : finalButtonText}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"light\"\n\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\tradius={radius}\n\t\t\t\t\t\tonPress={() => setShowEmailInput(false)}\n\t\t\t\t\t\tisDisabled={isLoading}\n\t\t\t\t\t>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Button\n\t\t\tcolor=\"primary\"\n\t\t\tsize={size}\n\t\t\tradius={radius}\n\t\t\tonPress={handleClick}\n\t\t\tisLoading={isLoading}\n\t\t\tisDisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tstartContent={\n\t\t\t\t<svg\n\t\t\t\t\tclassName=\"w-4 h-4\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\td=\"M12 19l9 2-9-18-9 18 9-2zm0 0v-8\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t{...buttonProps}\n\t\t>\n\t\t\t{finalButtonText}\n\t\t</Button>\n\t);\n}\n\n// ============================================================================\n// Main Magic Link Component\n// ============================================================================\n\nexport function MagicLink({\n\tvariant = \"form\",\n\tcardProps = {},\n\tsize = \"md\",\n\tradius = \"md\",\n\t...props\n}: MagicLinkProps) {\n\tconst { components } = useConfig();\n\n\t// Custom component override\n\tconst CustomMagicLink = components.MagicLink;\n\tif (CustomMagicLink) {\n\t\treturn <CustomMagicLink {...{ variant, cardProps, ...props }} />;\n\t}\n\n\t// Render based on variant\n\tswitch (variant) {\n\t\tcase \"button\":\n\t\t\treturn <MagicLinkButton {...props} />;\n\n\t\tcase \"card\":\n\t\t\treturn (\n\t\t\t\t<Card {...cardProps}>\n\t\t\t\t\t<CardBody>\n\t\t\t\t\t\t<MagicLinkForm {...props} />\n\t\t\t\t\t</CardBody>\n\t\t\t\t</Card>\n\t\t\t);\n\n\t\tcase \"inline\":\n\t\t\treturn <MagicLinkForm {...props} />;\n\n\t\tcase \"form\":\n\t\tdefault:\n\t\t\treturn (\n\t\t\t\t<FormWrapper\n\t\t\t\t\ttitle={props.title}\n\t\t\t\t\tsubtitle={props.subtitle}\n\t\t\t\t\tclassName={props.className}\n\t\t\t\t\tshowCard={false}\n\t\t\t\t\tsize={size}\n\t\t\t\t\tradius={radius}\n\t\t\t\t>\n\t\t\t\t\t<MagicLinkForm {...props} />\n\t\t\t\t</FormWrapper>\n\t\t\t);\n\t}\n}\n\n// ============================================================================\n// Magic Link Verification Component\n// ============================================================================\n\nexport interface MagicLinkVerificationProps {\n\t/**\n\t * Success callback\n\t */\n\tonSuccess?: (result: any) => void;\n\n\t/**\n\t * Error callback\n\t */\n\tonError?: (error: Error) => void;\n\n\t/**\n\t * Custom loading component\n\t */\n\tloadingComponent?: React.ReactNode;\n\n\t/**\n\t * Custom error component\n\t */\n\terrorComponent?: React.ComponentType<{ error: Error; retry: () => void }>;\n\n\t/**\n\t * Custom className\n\t */\n\tclassName?: string;\n\n\tsize?: SizeT;\n\tradius?: RadiusT;\n}\n\nexport function MagicLinkVerification({\n\tonSuccess,\n\tonError,\n\tloadingComponent,\n\terrorComponent: ErrorComponent,\n\tclassName = \"\",\n\tsize = \"md\",\n\tradius = \"md\",\n}: MagicLinkVerificationProps) {\n\tconst { verifyFromUrl, isLoading, error } = useMagicLink();\n\tconst [verificationState, setVerificationState] = React.useState<\n\t\t\"verifying\" | \"success\" | \"error\"\n\t>(\"verifying\");\n\tconst [result, setResult] = React.useState<any>(null);\n\n\tReact.useEffect(() => {\n\t\tconst verify = async () => {\n\t\t\ttry {\n\t\t\t\tconst verificationResult = await verifyFromUrl();\n\n\t\t\t\tif (verificationResult.success) {\n\t\t\t\t\tsetVerificationState(\"success\");\n\t\t\t\t\tsetResult(verificationResult);\n\t\t\t\t\tonSuccess?.(verificationResult);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(verificationResult.error || \"Verification failed\");\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconst error =\n\t\t\t\t\terr instanceof Error ? err : new Error(\"Verification failed\");\n\t\t\t\tsetVerificationState(\"error\");\n\t\t\t\tonError?.(error);\n\t\t\t}\n\t\t};\n\n\t\tverify();\n\t}, [verifyFromUrl, onSuccess, onError]);\n\n\tif (verificationState === \"verifying\" || isLoading) {\n\t\treturn (\n\t\t\t<div className={`flex items-center justify-center min-h-64 ${className}`}>\n\t\t\t\t{loadingComponent || (\n\t\t\t\t\t<LoadingSpinner\n\t\t\t\t\t\tvariant=\"pulse\"\n\t\t\t\t\t\tsize=\"lg\"\n\t\t\t\t\t\tshowText\n\t\t\t\t\t\ttext=\"Verifying magic link...\"\n\t\t\t\t\t\tcentered\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (verificationState === \"error\" || error) {\n\t\tconst verificationError = error || new Error(\"Verification failed\");\n\n\t\tif (ErrorComponent) {\n\t\t\treturn (\n\t\t\t\t<ErrorComponent\n\t\t\t\t\terror={verificationError}\n\t\t\t\t\tretry={() => window.location.reload()}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<div className={`text-center space-y-4 ${className}`}>\n\t\t\t\t<div className=\"mx-auto w-16 h-16 bg-danger-100 dark:bg-danger-900/30 rounded-full flex items-center justify-center\">\n\t\t\t\t\t<svg\n\t\t\t\t\t\tclassName=\"w-8 h-8 text-danger-600 dark:text-danger-400\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\td=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.732 16.5c-.77.833.192 2.5 1.732 2.5z\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t</div>\n\n\t\t\t\t<div>\n\t\t\t\t\t<h3 className=\"text-xl font-semibold text-foreground mb-2\">\n\t\t\t\t\t\tVerification Failed\n\t\t\t\t\t</h3>\n\t\t\t\t\t<p className=\"text-default-500 text-sm\">\n\t\t\t\t\t\t{verificationError.message}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t<Button\n\t\t\t\t\tcolor=\"primary\"\n\t\t\t\t\tsize={size}\n\t\t\t\t\tradius={radius}\n\t\t\t\t\tonPress={() => window.location.reload()}\n\t\t\t\t>\n\t\t\t\t\tTry Again\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (verificationState === \"success\") {\n\t\treturn (\n\t\t\t<div className={`text-center space-y-4 ${className}`}>\n\t\t\t\t<div className=\"mx-auto w-16 h-16 bg-success-100 dark:bg-success-900/30 rounded-full flex items-center justify-center\">\n\t\t\t\t\t<svg\n\t\t\t\t\t\tclassName=\"w-8 h-8 text-success-600 dark:text-success-400\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\td=\"M5 13l4 4L19 7\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t</div>\n\n\t\t\t\t<div>\n\t\t\t\t\t<h3 className=\"text-xl font-semibold text-foreground mb-2\">\n\t\t\t\t\t\tSuccess!\n\t\t\t\t\t</h3>\n\t\t\t\t\t<p className=\"text-default-500 text-sm\">\n\t\t\t\t\t\tYou have been successfully authenticated.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t{result?.requiresAdditionalVerification && (\n\t\t\t\t\t<div className=\"text-sm text-warning-600\">\n\t\t\t\t\t\tAdditional verification required. Redirecting...\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn null;\n}\n\n// ============================================================================\n// Export\n// ============================================================================\n\nexport default MagicLink;\n"],"names":["MagicLinkForm","type","initialEmail","redirectUrl","organizationId","onSuccess","onError","onEmailSent","title","subtitle","buttonText","showValidation","showResend","className","disabled","size","radius","sendMagicLink","isLoading","error","lastSentEmail","canResend","resendMagicLink","isValidEmail","clearState","useMagicLink","organizationSettings","useConfig","email","setEmail","React","emailSent","setEmailSent","defaultContent","finalTitle","finalSubtitle","finalButtonText","handleSubmit","e","result","err","handleResend","handleBackToForm","jsxs","motion","jsx","Button","EmailField","MagicLinkButton","buttonProps","showEmailInput","setShowEmailInput","handleClick","MagicLink","variant","cardProps","props","components","CustomMagicLink","Card","CardBody","FormWrapper","MagicLinkVerification","loadingComponent","ErrorComponent","verifyFromUrl","verificationState","setVerificationState","setResult","verificationResult","LoadingSpinner","verificationError","magic_link_default"],"mappings":"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"}