{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "auth-template",
  "type": "registry:block",
  "title": "Auth Template",
  "description": "Full-page surface for sign-in / sign-up / password-reset / verify-email flows. Centred narrow column with brand mark at top, form in the middle, helper link at the bottom (\"Already have an account?\" / \"Forgot password?\").",
  "author": "ofri-peretz <https://github.com/ofri-peretz>",
  "categories": [
    "form",
    "template"
  ],
  "dependencies": [],
  "registryDependencies": [
    "https://ds.interlace.tools/r/theme.json",
    "https://ds.interlace.tools/r/cn.json",
    "https://ds.interlace.tools/r/container.json",
    "https://ds.interlace.tools/r/section-boundary.json",
    "https://ds.interlace.tools/r/skeleton.json",
    "https://ds.interlace.tools/r/stack.json",
    "https://ds.interlace.tools/r/typography.json"
  ],
  "files": [
    {
      "path": "registry/interlace-ui/templates/auth-template.tsx",
      "target": "components/ui/templates/auth-template.tsx",
      "type": "registry:block",
      "content": "import * as React from 'react';\n\n// @interlace/auth-template v1.1.0 — Interlace design system.\n// Docs, props and live preview: https://ds.interlace.tools/c/auth-template\n// What changed since: https://ds.interlace.tools/c/auth-template#history\n// Generated banner — keep it, the upgrade diff reads this version.\n\n/**\n * @interlace/ui — AuthTemplate\n *\n * Full-page surface for sign-in / sign-up / password-reset / verify-email\n * flows. Centred narrow column with brand mark at top, form in the middle,\n * helper link at the bottom (\"Already have an account?\" / \"Forgot password?\").\n *\n * One template, four variants — pick via the `variant` prop. The form\n * itself is consumer-supplied (most apps want a custom action / OAuth\n * row); the template wraps it in the canonical layout.\n *\n * ## MIN_VIEWPORT — 320\n *\n * ## Anatomy\n *\n *   <main data-slot=\"auth-template\" data-min-viewport=\"320\">\n *     <Container size=\"prose\">\n *       <SectionBoundary name=\"auth-header\">{logo} {title} {description}</SectionBoundary>\n *       <SectionBoundary name=\"auth-form\">{form}</SectionBoundary>\n *       <SectionBoundary name=\"auth-footer\">{footer}</SectionBoundary>\n *     </Container>\n *   </main>\n */\n\nimport { cn } from '@/lib/utils';\nimport { Container } from '@/components/ui/container';\nimport { SectionBoundary } from '@/components/ui/section-boundary';\nimport { Stack } from '@/components/ui/stack';\nimport { Typography } from '@/components/ui/typography';\nimport { Skeleton } from '@/components/ui/skeleton';\n\nexport const MIN_VIEWPORT = 320 as const;\n\ntype AuthVariant = 'signin' | 'signup' | 'reset' | 'verify';\n\ninterface AuthTemplateProps extends Omit<React.ComponentProps<'main'>, 'title'> {\n  /** Which auth flow this surface represents. Drives default copy. */\n  variant?: AuthVariant;\n  /** Brand mark / logo at the top of the page. */\n  logo?: React.ReactNode;\n  /**\n   * Page title. Default per `variant` (e.g. \"Sign in to your account\").\n   * Pass to override.\n   */\n  title?: React.ReactNode;\n  /** One-line description under the title. */\n  description?: React.ReactNode;\n  /** The auth form. Consumer-supplied. */\n  form: React.ReactNode;\n  /** Optional footer (e.g. \"Already have an account? Sign in\"). */\n  footer?: React.ReactNode;\n}\n\nconst DEFAULT_TITLE: Record<AuthVariant, string> = {\n  signin: 'Sign in to your account',\n  signup: 'Create your account',\n  reset: 'Reset your password',\n  verify: 'Verify your email',\n};\n\nfunction AuthTemplate({\n  variant = 'signin',\n  logo,\n  title,\n  description,\n  form,\n  footer,\n  className,\n  ...props\n}: AuthTemplateProps) {\n  return (\n    <main\n      data-slot=\"auth-template\"\n      data-min-viewport={String(MIN_VIEWPORT)}\n      data-variant={variant}\n      className={cn(\n        'bg-background flex min-h-screen items-center justify-center py-xl',\n        className,\n      )}\n      {...props}\n    >\n      <Container size=\"prose\">\n        <Stack gap=\"lg\">\n          <SectionBoundary name=\"auth-header\" skeletonVariant=\"page-header\">\n            <Stack gap=\"md\" align=\"center\">\n              {logo ? <div>{logo}</div> : null}\n              <Typography variant=\"h2\" as=\"h1\" className=\"text-center text-balance\">\n                {title ?? DEFAULT_TITLE[variant]}\n              </Typography>\n              {description ? (\n                <Typography\n                  variant=\"body\"\n                  tone=\"muted\"\n                  className=\"max-w-prose text-center\"\n                >\n                  {description}\n                </Typography>\n              ) : null}\n            </Stack>\n          </SectionBoundary>\n\n          <SectionBoundary name=\"auth-form\" skeletonVariant=\"newsletter-form\">\n            <div className=\"border-border bg-card rounded-lg border p-lg\">\n              {form}\n            </div>\n          </SectionBoundary>\n\n          {footer ? (\n            <SectionBoundary name=\"auth-footer\" skeletonVariant=\"text\">\n              <div className=\"text-muted-foreground text-center text-sm\">\n                {footer}\n              </div>\n            </SectionBoundary>\n          ) : null}\n        </Stack>\n      </Container>\n    </main>\n  );\n}\nAuthTemplate.displayName = 'AuthTemplate';\n\n/**\n * Page-level loading state — the full-page silhouette of\n * `<AuthTemplate>`, not a single rect. Rendered by the consumer while\n * the whole route's data is in flight (`loading.tsx` in Next.js), or as\n * a `<SectionBoundary skeleton={…}>` override.\n *\n * Shapes mirror the real layout so the swap is CLS-neutral (R23). One\n * `role=\"status\"` region for the page; inner skeletons pass\n * `label={null}` so screen readers hear one announcement, not ten.\n */\nfunction AuthTemplateSkeleton({\n  className,\n  ...props\n}: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"auth-template-skeleton\"\n      data-min-viewport={String(MIN_VIEWPORT)}\n      role=\"status\"\n      aria-busy=\"true\"\n      aria-label=\"Loading…\"\n      className={cn(\n        'bg-background flex min-h-screen items-center justify-center py-xl',\n        className,\n      )}\n      {...props}\n    >\n      <Container size=\"prose\">\n        <Stack gap=\"lg\">\n          <Skeleton variant=\"page-header\" label={null} />\n          <Skeleton variant=\"newsletter-form\" label={null} />\n          <Skeleton variant=\"text\" label={null} />\n        </Stack>\n      </Container>\n    </div>\n  );\n}\nAuthTemplateSkeleton.displayName = 'AuthTemplateSkeleton';\nAuthTemplate.Skeleton = AuthTemplateSkeleton;\n\nexport { AuthTemplate };\nexport type { AuthTemplateProps, AuthVariant };\n"
    }
  ],
  "meta": {
    "tier": "template",
    "client": false,
    "minViewport": 320,
    "loading": false,
    "version": "1.1.0",
    "since": "1.0.0"
  },
  "docs": "## @interlace/auth-template\n\nInstalled to `components/ui/templates/auth-template.tsx`.\n\n```tsx\nimport { /* … */ } from '@/components/ui/templates/auth-template';\n```\n\nProps, a11y contract, live preview and source: https://ds.interlace.tools/c/auth-template\n\nRequires the `@interlace/theme` CSS baseline (installed automatically as a registry dependency)."
}
