{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "unlock-dialog",
  "title": "Unlock Dialog",
  "description": "A non-dismissable modal PIN prompt — no backdrop click, no Escape-to-close. Composable standalone, or used by Protected Modal.",
  "registryDependencies": [
    "https://knock.codes/r/react/pin-input.json",
    "https://knock.codes/r/react/knock-codes-types.json"
  ],
  "files": [
    {
      "path": "packages/react/UnlockDialog.tsx",
      "content": "\"use client\";\r\n\r\nimport { useId, type ReactNode } from \"react\";\r\nimport { PinInput } from \"./PinInput.tsx\";\r\nimport { DEFAULT_LABELS, type KnockCodesError, type KnockCodesLabels } from \"./types.ts\";\r\n\r\nexport interface UnlockDialogProps {\r\n  open: boolean;\r\n  value: string;\r\n  onChange: (value: string) => void;\r\n  onSubmit: () => void;\r\n  submitting: boolean;\r\n  error: KnockCodesError | null;\r\n  labels?: KnockCodesLabels;\r\n  autoFocus?: boolean;\r\n  /** Extra content under the form, e.g. help text or a support link. */\r\n  footer?: ReactNode;\r\n}\r\n\r\n/**\r\n * The modal shell `<ProtectedModal>` renders — also usable standalone when\r\n * you want to trigger an unlock prompt from your own button or menu item\r\n * instead of gating content directly. Deliberately not dismissable (no\r\n * backdrop click, no Escape-to-close): the point of a gate is that closing\r\n * the dialog can't be how you get past it.\r\n */\r\nexport function UnlockDialog({ open, value, onChange, onSubmit, submitting, error, labels, autoFocus = true, footer }: UnlockDialogProps) {\r\n  const merged = { ...DEFAULT_LABELS, ...labels };\r\n  const headingId = useId();\r\n\r\n  if (!open) return null;\r\n\r\n  return (\r\n    <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\">\r\n      <div\r\n        role=\"dialog\"\r\n        aria-modal=\"true\"\r\n        aria-labelledby={headingId}\r\n        className=\"w-full max-w-sm space-y-4 rounded-lg border border-gray-200 bg-white p-6 shadow-lg outline-none dark:border-gray-800 dark:bg-gray-950\"\r\n      >\r\n        <h2 id={headingId} className=\"text-lg font-semibold text-gray-900 dark:text-gray-50\">\r\n          {merged.heading}\r\n        </h2>\r\n        <PinInput\r\n          value={value}\r\n          onChange={onChange}\r\n          onSubmit={onSubmit}\r\n          submitting={submitting}\r\n          error={error}\r\n          labels={labels}\r\n          autoFocus={autoFocus}\r\n        />\r\n        {footer}\r\n      </div>\r\n    </div>\r\n  );\r\n}\r\n",
      "type": "registry:file",
      "target": "components/knock-codes/react/UnlockDialog.tsx"
    }
  ],
  "type": "registry:block"
}