{"version":3,"file":"sign-up-modal.cjs","sources":["../../../../../src/components/auth/sign-up/sign-up-modal.tsx"],"sourcesContent":["/**\n * @frank-auth/react - Sign Up Modal Component\n *\n * Modal wrapper for sign-up form with customizable overlay and behavior.\n */\n\n\"use client\";\n\nimport { Button, Modal, ModalBody, ModalHeader } from \"@/components/ui\";\nimport { XMarkIcon } from \"@heroicons/react/24/outline\";\nimport React, { useCallback } from \"react\";\n\nimport { useConfig } from \"../../../hooks/use-config\";\nimport type { SignUpModalProps } from \"./index\";\nimport { SignUpForm } from \"./sign-up-form\";\n\n// ============================================================================\n// Sign Up Modal Component\n// ============================================================================\n\nexport function SignUpModal({\n  isOpen = false,\n  onClose,\n  modalSize = \"md\",\n  closeOnBackdropClick = true,\n  closeOnEscape = true,\n  modalClassName = \"\",\n  showCloseButton = true,\n  methods = [\"password\", \"oauth\", \"magic-link\"],\n  email,\n  organizationId,\n  invitationToken,\n  redirectUrl,\n  onSuccess,\n  onError,\n  title,\n  subtitle,\n  size = \"md\",\n  showBranding = true,\n  disabled = false,\n  requireTerms = true,\n  termsUrl = \"/terms\",\n  privacyUrl = \"/privacy\",\n  backdrop = \"blur\",\n  placement = \"center\",\n}: SignUpModalProps) {\n  const { components } = useConfig();\n\n  // Custom component override\n  const CustomSignUpModal = components.SignUpModal;\n  if (CustomSignUpModal) {\n    return (\n      <CustomSignUpModal\n        {...{\n          isOpen,\n          onClose,\n          modalSize,\n          closeOnBackdropClick,\n          closeOnEscape,\n          modalClassName,\n          showCloseButton,\n          methods,\n          email,\n          organizationId,\n          invitationToken,\n          redirectUrl,\n          onSuccess,\n          onError,\n          title,\n          subtitle,\n          size,\n          showBranding,\n          disabled,\n          requireTerms,\n          termsUrl,\n          privacyUrl,\n          backdrop,\n          placement,\n        }}\n      />\n    );\n  }\n\n  // Handle successful sign-up\n  const handleSuccess = useCallback(\n    (result: any) => {\n      onSuccess?.(result);\n\n      // Auto-close modal on success unless redirecting\n      if (!redirectUrl) {\n        setTimeout(() => {\n          onClose?.();\n        }, 2000); // Allow time to see success message\n      }\n    },\n    [onSuccess, onClose, redirectUrl],\n  );\n\n  // Handle modal close\n  const handleClose = useCallback(() => {\n    if (disabled) return;\n    onClose?.();\n  }, [onClose, disabled]);\n\n  // Get modal size mapping\n  const getSizeProps = () => {\n    switch (modalSize) {\n      case \"sm\":\n        return {\n          size: \"sm\" as const,\n          className: \"max-w-sm max-h-[90vh]\",\n          scrollBehavior: \"inside\" as const,\n        };\n      case \"md\":\n        return {\n          size: \"md\" as const,\n          className: \"max-w-md max-h-[90vh]\",\n          scrollBehavior: \"inside\" as const,\n        };\n      case \"lg\":\n        return {\n          size: \"lg\" as const,\n          className: \"max-w-lg max-h-[90vh]\",\n          scrollBehavior: \"inside\" as const,\n        };\n      case \"xl\":\n        return {\n          size: \"xl\" as const,\n          className: \"max-w-xl max-h-[90vh]\",\n          scrollBehavior: \"inside\" as const,\n        };\n      case \"full\":\n        return {\n          size: \"full\" as const,\n          className: \"max-w-full h-full\",\n          scrollBehavior: \"outside\" as const,\n        };\n      default:\n        return {\n          size: \"md\" as const,\n          className: \"max-w-md max-h-[90vh]\",\n          scrollBehavior: \"inside\" as const,\n        };\n    }\n  };\n\n  const sizeProps = getSizeProps();\n\n  return (\n    <Modal\n      isOpen={isOpen}\n      onClose={handleClose}\n      size={sizeProps.size}\n      backdrop={backdrop}\n      placement={placement}\n      scrollBehavior={sizeProps.scrollBehavior}\n      closeButton={false} // We'll handle the close button manually\n      isDismissable={closeOnBackdropClick && !disabled}\n      isKeyboardDismissDisabled={!closeOnEscape || disabled}\n      className={`${modalClassName}`}\n      classNames={{\n        wrapper: \"z-[9999]\",\n        backdrop: \"z-[9998]\",\n        base: `${sizeProps.className}`,\n        body: \"px-0 py-0\",\n      }}\n    >\n      <>\n        {/* Modal Header */}\n        <ModalHeader className=\"flex items-center justify-between px-6 py-4 border-b border-divider\">\n          <div className=\"flex-1\">\n            {title && (\n              <h2 className=\"text-lg font-semibold text-foreground\">{title}</h2>\n            )}\n            {subtitle && (\n              <p className=\"text-sm text-default-500 mt-1\">{subtitle}</p>\n            )}\n          </div>\n\n          {showCloseButton && (\n            <Button\n              isIconOnly\n              variant=\"light\"\n              size=\"sm\"\n              onPress={handleClose}\n              className=\"text-default-400 hover:text-default-600 -mr-2\"\n              isDisabled={disabled}\n            >\n              <XMarkIcon className=\"w-4 h-4\" />\n            </Button>\n          )}\n        </ModalHeader>\n\n        {/* Modal Body */}\n        <ModalBody>\n          <div className=\"px-6 py-6\">\n            <SignUpForm\n              methods={methods}\n              email={email}\n              organizationId={organizationId}\n              invitationToken={invitationToken}\n              redirectUrl={redirectUrl}\n              onSuccess={handleSuccess}\n              onError={onError}\n              title={undefined} // Title is in header\n              subtitle={undefined} // Subtitle is in header\n              size={size}\n              showBranding={showBranding}\n              disabled={disabled}\n              requireTerms={requireTerms}\n              termsUrl={termsUrl}\n              privacyUrl={privacyUrl}\n              variant=\"minimal\"\n              className=\"space-y-4\"\n              showSignInLink={true}\n              autoFocus={true}\n            />\n          </div>\n        </ModalBody>\n      </>\n    </Modal>\n  );\n}\n\n// ============================================================================\n// Sign Up Modal Hook\n// ============================================================================\n\n/**\n * Hook for managing sign-up modal state\n */\nexport function useSignUpModal() {\n  const [isOpen, setIsOpen] = React.useState(false);\n  const [modalData, setModalData] = React.useState<{\n    email?: string;\n    organizationId?: string;\n    invitationToken?: string;\n  }>({});\n\n  const open = useCallback((data?: typeof modalData) => {\n    if (data) {\n      setModalData(data);\n    }\n    setIsOpen(true);\n  }, []);\n\n  const close = useCallback(() => {\n    setIsOpen(false);\n    // Clear data after modal closes\n    setTimeout(() => {\n      setModalData({});\n    }, 300);\n  }, []);\n\n  const toggle = useCallback(() => setIsOpen((prev) => !prev), []);\n\n  return {\n    isOpen,\n    open,\n    close,\n    toggle,\n    setIsOpen,\n    modalData,\n    setModalData,\n  };\n}\n\n// ============================================================================\n// Sign Up Modal with Trigger\n// ============================================================================\n\nexport interface SignUpModalWithTriggerProps extends SignUpModalProps {\n  /**\n   * Trigger element\n   */\n  trigger?: React.ReactElement;\n\n  /**\n   * Trigger props (for default button)\n   */\n  triggerProps?: {\n    children?: React.ReactNode;\n    variant?:\n      | \"solid\"\n      | \"bordered\"\n      | \"light\"\n      | \"flat\"\n      | \"faded\"\n      | \"shadow\"\n      | \"ghost\";\n    color?:\n      | \"default\"\n      | \"primary\"\n      | \"secondary\"\n      | \"success\"\n      | \"warning\"\n      | \"danger\";\n    size?: \"sm\" | \"md\" | \"lg\";\n    fullWidth?: boolean;\n    startContent?: React.ReactNode;\n    endContent?: React.ReactNode;\n    className?: string;\n    disabled?: boolean;\n  };\n\n  /**\n   * Pre-fill modal with data when opened\n   */\n  modalData?: {\n    email?: string;\n    organizationId?: string;\n    invitationToken?: string;\n  };\n}\n\n/**\n * Sign Up Modal with built-in trigger button\n */\nexport function SignUpModalWithTrigger({\n  trigger,\n  triggerProps = {},\n  modalData,\n  ...modalProps\n}: SignUpModalWithTriggerProps) {\n  const { isOpen, open, close } = useSignUpModal();\n\n  // Default trigger button\n  const defaultTrigger = (\n    <Button\n      variant={triggerProps.variant || \"solid\"}\n      color={triggerProps.color || \"primary\"}\n      size={triggerProps.size || \"md\"}\n      fullWidth={triggerProps.fullWidth}\n      startContent={triggerProps.startContent}\n      endContent={triggerProps.endContent}\n      className={triggerProps.className}\n      isDisabled={triggerProps.disabled}\n      onPress={() => open(modalData)}\n    >\n      {triggerProps.children || \"Sign Up\"}\n    </Button>\n  );\n\n  // Use custom trigger or default\n  const triggerElement = trigger\n    ? React.cloneElement(trigger, {\n        onClick: (e: React.MouseEvent) => {\n          trigger.props.onClick?.(e);\n          open(modalData);\n        },\n      })\n    : defaultTrigger;\n\n  return (\n    <>\n      {triggerElement}\n      <SignUpModal\n        {...modalProps}\n        isOpen={isOpen}\n        onClose={close}\n        email={modalData?.email || modalProps.email}\n        organizationId={modalData?.organizationId || modalProps.organizationId}\n        invitationToken={\n          modalData?.invitationToken || modalProps.invitationToken\n        }\n      />\n    </>\n  );\n}\n\n// ============================================================================\n// Specialized Modal Variants\n// ============================================================================\n\n/**\n * Compact Sign Up Modal\n */\nexport function CompactSignUpModal(props: SignUpModalProps) {\n  return <SignUpModal {...props} modalSize=\"sm\" size=\"sm\" />;\n}\n\n/**\n * Large Sign Up Modal\n */\nexport function LargeSignUpModal(props: SignUpModalProps) {\n  return <SignUpModal {...props} modalSize=\"lg\" size=\"lg\" />;\n}\n\n/**\n * Full Screen Sign Up Modal\n */\nexport function FullScreenSignUpModal(props: SignUpModalProps) {\n  return (\n    <SignUpModal {...props} modalSize=\"full\" size=\"lg\" backdrop=\"opaque\" />\n  );\n}\n\n/**\n * Organization Invitation Modal\n */\nexport interface OrganizationInviteModalProps\n  extends Omit<SignUpModalProps, \"invitationToken\" | \"organizationId\"> {\n  /**\n   * Invitation token\n   */\n  invitationToken: string;\n\n  /**\n   * Whether modal opens automatically\n   */\n  autoOpen?: boolean;\n}\n\nexport function OrganizationInviteModal({\n  invitationToken,\n  autoOpen = false,\n  title,\n  subtitle,\n  ...props\n}: OrganizationInviteModalProps) {\n  const [isOpen, setIsOpen] = React.useState(autoOpen);\n\n  // Parse invitation token to get organization info\n  const invitationData = React.useMemo(() => {\n    try {\n      const decoded = atob(invitationToken);\n      return JSON.parse(decoded);\n    } catch {\n      return null;\n    }\n  }, [invitationToken]);\n\n  const finalTitle =\n    title ||\n    (invitationData?.orgName\n      ? `Join ${invitationData.orgName}`\n      : \"Organization Invitation\");\n\n  const finalSubtitle =\n    subtitle ||\n    (invitationData?.inviterName\n      ? `${invitationData.inviterName} has invited you to join`\n      : \"You've been invited to join an organization\");\n\n  return (\n    <SignUpModal\n      {...props}\n      isOpen={isOpen}\n      onClose={() => setIsOpen(false)}\n      invitationToken={invitationToken}\n      organizationId={invitationData?.orgId}\n      title={finalTitle}\n      subtitle={finalSubtitle}\n      showBranding={true}\n      backdrop=\"blur\"\n      closeOnBackdropClick={false} // Require explicit close for invitations\n    />\n  );\n}\n\n// ============================================================================\n// Export\n// ============================================================================\n\nexport default SignUpModal;\n"],"names":["SignUpModal","isOpen","onClose","modalSize","closeOnBackdropClick","closeOnEscape","modalClassName","showCloseButton","methods","email","organizationId","invitationToken","redirectUrl","onSuccess","onError","title","subtitle","size","showBranding","disabled","requireTerms","termsUrl","privacyUrl","backdrop","placement","components","useConfig","CustomSignUpModal","jsx","handleSuccess","useCallback","result","handleClose","sizeProps","Modal","jsxs","Fragment","ModalHeader","Button","XMarkIcon","ModalBody","SignUpForm","useSignUpModal","setIsOpen","React","modalData","setModalData","open","data","close","toggle","prev"],"mappings":"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"}