{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "settings-sso",
  "title": "Settings SSO",
  "description": "Configure SSO providers for your organization.",
  "registryDependencies": [
    "alert-dialog",
    "badge",
    "button",
    "card",
    "dialog",
    "field",
    "input-group",
    "select",
    "switch",
    "textarea"
  ],
  "files": [
    {
      "path": "registry/new-york/blocks/settings/settings-sso.tsx",
      "content": "\"use client\";\n\nimport {\n  Check,\n  Copy,\n  Lock,\n  RefreshCw,\n  TestTube,\n  Trash2,\n  Users,\n} from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  AlertDialog,\n  AlertDialogAction,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogTitle,\n  AlertDialogTrigger,\n} from \"@/registry/new-york/ui/alert-dialog\";\nimport { Badge } from \"@/registry/new-york/ui/badge\";\nimport { Button } from \"@/registry/new-york/ui/button\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/registry/new-york/ui/card\";\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from \"@/registry/new-york/ui/dialog\";\nimport {\n  Field,\n  FieldContent,\n  FieldDescription,\n  FieldError,\n  FieldLabel,\n} from \"@/registry/new-york/ui/field\";\nimport {\n  InputGroup,\n  InputGroupInput,\n} from \"@/registry/new-york/ui/input-group\";\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"@/registry/new-york/ui/select\";\nimport { Switch } from \"@/registry/new-york/ui/switch\";\nimport { Textarea } from \"@/registry/new-york/ui/textarea\";\n\nexport interface SSOProvider {\n  id: string;\n  name: string;\n  type: \"saml\" | \"oauth\" | \"oidc\";\n  enabled: boolean;\n  status: \"active\" | \"error\" | \"pending\";\n  metadataUrl?: string;\n  entityId?: string;\n  ssoUrl?: string;\n  certificate?: string;\n  lastTested?: Date;\n  userCount?: number;\n}\n\nexport interface SettingsSSOProps {\n  providers?: SSOProvider[];\n  enabled?: boolean;\n  onCreate?: (data: {\n    name: string;\n    type: \"saml\" | \"oauth\" | \"oidc\";\n    metadataUrl?: string;\n    entityId?: string;\n    ssoUrl?: string;\n    certificate?: string;\n  }) => Promise<SSOProvider>;\n  onUpdate?: (id: string, data: Partial<SSOProvider>) => Promise<void>;\n  onDelete?: (id: string) => Promise<void>;\n  onTest?: (id: string) => Promise<void>;\n  onToggle?: (enabled: boolean) => Promise<void>;\n  className?: string;\n}\n\nfunction formatDate(date: Date): string {\n  return new Intl.DateTimeFormat(\"en-US\", {\n    month: \"short\",\n    day: \"numeric\",\n    year: \"numeric\",\n    hour: \"numeric\",\n    minute: \"2-digit\",\n  }).format(date);\n}\n\nexport default function SettingsSSO({\n  providers = [],\n  enabled = false,\n  onCreate,\n  onUpdate,\n  onDelete,\n  onTest,\n  onToggle,\n  className,\n}: SettingsSSOProps) {\n  const [createDialogOpen, setCreateDialogOpen] = useState(false);\n  const [errors, setErrors] = useState<Record<string, string>>({});\n  const [copiedText, setCopiedText] = useState<string | null>(null);\n\n  const [providerData, setProviderData] = useState({\n    name: \"\",\n    type: \"saml\" as \"saml\" | \"oauth\" | \"oidc\",\n    metadataUrl: \"\",\n    entityId: \"\",\n    ssoUrl: \"\",\n    certificate: \"\",\n  });\n\n  const handleCreate = async () => {\n    setErrors({});\n\n    if (!providerData.name.trim()) {\n      setErrors({ name: \"Name is required\" });\n      return;\n    }\n\n    try {\n      await onCreate?.(providerData);\n      setProviderData({\n        name: \"\",\n        type: \"saml\",\n        metadataUrl: \"\",\n        entityId: \"\",\n        ssoUrl: \"\",\n        certificate: \"\",\n      });\n      setCreateDialogOpen(false);\n    } catch (error) {\n      setErrors({\n        _general:\n          error instanceof Error\n            ? error.message\n            : \"Failed to create SSO provider\",\n      });\n    }\n  };\n\n  const copyToClipboard = async (text: string) => {\n    await navigator.clipboard.writeText(text);\n    setCopiedText(text);\n    setTimeout(() => setCopiedText(null), 2000);\n  };\n\n  const getStatusBadge = (status: SSOProvider[\"status\"]) => {\n    switch (status) {\n      case \"active\":\n        return (\n          <Badge className=\"flex items-center gap-1 text-xs\" variant=\"default\">\n            <Check className=\"size-3\" />\n            <span>Active</span>\n          </Badge>\n        );\n      case \"error\":\n        return (\n          <Badge className=\"text-xs\" variant=\"destructive\">\n            Error\n          </Badge>\n        );\n      case \"pending\":\n        return (\n          <Badge className=\"text-xs\" variant=\"secondary\">\n            Pending\n          </Badge>\n        );\n    }\n  };\n\n  return (\n    <Card className={cn(\"w-full shadow-xs\", className)}>\n      <CardHeader>\n        <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n          <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n            <CardTitle className=\"wrap-break-word\">Single Sign-On</CardTitle>\n            <CardDescription className=\"wrap-break-word\">\n              Configure SSO providers for your organization\n            </CardDescription>\n          </div>\n          <div className=\"flex flex-col gap-3 sm:shrink-0 sm:flex-row sm:items-center\">\n            <div className=\"flex items-center gap-2\">\n              <FieldLabel className=\"mb-0\" htmlFor=\"sso-enabled\">\n                Enable SSO\n              </FieldLabel>\n              <Switch\n                checked={enabled}\n                id=\"sso-enabled\"\n                onCheckedChange={(checked) => onToggle?.(checked)}\n              />\n            </div>\n            <Dialog onOpenChange={setCreateDialogOpen} open={createDialogOpen}>\n              <DialogTrigger asChild>\n                <Button className=\"w-full sm:w-auto sm:shrink-0\" type=\"button\">\n                  <Lock className=\"size-4\" />\n                  <span className=\"whitespace-nowrap\">Add Provider</span>\n                </Button>\n              </DialogTrigger>\n              <DialogContent className=\"sm:max-w-lg\">\n                <DialogHeader>\n                  <DialogTitle>Add SSO Provider</DialogTitle>\n                  <DialogDescription>\n                    Configure a new SSO provider for authentication\n                  </DialogDescription>\n                </DialogHeader>\n                <div className=\"flex flex-col gap-4\">\n                  {errors._general && (\n                    <div className=\"rounded-lg border border-destructive/50 bg-destructive/10 p-3\">\n                      <p className=\"text-destructive text-sm\">\n                        {errors._general}\n                      </p>\n                    </div>\n                  )}\n\n                  <Field>\n                    <FieldLabel htmlFor=\"provider-name\">\n                      Provider Name <span className=\"text-destructive\">*</span>\n                    </FieldLabel>\n                    <FieldContent>\n                      <InputGroup>\n                        <InputGroupInput\n                          id=\"provider-name\"\n                          onChange={(e) =>\n                            setProviderData((prev) => ({\n                              ...prev,\n                              name: e.target.value,\n                            }))\n                          }\n                          placeholder=\"Okta, Azure AD, etc.\"\n                          value={providerData.name}\n                        />\n                      </InputGroup>\n                      {errors.name && <FieldError>{errors.name}</FieldError>}\n                    </FieldContent>\n                  </Field>\n\n                  <Field>\n                    <FieldLabel htmlFor=\"provider-type\">\n                      Provider Type <span className=\"text-destructive\">*</span>\n                    </FieldLabel>\n                    <FieldContent>\n                      <Select\n                        onValueChange={(value: \"saml\" | \"oauth\" | \"oidc\") =>\n                          setProviderData((prev) => ({ ...prev, type: value }))\n                        }\n                        value={providerData.type}\n                      >\n                        <SelectTrigger id=\"provider-type\">\n                          <SelectValue />\n                        </SelectTrigger>\n                        <SelectContent>\n                          <SelectItem value=\"saml\">SAML 2.0</SelectItem>\n                          <SelectItem value=\"oauth\">OAuth 2.0</SelectItem>\n                          <SelectItem value=\"oidc\">OpenID Connect</SelectItem>\n                        </SelectContent>\n                      </Select>\n                    </FieldContent>\n                  </Field>\n\n                  {providerData.type === \"saml\" && (\n                    <>\n                      <Field>\n                        <FieldLabel htmlFor=\"metadata-url\">\n                          Metadata URL\n                        </FieldLabel>\n                        <FieldContent>\n                          <InputGroup>\n                            <InputGroupInput\n                              id=\"metadata-url\"\n                              onChange={(e) =>\n                                setProviderData((prev) => ({\n                                  ...prev,\n                                  metadataUrl: e.target.value,\n                                }))\n                              }\n                              placeholder=\"https://example.com/saml/metadata\"\n                              type=\"url\"\n                              value={providerData.metadataUrl}\n                            />\n                          </InputGroup>\n                          <FieldDescription>\n                            Or manually configure the fields below\n                          </FieldDescription>\n                        </FieldContent>\n                      </Field>\n\n                      <Field>\n                        <FieldLabel htmlFor=\"entity-id\">Entity ID</FieldLabel>\n                        <FieldContent>\n                          <InputGroup>\n                            <InputGroupInput\n                              id=\"entity-id\"\n                              onChange={(e) =>\n                                setProviderData((prev) => ({\n                                  ...prev,\n                                  entityId: e.target.value,\n                                }))\n                              }\n                              placeholder=\"https://example.com/saml\"\n                              value={providerData.entityId}\n                            />\n                          </InputGroup>\n                        </FieldContent>\n                      </Field>\n\n                      <Field>\n                        <FieldLabel htmlFor=\"sso-url\">SSO URL</FieldLabel>\n                        <FieldContent>\n                          <InputGroup>\n                            <InputGroupInput\n                              id=\"sso-url\"\n                              onChange={(e) =>\n                                setProviderData((prev) => ({\n                                  ...prev,\n                                  ssoUrl: e.target.value,\n                                }))\n                              }\n                              placeholder=\"https://example.com/saml/sso\"\n                              type=\"url\"\n                              value={providerData.ssoUrl}\n                            />\n                          </InputGroup>\n                        </FieldContent>\n                      </Field>\n\n                      <Field>\n                        <FieldLabel htmlFor=\"certificate\">\n                          Certificate\n                        </FieldLabel>\n                        <FieldContent>\n                          <Textarea\n                            id=\"certificate\"\n                            onChange={(e) =>\n                              setProviderData((prev) => ({\n                                ...prev,\n                                certificate: e.target.value,\n                              }))\n                            }\n                            placeholder=\"Paste your SAML certificate here...\"\n                            rows={4}\n                            value={providerData.certificate}\n                          />\n                        </FieldContent>\n                      </Field>\n                    </>\n                  )}\n                </div>\n                <DialogFooter>\n                  <Button\n                    onClick={() => setCreateDialogOpen(false)}\n                    type=\"button\"\n                    variant=\"outline\"\n                  >\n                    Cancel\n                  </Button>\n                  <Button onClick={handleCreate} type=\"button\">\n                    Create Provider\n                  </Button>\n                </DialogFooter>\n              </DialogContent>\n            </Dialog>\n          </div>\n        </div>\n      </CardHeader>\n      <CardContent>\n        {providers.length === 0 ? (\n          <div className=\"flex flex-col items-center justify-center gap-4 py-12 text-center\">\n            <div className=\"flex size-12 items-center justify-center rounded-full bg-muted\">\n              <Lock className=\"size-6 text-muted-foreground\" />\n            </div>\n            <div className=\"flex flex-col gap-2\">\n              <p className=\"font-medium text-sm\">No SSO providers</p>\n              <p className=\"text-muted-foreground text-sm\">\n                Add an SSO provider to enable single sign-on\n              </p>\n            </div>\n          </div>\n        ) : (\n          <div className=\"flex flex-col gap-4\">\n            {providers.map((provider) => (\n              <div\n                className=\"flex flex-col gap-4 rounded-lg border p-4\"\n                key={provider.id}\n              >\n                {/* Header */}\n                <div className=\"flex flex-wrap items-center gap-3\">\n                  <div className=\"flex flex-wrap items-center gap-2\">\n                    <h4 className=\"font-medium text-sm\">{provider.name}</h4>\n                    {getStatusBadge(provider.status)}\n                    <Badge className=\"text-xs uppercase\" variant=\"outline\">\n                      {provider.type}\n                    </Badge>\n                  </div>\n                  <div className=\"ml-auto flex shrink-0 flex-wrap gap-2\">\n                    <Button\n                      className=\"w-full sm:w-auto\"\n                      onClick={() => onTest?.(provider.id)}\n                      type=\"button\"\n                      variant=\"outline\"\n                    >\n                      <div className=\"flex items-center gap-2\">\n                        <TestTube className=\"size-4\" />\n                        <span>Test Connection</span>\n                      </div>\n                    </Button>\n                    <Button\n                      className=\"w-full sm:w-auto\"\n                      onClick={() =>\n                        onUpdate?.(provider.id, { enabled: !provider.enabled })\n                      }\n                      type=\"button\"\n                      variant=\"outline\"\n                    >\n                      {provider.enabled ? (\n                        <div className=\"flex items-center gap-2\">\n                          <Check className=\"size-4\" />\n                          <span>Enabled</span>\n                        </div>\n                      ) : (\n                        <div className=\"flex items-center gap-2\">\n                          <RefreshCw className=\"size-4\" />\n                          <span>Enable</span>\n                        </div>\n                      )}\n                    </Button>\n                    <AlertDialog>\n                      <AlertDialogTrigger asChild>\n                        <Button\n                          className=\"w-full sm:w-auto\"\n                          type=\"button\"\n                          variant=\"destructive\"\n                        >\n                          <div className=\"flex items-center gap-2\">\n                            <Trash2 className=\"size-4\" />\n                            <span>Delete</span>\n                          </div>\n                        </Button>\n                      </AlertDialogTrigger>\n                      <AlertDialogContent>\n                        <AlertDialogHeader>\n                          <AlertDialogTitle>\n                            Delete SSO Provider?\n                          </AlertDialogTitle>\n                          <AlertDialogDescription>\n                            This will permanently delete the SSO provider{\" \"}\n                            <strong>{provider.name}</strong>. This action cannot\n                            be undone.\n                          </AlertDialogDescription>\n                        </AlertDialogHeader>\n                        <AlertDialogFooter>\n                          <AlertDialogCancel>Cancel</AlertDialogCancel>\n                          <AlertDialogAction\n                            onClick={() => onDelete?.(provider.id)}\n                          >\n                            Delete Provider\n                          </AlertDialogAction>\n                        </AlertDialogFooter>\n                      </AlertDialogContent>\n                    </AlertDialog>\n                  </div>\n                </div>\n\n                {/* Main Content */}\n                <div className=\"flex flex-col gap-4\">\n                  {/* Metadata URL */}\n                  {provider.metadataUrl && (\n                    <div className=\"flex flex-col gap-3 rounded-lg border bg-muted/30 p-4\">\n                      <Field>\n                        <FieldLabel className=\"mb-0\">Metadata URL</FieldLabel>\n                        <FieldContent>\n                          <div className=\"flex items-center gap-2\">\n                            <code className=\"flex-1 break-all rounded bg-background px-3 py-2 font-mono text-xs\">\n                              {provider.metadataUrl}\n                            </code>\n                            <Button\n                              aria-label=\"Copy metadata URL\"\n                              onClick={() =>\n                                copyToClipboard(provider.metadataUrl!)\n                              }\n                              size=\"icon-sm\"\n                              type=\"button\"\n                              variant=\"ghost\"\n                            >\n                              {copiedText === provider.metadataUrl ? (\n                                <Check className=\"size-4 text-green-600\" />\n                              ) : (\n                                <Copy className=\"size-4\" />\n                              )}\n                            </Button>\n                          </div>\n                        </FieldContent>\n                      </Field>\n                    </div>\n                  )}\n\n                  {/* Metadata */}\n                  <div className=\"flex flex-wrap items-center gap-3 text-muted-foreground text-xs\">\n                    {provider.userCount !== undefined && (\n                      <>\n                        <span className=\"flex items-center gap-1\">\n                          <Users className=\"size-3\" />\n                          {provider.userCount} users\n                        </span>\n                        <span>•</span>\n                      </>\n                    )}\n                    {provider.lastTested && (\n                      <span>\n                        Last tested: {formatDate(provider.lastTested)}\n                      </span>\n                    )}\n                  </div>\n                </div>\n              </div>\n            ))}\n          </div>\n        )}\n      </CardContent>\n    </Card>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "block",
    "settings"
  ],
  "type": "registry:ui"
}