{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "login-page", "title": "Login Page", "description": "A composable login page with customizable regions, form modes, social providers, hero, and secure footer links", "dependencies": ["daisyui", "lucide-react", "react-hook-form"], "files": [ { "path": "registry/default/blocks/login-page/login-page.tsx", "content": "import { Children, type ComponentPropsWithRef, type ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\nimport {\n\tLoginPageForm,\n\ttype LoginPageFormIcons,\n\ttype LoginPageFormLabels,\n\ttype LoginPageFormMode,\n\ttype LoginPageFormProps,\n\ttype LoginPageFormValues,\n} from './login-form';\nimport { type LoginPageSocialItem, LoginPageSocialLogin, type LoginPageSocialLoginProps } from './login-social';\n\nexport const LOGIN_PAGE_BEIAN_URL = 'https://beian.miit.gov.cn/';\n\nexport type LoginPageLinkProps = {\n\ttext?: ReactNode;\n\turl?: string;\n};\n\nexport type LoginPageFooterLinks = {\n\tbeian?: LoginPageLinkProps;\n\tlinks?: readonly LoginPageLinkProps[];\n\tpolicy?: LoginPageLinkProps;\n\tterms?: LoginPageLinkProps;\n};\n\nexport type LoginPageLayoutProps = Omit, 'content'> & {\n\tcontent?: ReactNode;\n\tfooter?: ReactNode;\n\theader?: ReactNode;\n\thero?: ReactNode;\n};\n\nexport type LoginPageHeaderLabels = {\n\tregisterAction?: ReactNode;\n\tregisterPrompt?: ReactNode;\n};\n\nexport type LoginPageHeaderProps = Omit, 'title'> & {\n\tactions?: ReactNode;\n\theadingId?: string;\n\tlabels?: LoginPageHeaderLabels;\n\tlogo?: ReactNode;\n\tonRegister?: () => void;\n\tsubtitle?: ReactNode;\n\ttitle?: ReactNode;\n};\n\nexport type LoginPageFooterProps = ComponentPropsWithRef<'footer'> &\n\tLoginPageFooterLinks & {\n\t\tcopyright?: ReactNode;\n\t\tseparator?: ReactNode;\n\t};\n\nexport type LoginPageHeroProps = ComponentPropsWithRef<'aside'>;\n\nexport type LoginPageCompositeProps = Omit, 'content' | 'onSubmit' | 'title'> & {\n\tcontent?: ReactNode;\n\tdefaultValues?: Partial;\n\tdisabled?: boolean;\n\tfooter?: ReactNode;\n\tfooterLinks?: LoginPageFooterLinks;\n\tform?: ReactNode;\n\tformIcons?: LoginPageFormIcons;\n\tformLabels?: LoginPageFormLabels;\n\tformMode?: LoginPageFormMode;\n\theader?: ReactNode;\n\theaderLabels?: LoginPageHeaderLabels;\n\theadingId?: string;\n\thero?: ReactNode;\n\tlogo?: ReactNode;\n\tonForgotPassword?: () => void;\n\tonRegister?: () => void;\n\tonSubmit?: LoginPageFormProps['onSubmit'];\n\torgValue?: string;\n\tshowOrg?: boolean;\n\tshowPasswordToggle?: boolean;\n\tshowRemember?: boolean;\n\tsocial?: ReactNode;\n\tsocialColumns?: LoginPageSocialLoginProps['columns'];\n\tsocialTitle?: ReactNode;\n\tsocials?: readonly LoginPageSocialItem[];\n\tsubtitle?: ReactNode;\n\ttitle?: ReactNode;\n};\n\nexport function LoginPageComposite({\n\tchildren,\n\tclassName,\n\tcontent,\n\tdefaultValues,\n\tdisabled,\n\tfooter,\n\tfooterLinks,\n\tform,\n\tformIcons,\n\tformLabels,\n\tformMode,\n\theader,\n\theaderLabels,\n\theadingId,\n\thero,\n\tlogo,\n\tonForgotPassword,\n\tonRegister,\n\tonSubmit,\n\torgValue,\n\tshowOrg,\n\tshowPasswordToggle,\n\tshowRemember,\n\tsocial,\n\tsocialColumns,\n\tsocialTitle,\n\tsocials,\n\tsubtitle = '登录系统',\n\ttitle,\n\t...props\n}: LoginPageCompositeProps) {\n\tconst headerContent =\n\t\theader === undefined ? (\n\t\t\t\n\t\t) : (\n\t\t\theader\n\t\t);\n\tconst formContent =\n\t\tform === undefined ? (\n\t\t\t\n\t\t) : (\n\t\t\tform\n\t\t);\n\tconst socialContent =\n\t\tsocial === undefined ? (\n\t\t\t\n\t\t) : (\n\t\t\tsocial\n\t\t);\n\tconst contentNode =\n\t\tcontent === undefined ? (\n\t\t\t<>\n\t\t\t\t{formContent}\n\t\t\t\t{socialContent}\n\t\t\t\t{children}\n\t\t\t\n\t\t) : (\n\t\t\tcontent\n\t\t);\n\tconst footerContent =\n\t\tfooter === undefined ? (\n\t\t\t\n\t\t) : (\n\t\t\t(footer ?? undefined)\n\t\t);\n\n\treturn (\n\t\t\n\t);\n}\n\nexport function LoginPageLayout({\n\theader,\n\tchildren,\n\tcontent,\n\thero,\n\tfooter,\n\tclassName,\n\t...props\n}: LoginPageLayoutProps) {\n\treturn (\n\t\t
\n\t\t\t\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t{header}\n\t\t\t\t\t\t{content}\n\t\t\t\t\t\t{children}\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t{footer !== undefined ? (\n\t\t\t\t\t
\n\t\t\t\t\t\t{footer}\n\t\t\t\t\t
\n\t\t\t\t) : null}\n\t\t\t
\n\t\t\t{hero ? {hero} : null}\n\t\t\n\t);\n}\n\nexport function LoginPageHeader({\n\tactions,\n\theadingId,\n\tlabels,\n\tlogo,\n\tonRegister,\n\tsubtitle,\n\ttitle,\n\tclassName,\n\t...props\n}: LoginPageHeaderProps) {\n\treturn (\n\t\t
\n\t\t\t
\n\t\t\t\t{logo ? {logo} : null}\n\t\t\t\t{title ?
{title}
: null}\n\t\t\t\t{actions}\n\t\t\t
\n\t\t\t{subtitle ? (\n\t\t\t\t

\n\t\t\t\t\t{subtitle}\n\t\t\t\t

\n\t\t\t) : null}\n\t\t\t{onRegister ? (\n\t\t\t\t

\n\t\t\t\t\t{labels?.registerPrompt ?? '尚未加入?'}{' '}\n\t\t\t\t\t\n\t\t\t\t

\n\t\t\t) : null}\n\t\t
\n\t);\n}\n\nexport function LoginPageFooter({\n\tbeian,\n\tcopyright,\n\tlinks,\n\tpolicy,\n\tseparator = ,\n\tterms,\n\tclassName,\n\t...props\n}: LoginPageFooterProps) {\n\tconst items: ReactNode[] = [copyright === undefined ? `© ${new Date().getFullYear()}` : copyright];\n\tconst policyLink = renderLoginPageLink(policy, '隐私政策');\n\tconst termsLink = renderLoginPageLink(terms, '服务条款');\n\tif (policyLink) items.push(policyLink);\n\tif (termsLink) items.push(termsLink);\n\tfor (const link of links ?? []) {\n\t\tconst item = renderLoginPageLink(link);\n\t\tif (item) items.push(item);\n\t}\n\tconst beianLink = renderLoginPageLink(beian?.text ? { ...beian, url: beian.url ?? LOGIN_PAGE_BEIAN_URL } : undefined);\n\tif (beianLink) items.push(beianLink);\n\tconst visibleItems = items.filter((item) => item !== null && item !== undefined && item !== false);\n\tconst separatorNode = {separator};\n\n\treturn (\n\t\t\n\t\t\t{Children.toArray(visibleItems.flatMap((item) => [separatorNode, item]).slice(1))}\n\t\t\n\t);\n}\n\nexport function LoginPageHero({ className, ...props }: LoginPageHeroProps) {\n\treturn (\n\t\t