{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "authentication",
  "title": "Authentication",
  "description": "A compact sign-in, verification, and account-recovery flow with no authentication backend assumptions.",
  "registryDependencies": [
    "@rivetui/alert",
    "@rivetui/button",
    "@rivetui/field",
    "@rivetui/input",
    "@rivetui/input-otp",
    "@rivetui/password-field"
  ],
  "files": [
    {
      "path": "registry/rivetui/blocks/authentication/authentication.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n  Alert,\n  AlertContent,\n  AlertDescription,\n  AlertTitle,\n} from \"@/registry/rivetui/components/alert/alert\";\nimport { Button } from \"@/registry/rivetui/components/button/button\";\nimport { Field, FieldLabel } from \"@/registry/rivetui/components/field/field\";\nimport { Input } from \"@/registry/rivetui/components/input/input\";\nimport {\n  InputOTP,\n  InputOTPGroup,\n  InputOTPSeparator,\n  InputOTPSlot,\n  REGEXP_ONLY_DIGITS,\n} from \"@/registry/rivetui/components/input-otp/input-otp\";\nimport { PasswordField } from \"@/registry/rivetui/components/password-field/password-field\";\n\ntype AuthenticationView = \"recovery\" | \"sign-in\" | \"verify\";\n\ntype AuthenticationProps = Omit<React.ComponentProps<\"section\">, \"onSubmit\"> & {\n  defaultView?: AuthenticationView;\n  onSubmit?: (view: AuthenticationView, formData: FormData) => void;\n  onViewChange?: (view: AuthenticationView) => void;\n};\n\nfunction Authentication({\n  className,\n  defaultView = \"sign-in\",\n  onSubmit,\n  onViewChange,\n  ...props\n}: AuthenticationProps) {\n  const [view, setView] = React.useState<AuthenticationView>(defaultView);\n\n  function changeView(nextView: AuthenticationView) {\n    setView(nextView);\n    onViewChange?.(nextView);\n  }\n\n  function handleSubmit(event: React.FormEvent<HTMLFormElement>) {\n    event.preventDefault();\n    onSubmit?.(view, new FormData(event.currentTarget));\n\n    if (view === \"sign-in\" && !onSubmit) {\n      changeView(\"verify\");\n    }\n  }\n\n  return (\n    <section\n      aria-labelledby=\"authentication-title\"\n      className={cn(\"w-full max-w-md border border-border bg-background\", className)}\n      {...props}\n    >\n      <header className=\"border-b border-border p-5 sm:p-6\">\n        <p className=\"font-mono text-[0.625rem] uppercase tracking-[0.14em] text-muted-foreground\">\n          Secure access\n        </p>\n        <h2 id=\"authentication-title\" className=\"mt-3 text-2xl font-semibold tracking-[-0.04em]\">\n          {view === \"sign-in\" ? \"Sign in\" : view === \"verify\" ? \"Verify access\" : \"Recover access\"}\n        </h2>\n        <p className=\"mt-2 text-sm leading-6 text-muted-foreground\">\n          {view === \"sign-in\"\n            ? \"Use your workspace credentials to continue.\"\n            : view === \"verify\"\n              ? \"Enter the six-digit code sent to your trusted device.\"\n              : \"We will send a recovery link to your account email.\"}\n        </p>\n      </header>\n\n      <form className=\"grid gap-5 p-5 sm:p-6\" onSubmit={handleSubmit}>\n        {view === \"sign-in\" ? (\n          <>\n            <Field>\n              <FieldLabel htmlFor=\"auth-email\">Email</FieldLabel>\n              <Input\n                id=\"auth-email\"\n                name=\"email\"\n                type=\"email\"\n                autoComplete=\"email\"\n                placeholder=\"you@company.com\"\n                required\n              />\n            </Field>\n            <Field>\n              <div className=\"flex items-center justify-between gap-4\">\n                <FieldLabel htmlFor=\"auth-password\">Password</FieldLabel>\n                <button\n                  type=\"button\"\n                  className=\"text-xs text-muted-foreground underline-offset-4 hover:text-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40\"\n                  onClick={() => changeView(\"recovery\")}\n                >\n                  Forgot password?\n                </button>\n              </div>\n              <PasswordField\n                id=\"auth-password\"\n                name=\"password\"\n                autoComplete=\"current-password\"\n                required\n              />\n            </Field>\n            <Button type=\"submit\" className=\"w-full\">\n              Continue\n            </Button>\n          </>\n        ) : null}\n\n        {view === \"verify\" ? (\n          <>\n            <Alert role=\"status\">\n              <AlertContent>\n                <AlertTitle>Code sent</AlertTitle>\n                <AlertDescription>Check your authenticator or trusted device.</AlertDescription>\n              </AlertContent>\n            </Alert>\n            <Field>\n              <FieldLabel htmlFor=\"auth-code\">Verification code</FieldLabel>\n              <InputOTP\n                id=\"auth-code\"\n                name=\"code\"\n                maxLength={6}\n                pattern={REGEXP_ONLY_DIGITS}\n                required\n              >\n                <InputOTPGroup>\n                  <InputOTPSlot index={0} />\n                  <InputOTPSlot index={1} />\n                  <InputOTPSlot index={2} />\n                </InputOTPGroup>\n                <InputOTPSeparator />\n                <InputOTPGroup>\n                  <InputOTPSlot index={3} />\n                  <InputOTPSlot index={4} />\n                  <InputOTPSlot index={5} />\n                </InputOTPGroup>\n              </InputOTP>\n            </Field>\n            <div className=\"grid gap-2 sm:grid-cols-2\">\n              <Button type=\"button\" variant=\"outline\" onClick={() => changeView(\"sign-in\")}>\n                Back\n              </Button>\n              <Button type=\"submit\">Verify</Button>\n            </div>\n          </>\n        ) : null}\n\n        {view === \"recovery\" ? (\n          <>\n            <Field>\n              <FieldLabel htmlFor=\"recovery-email\">Account email</FieldLabel>\n              <Input\n                id=\"recovery-email\"\n                name=\"email\"\n                type=\"email\"\n                autoComplete=\"email\"\n                placeholder=\"you@company.com\"\n                required\n              />\n            </Field>\n            <Alert variant=\"warning\" role=\"note\">\n              <AlertContent>\n                <AlertTitle>Recovery window</AlertTitle>\n                <AlertDescription>The recovery link expires after 20 minutes.</AlertDescription>\n              </AlertContent>\n            </Alert>\n            <div className=\"grid gap-2 sm:grid-cols-2\">\n              <Button type=\"button\" variant=\"outline\" onClick={() => changeView(\"sign-in\")}>\n                Back\n              </Button>\n              <Button type=\"submit\">Send recovery link</Button>\n            </div>\n          </>\n        ) : null}\n      </form>\n    </section>\n  );\n}\n\nexport type { AuthenticationProps, AuthenticationView };\nexport { Authentication };\n",
      "type": "registry:component",
      "target": "components/blocks/authentication.tsx"
    }
  ],
  "categories": [
    "authentication",
    "forms"
  ],
  "type": "registry:block"
}