UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

1 lines 17 kB
{"version":3,"file":"sign-up-button.cjs","sources":["../../../../../src/components/auth/sign-up/sign-up-button.tsx"],"sourcesContent":["/**\n * @frank-auth/react - Sign Up Button Component\n *\n * Trigger button for sign-up that can work in navigation or modal mode.\n */\n\n\"use client\";\n\nimport { Button } from \"@/components/ui\";\nimport {\n\tArrowRightIcon,\n\tSparklesIcon,\n\tUserIcon,\n\tUserPlusIcon,\n} from \"@heroicons/react/24/outline\";\nimport React, { useCallback, useState } from \"react\";\n\nimport { useAuth } from \"../../../hooks/use-auth\";\nimport { useConfig } from \"../../../hooks/use-config\";\nimport type { SignUpButtonProps } from \"./index\";\nimport { SignUpModal, useSignUpModal } from \"./sign-up-modal\";\n\n// ============================================================================\n// Sign Up Button Component\n// ============================================================================\n\nexport function SignUpButton({\n\tchildren,\n\tvariant = \"solid\",\n\tcolor = \"primary\",\n\tsize = \"md\",\n\tfullWidth = false,\n\tstartContent,\n\tendContent,\n\tclassName = \"\",\n\tmodalMode = false,\n\tmodalProps = {},\n\thref = \"/auth/sign-up\",\n\tonClick,\n\tonSuccess,\n\tonError,\n\tdisabled = false,\n\tloading = false,\n\tshowAuthenticatedState = true,\n\ticonOnly = false,\n\tredirectAfterSignUp,\n\tautoRedirect = true,\n}: SignUpButtonProps) {\n\tconst { isSignedIn, user, isLoading } = useAuth();\n\tconst { components, features } = useConfig();\n\tconst { isOpen, open, close } = useSignUpModal();\n\n\t// Custom component override\n\tconst CustomSignUpButton = components.SignUpButton;\n\tif (CustomSignUpButton) {\n\t\treturn (\n\t\t\t<CustomSignUpButton\n\t\t\t\t{...{\n\t\t\t\t\tchildren,\n\t\t\t\t\tvariant,\n\t\t\t\t\tcolor,\n\t\t\t\t\tsize,\n\t\t\t\t\tfullWidth,\n\t\t\t\t\tstartContent,\n\t\t\t\t\tendContent,\n\t\t\t\t\tclassName,\n\t\t\t\t\tmodalMode,\n\t\t\t\t\tmodalProps,\n\t\t\t\t\thref,\n\t\t\t\t\tonClick,\n\t\t\t\t\tonSuccess,\n\t\t\t\t\tonError,\n\t\t\t\t\tdisabled,\n\t\t\t\t\tloading,\n\t\t\t\t\tshowAuthenticatedState,\n\t\t\t\t\ticonOnly,\n\t\t\t\t\tredirectAfterSignUp,\n\t\t\t\t\tautoRedirect,\n\t\t\t\t}}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// Check if sign-up is available\n\tif (!features.signUp) {\n\t\treturn null;\n\t}\n\n\t// Handle sign-up success\n\tconst handleSuccess = useCallback(\n\t\t(result: any) => {\n\t\t\tonSuccess?.(result);\n\n\t\t\t// Auto-redirect logic\n\t\t\tif (autoRedirect && redirectAfterSignUp) {\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\twindow.location.href = redirectAfterSignUp;\n\t\t\t\t}, 1000);\n\t\t\t} else if (autoRedirect && result.user) {\n\t\t\t\t// Default redirects based on user type\n\t\t\t\tconst userType = result.user.userType || \"external\";\n\t\t\t\tconst defaultRedirects = {\n\t\t\t\t\tinternal: \"/admin/dashboard\",\n\t\t\t\t\texternal: \"/dashboard\",\n\t\t\t\t\tend_user: \"/app\",\n\t\t\t\t};\n\n\t\t\t\tconst redirectUrl =\n\t\t\t\t\tdefaultRedirects[userType as keyof typeof defaultRedirects] ||\n\t\t\t\t\t\"/dashboard\";\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\twindow.location.href = redirectUrl;\n\t\t\t\t}, 1000);\n\t\t\t}\n\t\t},\n\t\t[onSuccess, autoRedirect, redirectAfterSignUp],\n\t);\n\n\t// Handle button click\n\tconst handleClick = useCallback(() => {\n\t\tif (disabled || loading || isLoading) return;\n\n\t\t// Custom onClick handler\n\t\tif (onClick) {\n\t\t\tonClick();\n\t\t\treturn;\n\t\t}\n\n\t\t// Modal mode\n\t\tif (modalMode) {\n\t\t\topen();\n\t\t\treturn;\n\t\t}\n\n\t\t// Navigation mode\n\t\tif (href) {\n\t\t\twindow.location.href = href;\n\t\t}\n\t}, [disabled, loading, isLoading, onClick, modalMode, open, href]);\n\n\t// Show authenticated state (user already signed up)\n\tif (showAuthenticatedState && isSignedIn && user) {\n\t\treturn (\n\t\t\t<Button\n\t\t\t\tvariant=\"light\"\n\t\t\t\tsize={size}\n\t\t\t\tclassName={`${className} text-success-600`}\n\t\t\t\tstartContent={<UserIcon className=\"w-4 h-4\" />}\n\t\t\t\tisDisabled\n\t\t\t>\n\t\t\t\t{iconOnly\n\t\t\t\t\t? null\n\t\t\t\t\t: `Welcome, ${user.firstName || user.primaryEmailAddress || \"User\"}`}\n\t\t\t</Button>\n\t\t);\n\t}\n\n\t// Default content\n\tconst defaultStartContent =\n\t\tstartContent ||\n\t\t(iconOnly ? (\n\t\t\t<UserPlusIcon className=\"w-4 h-4\" />\n\t\t) : (\n\t\t\t<UserPlusIcon className=\"w-4 h-4\" />\n\t\t));\n\n\tconst buttonContent = children || (iconOnly ? null : \"Sign Up\");\n\n\treturn (\n\t\t<>\n\t\t\t<Button\n\t\t\t\tvariant={variant}\n\t\t\t\tcolor={color}\n\t\t\t\tsize={size}\n\t\t\t\tfullWidth={fullWidth}\n\t\t\t\tstartContent={defaultStartContent}\n\t\t\t\tendContent={endContent}\n\t\t\t\tclassName={className}\n\t\t\t\tonPress={handleClick}\n\t\t\t\tisDisabled={disabled || isLoading}\n\t\t\t\tisLoading={loading || isLoading}\n\t\t\t\tisIconOnly={iconOnly}\n\t\t\t>\n\t\t\t\t{buttonContent}\n\t\t\t</Button>\n\n\t\t\t{/* Modal */}\n\t\t\t{modalMode && (\n\t\t\t\t<SignUpModal\n\t\t\t\t\tisOpen={isOpen}\n\t\t\t\t\tonClose={close}\n\t\t\t\t\tonSuccess={handleSuccess}\n\t\t\t\t\tonError={onError}\n\t\t\t\t\tredirectUrl={redirectAfterSignUp}\n\t\t\t\t\t{...modalProps}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n\n// ============================================================================\n// Sign Up Button Variants\n// ============================================================================\n\n/**\n * Primary Sign Up Button\n */\nexport function PrimarySignUpButton(\n\tprops: Omit<SignUpButtonProps, \"variant\" | \"color\">,\n) {\n\treturn <SignUpButton {...props} variant=\"solid\" color=\"primary\" />;\n}\n\n/**\n * Secondary Sign Up Button\n */\nexport function SecondarySignUpButton(\n\tprops: Omit<SignUpButtonProps, \"variant\" | \"color\">,\n) {\n\treturn <SignUpButton {...props} variant=\"bordered\" color=\"default\" />;\n}\n\n/**\n * Success Sign Up Button (emphasizes positive action)\n */\nexport function SuccessSignUpButton(\n\tprops: Omit<SignUpButtonProps, \"variant\" | \"color\">,\n) {\n\treturn <SignUpButton {...props} variant=\"solid\" color=\"success\" />;\n}\n\n/**\n * Ghost Sign Up Button\n */\nexport function GhostSignUpButton(props: Omit<SignUpButtonProps, \"variant\">) {\n\treturn <SignUpButton {...props} variant=\"ghost\" />;\n}\n\n/**\n * Icon-only Sign Up Button\n */\nexport function IconSignUpButton(props: Omit<SignUpButtonProps, \"iconOnly\">) {\n\treturn <SignUpButton {...props} iconOnly />;\n}\n\n// ============================================================================\n// Modal Sign Up Button\n// ============================================================================\n\n/**\n * Sign Up Button that always opens in modal\n */\nexport function ModalSignUpButton(props: Omit<SignUpButtonProps, \"modalMode\">) {\n\treturn <SignUpButton {...props} modalMode />;\n}\n\n// ============================================================================\n// Specialized Sign Up Buttons\n// ============================================================================\n\n/**\n * Navigation Sign Up Button (for nav bars)\n */\nexport function NavSignUpButton({\n\tclassName = \"\",\n\t...props\n}: SignUpButtonProps) {\n\treturn (\n\t\t<SignUpButton\n\t\t\t{...props}\n\t\t\tvariant=\"ghost\"\n\t\t\tsize=\"sm\"\n\t\t\tclassName={`font-medium ${className}`}\n\t\t\tmodalMode\n\t\t/>\n\t);\n}\n\n/**\n * Header Sign Up Button (for headers)\n */\nexport function HeaderSignUpButton({\n\tclassName = \"\",\n\t...props\n}: SignUpButtonProps) {\n\treturn (\n\t\t<SignUpButton\n\t\t\t{...props}\n\t\t\tvariant=\"solid\"\n\t\t\tcolor=\"primary\"\n\t\t\tsize=\"sm\"\n\t\t\tclassName={`${className}`}\n\t\t\tmodalMode\n\t\t/>\n\t);\n}\n\n/**\n * Hero Sign Up Button (for landing pages)\n */\nexport function HeroSignUpButton({\n\tsize = \"lg\",\n\tclassName = \"\",\n\tchildren,\n\t...props\n}: SignUpButtonProps) {\n\treturn (\n\t\t<SignUpButton\n\t\t\t{...props}\n\t\t\tvariant=\"solid\"\n\t\t\tcolor=\"primary\"\n\t\t\tsize={size}\n\t\t\tclassName={`font-semibold ${className}`}\n\t\t\tendContent={<ArrowRightIcon className=\"w-5 h-5\" />}\n\t\t>\n\t\t\t{children || \"Get Started\"}\n\t\t</SignUpButton>\n\t);\n}\n\n/**\n * Call-to-Action Sign Up Button (premium feel)\n */\nexport function CTASignUpButton({\n\tclassName = \"\",\n\tchildren,\n\tstartContent,\n\t...props\n}: SignUpButtonProps) {\n\treturn (\n\t\t<SignUpButton\n\t\t\t{...props}\n\t\t\tvariant=\"shadow\"\n\t\t\tcolor=\"secondary\"\n\t\t\tsize=\"lg\"\n\t\t\tclassName={`font-semibold shadow-lg hover:shadow-xl transition-shadow ${className}`}\n\t\t\tstartContent={startContent || <SparklesIcon className=\"w-5 h-5\" />}\n\t\t\tendContent={<ArrowRightIcon className=\"w-5 h-5\" />}\n\t\t>\n\t\t\t{children || \"Start Free Trial\"}\n\t\t</SignUpButton>\n\t);\n}\n\n/**\n * Quick Access Sign Up Button (floating action)\n */\nexport function QuickSignUpButton({\n\tclassName = \"\",\n\t...props\n}: SignUpButtonProps) {\n\treturn (\n\t\t<SignUpButton\n\t\t\t{...props}\n\t\t\tvariant=\"shadow\"\n\t\t\tcolor=\"primary\"\n\t\t\ticonOnly\n\t\t\tclassName={`fixed bottom-4 right-4 z-50 rounded-full w-12 h-12 shadow-lg ${className}`}\n\t\t\tmodalMode\n\t\t\tstartContent={<UserPlusIcon className=\"w-6 h-6\" />}\n\t\t/>\n\t);\n}\n\n/**\n * Free Sign Up Button (emphasizes no cost)\n */\nexport function FreeSignUpButton({\n\tchildren,\n\tclassName = \"\",\n\t...props\n}: SignUpButtonProps) {\n\treturn (\n\t\t<SignUpButton\n\t\t\t{...props}\n\t\t\tvariant=\"solid\"\n\t\t\tcolor=\"success\"\n\t\t\tclassName={`${className}`}\n\t\t>\n\t\t\t{children || \"Sign Up Free\"}\n\t\t</SignUpButton>\n\t);\n}\n\n// ============================================================================\n// Organization-specific Sign Up Button\n// ============================================================================\n\nexport interface OrganizationSignUpButtonProps extends SignUpButtonProps {\n\t/**\n\t * Organization ID\n\t */\n\torganizationId?: string;\n\n\t/**\n\t * Organization name (for display)\n\t */\n\torganizationName?: string;\n\n\t/**\n\t * Organization logo\n\t */\n\torganizationLogo?: string;\n\n\t/**\n\t * Invitation token (for invited sign-ups)\n\t */\n\tinvitationToken?: string;\n}\n\nexport function OrganizationSignUpButton({\n\torganizationId,\n\torganizationName,\n\torganizationLogo,\n\tinvitationToken,\n\tchildren,\n\tstartContent,\n\tmodalProps = {},\n\t...props\n}: OrganizationSignUpButtonProps) {\n\tconst content =\n\t\tchildren ||\n\t\t(invitationToken\n\t\t\t? `Accept Invitation`\n\t\t\t: organizationName\n\t\t\t\t? `Join ${organizationName}`\n\t\t\t\t: \"Join Organization\");\n\n\tconst logoContent = organizationLogo ? (\n\t\t<img\n\t\t\tsrc={organizationLogo}\n\t\t\talt={organizationName}\n\t\t\tclassName=\"w-4 h-4 rounded\"\n\t\t/>\n\t) : (\n\t\t<UserPlusIcon className=\"w-4 h-4\" />\n\t);\n\n\treturn (\n\t\t<SignUpButton\n\t\t\t{...props}\n\t\t\tstartContent={startContent || logoContent}\n\t\t\tmodalProps={{\n\t\t\t\t...modalProps,\n\t\t\t\torganizationId,\n\t\t\t\tinvitationToken,\n\t\t\t\ttitle: organizationName\n\t\t\t\t\t? `Join ${organizationName}`\n\t\t\t\t\t: \"Join Organization\",\n\t\t\t\tshowBranding: true,\n\t\t\t}}\n\t\t>\n\t\t\t{content}\n\t\t</SignUpButton>\n\t);\n}\n\n// ============================================================================\n// Multi-step Sign Up Button\n// ============================================================================\n\nexport interface MultiStepSignUpButtonProps extends SignUpButtonProps {\n\t/**\n\t * Steps to show in the sign-up process\n\t */\n\tsteps?: Array<{\n\t\ttitle: string;\n\t\tdescription?: string;\n\t\tfields: string[];\n\t}>;\n\n\t/**\n\t * Current step (for controlled mode)\n\t */\n\tcurrentStep?: number;\n\n\t/**\n\t * Step change callback\n\t */\n\tonStepChange?: (step: number) => void;\n}\n\nexport function MultiStepSignUpButton({\n\tsteps = [\n\t\t{\n\t\t\ttitle: \"Basic Info\",\n\t\t\tdescription: \"Your email and password\",\n\t\t\tfields: [\"email\", \"password\"],\n\t\t},\n\t\t{\n\t\t\ttitle: \"Personal Details\",\n\t\t\tdescription: \"Tell us about yourself\",\n\t\t\tfields: [\"firstName\", \"lastName\"],\n\t\t},\n\t\t{\n\t\t\ttitle: \"Verification\",\n\t\t\tdescription: \"Verify your email\",\n\t\t\tfields: [\"verification\"],\n\t\t},\n\t],\n\tcurrentStep,\n\tonStepChange,\n\tmodalProps = {},\n\t...props\n}: MultiStepSignUpButtonProps) {\n\tconst [internalStep, setInternalStep] = useState(0);\n\n\tconst activeStep = currentStep !== undefined ? currentStep : internalStep;\n\n\tconst handleStepChange = useCallback(\n\t\t(step: number) => {\n\t\t\tif (onStepChange) {\n\t\t\t\tonStepChange(step);\n\t\t\t} else {\n\t\t\t\tsetInternalStep(step);\n\t\t\t}\n\t\t},\n\t\t[onStepChange],\n\t);\n\n\treturn (\n\t\t<SignUpButton\n\t\t\t{...props}\n\t\t\tmodalMode\n\t\t\tmodalProps={{\n\t\t\t\t...modalProps,\n\t\t\t\ttitle: `Step ${activeStep + 1} of ${steps.length}: ${steps[activeStep]?.title}`,\n\t\t\t\tsubtitle: steps[activeStep]?.description,\n\t\t\t}}\n\t\t/>\n\t);\n}\n\n// ============================================================================\n// Trial Sign Up Button\n// ============================================================================\n\nexport interface TrialSignUpButtonProps extends SignUpButtonProps {\n\t/**\n\t * Trial duration\n\t */\n\ttrialDays?: number;\n\n\t/**\n\t * Whether trial requires credit card\n\t */\n\trequiresCreditCard?: boolean;\n}\n\nexport function TrialSignUpButton({\n\ttrialDays = 14,\n\trequiresCreditCard = false,\n\tchildren,\n\tmodalProps = {},\n\t...props\n}: TrialSignUpButtonProps) {\n\tconst trialText = `Start ${trialDays}-Day Free Trial`;\n\tconst subtitle = requiresCreditCard\n\t\t? `No charge for ${trialDays} days, cancel anytime`\n\t\t: `No credit card required`;\n\n\treturn (\n\t\t<SignUpButton\n\t\t\t{...props}\n\t\t\tcolor=\"success\"\n\t\t\tmodalProps={{\n\t\t\t\t...modalProps,\n\t\t\t\ttitle: `Start Your Free Trial`,\n\t\t\t\tsubtitle,\n\t\t\t}}\n\t\t>\n\t\t\t{children || trialText}\n\t\t</SignUpButton>\n\t);\n}\n\n// ============================================================================\n// Export\n// ============================================================================\n\nexport default SignUpButton;\n"],"names":["SignUpButton","children","variant","color","size","fullWidth","startContent","endContent","className","modalMode","modalProps","href","onClick","onSuccess","onError","disabled","loading","showAuthenticatedState","iconOnly","redirectAfterSignUp","autoRedirect","isSignedIn","user","isLoading","useAuth","components","features","useConfig","isOpen","open","close","useSignUpModal","CustomSignUpButton","jsx","handleSuccess","useCallback","result","userType","redirectUrl","handleClick","Button","UserIcon","defaultStartContent","UserPlusIcon","buttonContent","jsxs","Fragment","SignUpModal"],"mappings":"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"}